]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
lib: Replace prefix2str for JSON to %pFX
[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))
2d02e34e 2061 || (!reflect && !transparent
c728d027
DA
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) {
8736 json_nexthop_global = json_object_new_object();
8737
c949c771
DA
8738 json_object_string_addf(json_nexthop_global, "ip",
8739 "%pI4", &attr->nexthop);
515c2602 8740
939a97f4 8741 if (path->peer->hostname)
515c2602
DA
8742 json_object_string_add(json_nexthop_global,
8743 "hostname",
939a97f4 8744 path->peer->hostname);
515c2602 8745
a4d82a8a
PZ
8746 json_object_string_add(json_nexthop_global, "afi",
8747 "ipv4");
445c2480
DS
8748 json_object_boolean_true_add(json_nexthop_global,
8749 "used");
aef999a2
DA
8750 } else {
8751 if (nexthop_hostname)
8752 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8753 nexthop_hostname, vrf_id_str);
8754 else
8755 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8756 vrf_id_str);
8757
ae248832 8758 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8759 if (len < 1)
8760 vty_out(vty, "\n%*s", 36, " ");
8761 else
8762 vty_out(vty, "%*s", len, " ");
8763 }
d33fc23b 8764 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8765 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8766 if (json_paths) {
8767 json_nexthop_global = json_object_new_object();
515c2602 8768
026b914a
PG
8769 json_object_string_add(json_nexthop_global,
8770 "afi", "ipv4");
c949c771
DA
8771 json_object_string_addf(json_nexthop_global,
8772 "ip", "%pI4",
8773 &attr->nexthop);
515c2602 8774
939a97f4 8775 if (path->peer->hostname)
515c2602
DA
8776 json_object_string_add(
8777 json_nexthop_global, "hostname",
939a97f4 8778 path->peer->hostname);
515c2602 8779
50e05855
AD
8780 json_object_boolean_true_add(
8781 json_nexthop_global,
026b914a
PG
8782 "used");
8783 } else {
aef999a2
DA
8784 if (nexthop_hostname)
8785 len = vty_out(vty, "%pI4(%s)%s",
8786 &attr->nexthop,
8787 nexthop_hostname,
8788 vrf_id_str);
8789 else
8790 len = vty_out(vty, "%pI4%s",
8791 &attr->nexthop,
8792 vrf_id_str);
8793
ae248832 8794 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8795 if (len < 1)
8796 vty_out(vty, "\n%*s", 36, " ");
8797 else
8798 vty_out(vty, "%*s", len, " ");
026b914a
PG
8799 }
8800 }
d33fc23b 8801 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8802 if (json_paths) {
8803 json_nexthop_global = json_object_new_object();
d62a17ae 8804
c949c771
DA
8805 json_object_string_addf(json_nexthop_global, "ip",
8806 "%pI4", &attr->nexthop);
515c2602 8807
939a97f4 8808 if (path->peer->hostname)
515c2602
DA
8809 json_object_string_add(json_nexthop_global,
8810 "hostname",
939a97f4 8811 path->peer->hostname);
445c2480 8812
a4d82a8a
PZ
8813 json_object_string_add(json_nexthop_global, "afi",
8814 "ipv4");
445c2480
DS
8815 json_object_boolean_true_add(json_nexthop_global,
8816 "used");
8817 } else {
aef999a2
DA
8818 if (nexthop_hostname)
8819 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8820 nexthop_hostname, vrf_id_str);
8821 else
8822 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8823 vrf_id_str);
9df8b37c 8824
ae248832 8825 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8826 if (len < 1)
8827 vty_out(vty, "\n%*s", 36, " ");
8828 else
8829 vty_out(vty, "%*s", len, " ");
d62a17ae 8830 }
445c2480 8831 }
b05a1c8b 8832
445c2480 8833 /* IPv6 Next Hop */
a4d82a8a 8834 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8835 if (json_paths) {
8836 json_nexthop_global = json_object_new_object();
c949c771
DA
8837 json_object_string_addf(json_nexthop_global, "ip",
8838 "%pI6",
8839 &attr->mp_nexthop_global);
515c2602 8840
939a97f4 8841 if (path->peer->hostname)
515c2602
DA
8842 json_object_string_add(json_nexthop_global,
8843 "hostname",
939a97f4 8844 path->peer->hostname);
515c2602 8845
a4d82a8a
PZ
8846 json_object_string_add(json_nexthop_global, "afi",
8847 "ipv6");
8848 json_object_string_add(json_nexthop_global, "scope",
8849 "global");
445c2480
DS
8850
8851 /* We display both LL & GL if both have been
8852 * received */
0606039c
DA
8853 if ((attr->mp_nexthop_len
8854 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8855 || (path->peer->conf_if)) {
a4d82a8a 8856 json_nexthop_ll = json_object_new_object();
c949c771
DA
8857 json_object_string_addf(
8858 json_nexthop_ll, "ip", "%pI6",
8859 &attr->mp_nexthop_local);
515c2602 8860
939a97f4 8861 if (path->peer->hostname)
515c2602
DA
8862 json_object_string_add(
8863 json_nexthop_ll, "hostname",
939a97f4 8864 path->peer->hostname);
515c2602 8865
a4d82a8a
PZ
8866 json_object_string_add(json_nexthop_ll, "afi",
8867 "ipv6");
8868 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8869 "link-local");
d62a17ae 8870
a4d82a8a
PZ
8871 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8872 &attr->mp_nexthop_local)
445c2480
DS
8873 != 0)
8874 && !attr->mp_nexthop_prefer_global)
d62a17ae 8875 json_object_boolean_true_add(
a4d82a8a 8876 json_nexthop_ll, "used");
445c2480
DS
8877 else
8878 json_object_boolean_true_add(
a4d82a8a 8879 json_nexthop_global, "used");
445c2480
DS
8880 } else
8881 json_object_boolean_true_add(
8882 json_nexthop_global, "used");
8883 } else {
8884 /* Display LL if LL/Global both in table unless
8885 * prefer-global is set */
0606039c
DA
8886 if (((attr->mp_nexthop_len
8887 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8888 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8889 || (path->peer->conf_if)) {
8890 if (path->peer->conf_if) {
a4d82a8a 8891 len = vty_out(vty, "%s",
9b6d8fcf 8892 path->peer->conf_if);
ae248832
MK
8893 /* len of IPv6 addr + max len of def
8894 * ifname */
8895 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8896
8897 if (len < 1)
a4d82a8a 8898 vty_out(vty, "\n%*s", 36, " ");
445c2480 8899 else
a4d82a8a 8900 vty_out(vty, "%*s", len, " ");
d62a17ae 8901 } else {
aef999a2
DA
8902 if (nexthop_hostname)
8903 len = vty_out(
8904 vty, "%pI6(%s)%s",
8905 &attr->mp_nexthop_local,
8906 nexthop_hostname,
8907 vrf_id_str);
8908 else
8909 len = vty_out(
8910 vty, "%pI6%s",
8911 &attr->mp_nexthop_local,
8912 vrf_id_str);
8913
ae248832 8914 len = wide ? (41 - len) : (16 - len);
d62a17ae 8915
8916 if (len < 1)
a4d82a8a 8917 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8918 else
a4d82a8a 8919 vty_out(vty, "%*s", len, " ");
d62a17ae 8920 }
445c2480 8921 } else {
aef999a2
DA
8922 if (nexthop_hostname)
8923 len = vty_out(vty, "%pI6(%s)%s",
8924 &attr->mp_nexthop_global,
8925 nexthop_hostname,
8926 vrf_id_str);
8927 else
8928 len = vty_out(vty, "%pI6%s",
8929 &attr->mp_nexthop_global,
8930 vrf_id_str);
8931
ae248832 8932 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8933
8934 if (len < 1)
8935 vty_out(vty, "\n%*s", 36, " ");
8936 else
8937 vty_out(vty, "%*s", len, " ");
d62a17ae 8938 }
8939 }
445c2480 8940 }
718e3744 8941
445c2480
DS
8942 /* MED/Metric */
8943 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8944 if (json_paths)
50e05855 8945 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8946 else if (wide)
8947 vty_out(vty, "%7u", attr->med);
0fbac0b4 8948 else
445c2480 8949 vty_out(vty, "%10u", attr->med);
ae248832
MK
8950 else if (!json_paths) {
8951 if (wide)
8952 vty_out(vty, "%*s", 7, " ");
8953 else
8954 vty_out(vty, "%*s", 10, " ");
8955 }
d62a17ae 8956
445c2480
DS
8957 /* Local Pref */
8958 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8959 if (json_paths)
50e05855 8960 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8961 attr->local_pref);
8962 else
445c2480
DS
8963 vty_out(vty, "%7u", attr->local_pref);
8964 else if (!json_paths)
8965 vty_out(vty, " ");
d62a17ae 8966
445c2480
DS
8967 if (json_paths)
8968 json_object_int_add(json_path, "weight", attr->weight);
8969 else
8970 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8971
445c2480
DS
8972 if (json_paths) {
8973 char buf[BUFSIZ];
a4d82a8a
PZ
8974 json_object_string_add(
8975 json_path, "peerId",
9b6d8fcf 8976 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8977 }
b05a1c8b 8978
445c2480
DS
8979 /* Print aspath */
8980 if (attr->aspath) {
0fbac0b4 8981 if (json_paths)
50e05855 8982 json_object_string_add(json_path, "path",
0fbac0b4
DA
8983 attr->aspath->str);
8984 else
445c2480 8985 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8986 }
f1aa5d8a 8987
445c2480
DS
8988 /* Print origin */
8989 if (json_paths)
a4d82a8a
PZ
8990 json_object_string_add(json_path, "origin",
8991 bgp_origin_long_str[attr->origin]);
445c2480
DS
8992 else
8993 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8994
9df8b37c 8995 if (json_paths) {
d071f237 8996 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8997 json_object_string_add(json_path, "esi",
8998 esi_to_str(&attr->esi,
8999 esi_buf, sizeof(esi_buf)));
9000 }
6f214dd3
CS
9001 if (safi == SAFI_EVPN &&
9002 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9003 json_ext_community = json_object_new_object();
9004 json_object_string_add(json_ext_community,
9005 "string",
9006 attr->ecommunity->str);
9007 json_object_object_add(json_path,
9008 "extendedCommunity",
9009 json_ext_community);
9010 }
9011
9df8b37c
PZ
9012 if (nexthop_self)
9013 json_object_boolean_true_add(json_path,
9014 "announceNexthopSelf");
9015 if (nexthop_othervrf) {
9016 json_object_string_add(json_path, "nhVrfName",
9017 nexthop_vrfname);
9018
9019 json_object_int_add(json_path, "nhVrfId",
9020 ((nexthop_vrfid == VRF_UNKNOWN)
9021 ? -1
9022 : (int)nexthop_vrfid));
9023 }
9024 }
9025
d62a17ae 9026 if (json_paths) {
9027 if (json_nexthop_global || json_nexthop_ll) {
9028 json_nexthops = json_object_new_array();
f1aa5d8a 9029
d62a17ae 9030 if (json_nexthop_global)
9031 json_object_array_add(json_nexthops,
9032 json_nexthop_global);
f1aa5d8a 9033
d62a17ae 9034 if (json_nexthop_ll)
9035 json_object_array_add(json_nexthops,
9036 json_nexthop_ll);
f1aa5d8a 9037
d62a17ae 9038 json_object_object_add(json_path, "nexthops",
9039 json_nexthops);
9040 }
9041
9042 json_object_array_add(json_paths, json_path);
9043 } else {
9044 vty_out(vty, "\n");
6f214dd3 9045
b5e140c8 9046 if (safi == SAFI_EVPN) {
d071f237 9047 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9048 /* XXX - add these params to the json out */
b5e140c8 9049 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9050 vty_out(vty, "ESI:%s",
9051 esi_to_str(&attr->esi, esi_buf,
9052 sizeof(esi_buf)));
60605cbc 9053
229587fb 9054 vty_out(vty, "\n");
b5e140c8
AK
9055 }
9056 if (attr->flag &
9057 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9058 vty_out(vty, "%*s", 20, " ");
9059 vty_out(vty, "%s\n", attr->ecommunity->str);
9060 }
6f214dd3
CS
9061 }
9062
49e5a4a0 9063#ifdef ENABLE_BGP_VNC
d62a17ae 9064 /* prints an additional line, indented, with VNC info, if
9065 * present */
9066 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9067 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9068#endif
d62a17ae 9069 }
9070}
718e3744 9071
9072/* called from terminal list command */
7d3cae70
DA
9073void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9074 const struct prefix *p, struct attr *attr, safi_t safi,
9075 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9076{
9077 json_object *json_status = NULL;
9078 json_object *json_net = NULL;
aef999a2 9079 int len;
d62a17ae 9080 char buff[BUFSIZ];
dc387b0f 9081
d62a17ae 9082 /* Route status display. */
9083 if (use_json) {
9084 json_status = json_object_new_object();
9085 json_net = json_object_new_object();
9086 } else {
9087 vty_out(vty, "*");
9088 vty_out(vty, ">");
9089 vty_out(vty, " ");
9090 }
718e3744 9091
d62a17ae 9092 /* print prefix and mask */
50e05855 9093 if (use_json) {
dc387b0f
LK
9094 if (safi == SAFI_EVPN)
9095 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9096 else if (p->family == AF_INET || p->family == AF_INET6) {
9097 json_object_string_add(
9098 json_net, "addrPrefix",
9099 inet_ntop(p->family, &p->u.prefix, buff,
9100 BUFSIZ));
9101 json_object_int_add(json_net, "prefixLen",
9102 p->prefixlen);
9103 prefix2str(p, buff, PREFIX_STRLEN);
9104 json_object_string_add(json_net, "network", buff);
9105 }
50e05855 9106 } else
7d3cae70 9107 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9108
9109 /* Print attribute */
9110 if (attr) {
9111 if (use_json) {
9112 if (p->family == AF_INET
9113 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9114 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9115 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9116 json_object_string_addf(
9117 json_net, "nextHop", "%pI4",
9118 &attr->mp_nexthop_global_in);
d62a17ae 9119 else
c949c771
DA
9120 json_object_string_addf(
9121 json_net, "nextHop", "%pI4",
9122 &attr->nexthop);
d62a17ae 9123 } else if (p->family == AF_INET6
9124 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9125 json_object_string_addf(
9126 json_net, "nextHopGlobal", "%pI6",
9127 &attr->mp_nexthop_global);
23d0a753
DA
9128 } else if (p->family == AF_EVPN
9129 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9130 json_object_string_addf(
9131 json_net, "nextHop", "%pI4",
9132 &attr->mp_nexthop_global_in);
23d0a753 9133 }
d62a17ae 9134
9135 if (attr->flag
9136 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9137 json_object_int_add(json_net, "metric",
9138 attr->med);
9139
0fbac0b4 9140 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9141 json_object_int_add(json_net, "locPrf",
0fbac0b4 9142 attr->local_pref);
d62a17ae 9143
9144 json_object_int_add(json_net, "weight", attr->weight);
9145
9146 /* Print aspath */
0fbac0b4 9147 if (attr->aspath)
50e05855 9148 json_object_string_add(json_net, "path",
0fbac0b4 9149 attr->aspath->str);
d62a17ae 9150
9151 /* Print origin */
9152 json_object_string_add(json_net, "bgpOriginCode",
9153 bgp_origin_str[attr->origin]);
9154 } else {
9155 if (p->family == AF_INET
9156 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9157 || safi == SAFI_EVPN
9158 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9159 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9160 || safi == SAFI_EVPN)
23d0a753
DA
9161 vty_out(vty, "%-16pI4",
9162 &attr->mp_nexthop_global_in);
ae248832 9163 else if (wide)
23d0a753 9164 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9165 else
23d0a753 9166 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9167 } else if (p->family == AF_INET6
9168 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9169 char buf[BUFSIZ];
9170
9171 len = vty_out(
9172 vty, "%s",
9173 inet_ntop(AF_INET6,
9174 &attr->mp_nexthop_global, buf,
9175 BUFSIZ));
ae248832 9176 len = wide ? (41 - len) : (16 - len);
d62a17ae 9177 if (len < 1)
9178 vty_out(vty, "\n%*s", 36, " ");
9179 else
9180 vty_out(vty, "%*s", len, " ");
9181 }
9182 if (attr->flag
9183 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9184 if (wide)
9185 vty_out(vty, "%7u", attr->med);
9186 else
9187 vty_out(vty, "%10u", attr->med);
9188 else if (wide)
9189 vty_out(vty, " ");
d62a17ae 9190 else
9191 vty_out(vty, " ");
718e3744 9192
d62a17ae 9193 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9194 vty_out(vty, "%7u", attr->local_pref);
9195 else
9196 vty_out(vty, " ");
9197
9198 vty_out(vty, "%7u ", attr->weight);
9199
9200 /* Print aspath */
9201 if (attr->aspath)
9202 aspath_print_vty(vty, "%s", attr->aspath, " ");
9203
9204 /* Print origin */
9205 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9206 }
9207 }
9208 if (use_json) {
9209 json_object_boolean_true_add(json_status, "*");
9210 json_object_boolean_true_add(json_status, ">");
9211 json_object_object_add(json_net, "appliedStatusSymbols",
9212 json_status);
1608ff77 9213
dc387b0f
LK
9214 prefix2str(p, buff, PREFIX_STRLEN);
9215 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9216 } else
9217 vty_out(vty, "\n");
9218}
9219
bd494ec5 9220void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9221 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9222 json_object *json)
9223{
9224 json_object *json_out = NULL;
9225 struct attr *attr;
9226 mpls_label_t label = MPLS_INVALID_LABEL;
9227
9b6d8fcf 9228 if (!path->extra)
d62a17ae 9229 return;
9230
9231 if (json)
9232 json_out = json_object_new_object();
9233
9234 /* short status lead text */
82c298be 9235 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9236
9237 /* print prefix and mask */
9238 if (json == NULL) {
9239 if (!display)
7d3cae70 9240 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9241 else
9242 vty_out(vty, "%*s", 17, " ");
9243 }
9244
9245 /* Print attribute */
9b6d8fcf 9246 attr = path->attr;
05864da7
DS
9247 if (((p->family == AF_INET)
9248 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9249 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9250 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9251 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9252 || safi == SAFI_EVPN) {
9253 if (json)
c949c771
DA
9254 json_object_string_addf(
9255 json_out, "mpNexthopGlobalIn", "%pI4",
9256 &attr->mp_nexthop_global_in);
05864da7 9257 else
23d0a753
DA
9258 vty_out(vty, "%-16pI4",
9259 &attr->mp_nexthop_global_in);
05864da7
DS
9260 } else {
9261 if (json)
c949c771
DA
9262 json_object_string_addf(json_out, "nexthop",
9263 "%pI4", &attr->nexthop);
05864da7 9264 else
23d0a753 9265 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9266 }
9267 } else if (((p->family == AF_INET6)
9268 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9269 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9270 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9271 char buf_a[512];
9272
9273 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9274 if (json)
c949c771
DA
9275 json_object_string_addf(
9276 json_out, "mpNexthopGlobalIn", "%pI6",
9277 &attr->mp_nexthop_global);
05864da7
DS
9278 else
9279 vty_out(vty, "%s",
9280 inet_ntop(AF_INET6,
9281 &attr->mp_nexthop_global,
9282 buf_a, sizeof(buf_a)));
9283 } else if (attr->mp_nexthop_len
9284 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9285 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9286 &attr->mp_nexthop_global,
9287 &attr->mp_nexthop_local);
9288 if (json)
9289 json_object_string_add(json_out,
9290 "mpNexthopGlobalLocal",
9291 buf_a);
9292 else
9293 vty_out(vty, "%s", buf_a);
d62a17ae 9294 }
9295 }
9296
9b6d8fcf 9297 label = decode_label(&path->extra->label[0]);
d62a17ae 9298
9299 if (bgp_is_valid_label(&label)) {
9300 if (json) {
9301 json_object_int_add(json_out, "notag", label);
9302 json_object_array_add(json, json_out);
9303 } else {
9304 vty_out(vty, "notag/%d", label);
9305 vty_out(vty, "\n");
9306 }
700ddfed
PG
9307 } else if (!json)
9308 vty_out(vty, "\n");
d62a17ae 9309}
718e3744 9310
bd494ec5 9311void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9312 struct bgp_path_info *path, int display,
d62a17ae 9313 json_object *json_paths)
718e3744 9314{
d62a17ae 9315 struct attr *attr;
14f51eba 9316 char buf[BUFSIZ] = {0};
d62a17ae 9317 json_object *json_path = NULL;
14f51eba
LK
9318 json_object *json_nexthop = NULL;
9319 json_object *json_overlay = NULL;
856ca177 9320
9b6d8fcf 9321 if (!path->extra)
d62a17ae 9322 return;
718e3744 9323
14f51eba
LK
9324 if (json_paths) {
9325 json_path = json_object_new_object();
9326 json_overlay = json_object_new_object();
9327 json_nexthop = json_object_new_object();
9328 }
9329
d62a17ae 9330 /* short status lead text */
82c298be 9331 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9332
d62a17ae 9333 /* print prefix and mask */
9334 if (!display)
7d3cae70 9335 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9336 else
9337 vty_out(vty, "%*s", 17, " ");
9338
9339 /* Print attribute */
9b6d8fcf 9340 attr = path->attr;
05864da7
DS
9341 char buf1[BUFSIZ];
9342 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9343
05864da7
DS
9344 switch (af) {
9345 case AF_INET:
9346 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9347 if (!json_path) {
9348 vty_out(vty, "%-16s", buf);
9349 } else {
9350 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9351
05864da7 9352 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9353
05864da7
DS
9354 json_object_object_add(json_path, "nexthop",
9355 json_nexthop);
9356 }
9357 break;
9358 case AF_INET6:
9359 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9360 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9361 if (!json_path) {
9362 vty_out(vty, "%s(%s)", buf, buf1);
9363 } else {
9364 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9365
05864da7
DS
9366 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9367 buf1);
14f51eba 9368
05864da7 9369 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9370
05864da7
DS
9371 json_object_object_add(json_path, "nexthop",
9372 json_nexthop);
9373 }
9374 break;
9375 default:
9376 if (!json_path) {
9377 vty_out(vty, "?");
9378 } else {
9379 json_object_string_add(json_nexthop, "Error",
9380 "Unsupported address-family");
d62a17ae 9381 }
05864da7 9382 }
988258b4 9383
6c924775
DS
9384 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9385
9386 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9387 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9388 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9389 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9390
05864da7
DS
9391 if (!json_path)
9392 vty_out(vty, "/%s", buf);
9393 else
9394 json_object_string_add(json_overlay, "gw", buf);
9395
9396 if (attr->ecommunity) {
9397 char *mac = NULL;
9398 struct ecommunity_val *routermac = ecommunity_lookup(
9399 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9400 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9401
9402 if (routermac)
9403 mac = ecom_mac2str((char *)routermac->val);
9404 if (mac) {
9405 if (!json_path) {
c4efd0f4 9406 vty_out(vty, "/%s", mac);
05864da7
DS
9407 } else {
9408 json_object_string_add(json_overlay, "rmac",
9409 mac);
988258b4 9410 }
05864da7 9411 XFREE(MTYPE_TMP, mac);
988258b4 9412 }
05864da7 9413 }
718e3744 9414
05864da7
DS
9415 if (!json_path) {
9416 vty_out(vty, "\n");
9417 } else {
9418 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9419
05864da7 9420 json_object_array_add(json_paths, json_path);
14f51eba 9421 }
d62a17ae 9422}
718e3744 9423
d62a17ae 9424/* dampening route */
5f040085
DS
9425static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9426 struct bgp_path_info *path, int display,
9427 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9428 json_object *json_paths)
d62a17ae 9429{
e5be8c1d 9430 struct attr *attr = path->attr;
d62a17ae 9431 int len;
9432 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9433 json_object *json_path = NULL;
9434
9435 if (use_json)
9436 json_path = json_object_new_object();
d62a17ae 9437
9438 /* short status lead text */
e5be8c1d 9439 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9440
9441 /* print prefix and mask */
9442 if (!use_json) {
9443 if (!display)
7d3cae70 9444 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9445 else
9446 vty_out(vty, "%*s", 17, " ");
d62a17ae 9447
e5be8c1d
DA
9448 len = vty_out(vty, "%s", path->peer->host);
9449 len = 17 - len;
9450
9451 if (len < 1)
d62a17ae 9452 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9453 else
9454 vty_out(vty, "%*s", len, " ");
d62a17ae 9455
9b6d8fcf
DS
9456 vty_out(vty, "%s ",
9457 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9458 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9459 use_json, NULL));
d62a17ae 9460
e5be8c1d 9461 if (attr->aspath)
05864da7 9462 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9463
05864da7
DS
9464 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9465
d62a17ae 9466 vty_out(vty, "\n");
e5be8c1d
DA
9467 } else {
9468 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9469 safi, use_json, json_path);
9470
9471 if (attr->aspath)
9472 json_object_string_add(json_path, "asPath",
9473 attr->aspath->str);
9474
9475 json_object_string_add(json_path, "origin",
9476 bgp_origin_str[attr->origin]);
9477 json_object_string_add(json_path, "peerHost", path->peer->host);
9478
9479 json_object_array_add(json_paths, json_path);
9480 }
d62a17ae 9481}
718e3744 9482
d62a17ae 9483/* flap route */
5f040085
DS
9484static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9485 struct bgp_path_info *path, int display,
9486 afi_t afi, safi_t safi, bool use_json,
31258046 9487 json_object *json_paths)
784d3a42 9488{
31258046 9489 struct attr *attr = path->attr;
d62a17ae 9490 struct bgp_damp_info *bdi;
9491 char timebuf[BGP_UPTIME_LEN];
9492 int len;
31258046 9493 json_object *json_path = NULL;
784d3a42 9494
9b6d8fcf 9495 if (!path->extra)
d62a17ae 9496 return;
784d3a42 9497
31258046
DA
9498 if (use_json)
9499 json_path = json_object_new_object();
9500
9b6d8fcf 9501 bdi = path->extra->damp_info;
784d3a42 9502
d62a17ae 9503 /* short status lead text */
31258046 9504 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9505
d62a17ae 9506 if (!use_json) {
9507 if (!display)
7d3cae70 9508 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9509 else
9510 vty_out(vty, "%*s", 17, " ");
784d3a42 9511
31258046
DA
9512 len = vty_out(vty, "%s", path->peer->host);
9513 len = 16 - len;
9514 if (len < 1)
d62a17ae 9515 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9516 else
9517 vty_out(vty, "%*s", len, " ");
784d3a42 9518
31258046
DA
9519 len = vty_out(vty, "%d", bdi->flap);
9520 len = 5 - len;
9521 if (len < 1)
d62a17ae 9522 vty_out(vty, " ");
d62a17ae 9523 else
9524 vty_out(vty, "%*s", len, " ");
d62a17ae 9525
996c9314
LB
9526 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9527 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9528
31258046
DA
9529 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9530 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9531 vty_out(vty, "%s ",
9b6d8fcf 9532 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9533 BGP_UPTIME_LEN, afi,
31258046
DA
9534 safi, use_json, NULL));
9535 else
d62a17ae 9536 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9537
31258046 9538 if (attr->aspath)
05864da7 9539 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9540
05864da7
DS
9541 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9542
d62a17ae 9543 vty_out(vty, "\n");
31258046
DA
9544 } else {
9545 json_object_string_add(json_path, "peerHost", path->peer->host);
9546 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9547
9548 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9549 json_path);
9550
9551 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9552 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9553 bgp_damp_reuse_time_vty(vty, path, timebuf,
9554 BGP_UPTIME_LEN, afi, safi,
9555 use_json, json_path);
9556
9557 if (attr->aspath)
9558 json_object_string_add(json_path, "asPath",
9559 attr->aspath->str);
9560
9561 json_object_string_add(json_path, "origin",
9562 bgp_origin_str[attr->origin]);
9563
9564 json_object_array_add(json_paths, json_path);
9565 }
d62a17ae 9566}
9567
9568static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9569 int *first, const char *header,
9570 json_object *json_adv_to)
9571{
9572 char buf1[INET6_ADDRSTRLEN];
9573 json_object *json_peer = NULL;
9574
9575 if (json_adv_to) {
9576 /* 'advertised-to' is a dictionary of peers we have advertised
9577 * this
9578 * prefix too. The key is the peer's IP or swpX, the value is
9579 * the
9580 * hostname if we know it and "" if not.
9581 */
9582 json_peer = json_object_new_object();
9583
9584 if (peer->hostname)
9585 json_object_string_add(json_peer, "hostname",
9586 peer->hostname);
9587
9588 if (peer->conf_if)
9589 json_object_object_add(json_adv_to, peer->conf_if,
9590 json_peer);
9591 else
9592 json_object_object_add(
9593 json_adv_to,
9594 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9595 json_peer);
9596 } else {
9597 if (*first) {
9598 vty_out(vty, "%s", header);
9599 *first = 0;
9600 }
9601
9602 if (peer->hostname
892fedb6 9603 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9604 if (peer->conf_if)
9605 vty_out(vty, " %s(%s)", peer->hostname,
9606 peer->conf_if);
9607 else
9608 vty_out(vty, " %s(%s)", peer->hostname,
9609 sockunion2str(&peer->su, buf1,
9610 SU_ADDRSTRLEN));
9611 } else {
9612 if (peer->conf_if)
9613 vty_out(vty, " %s", peer->conf_if);
9614 else
9615 vty_out(vty, " %s",
9616 sockunion2str(&peer->su, buf1,
9617 SU_ADDRSTRLEN));
9618 }
9619 }
784d3a42
PG
9620}
9621
dcc68b5e
MS
9622static void route_vty_out_tx_ids(struct vty *vty,
9623 struct bgp_addpath_info_data *d)
9624{
9625 int i;
9626
9627 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9628 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9629 d->addpath_tx_id[i],
9630 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9631 }
9632}
9633
5e4d4c8a 9634static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9635 struct bgp_path_info *pi,
9636 struct attr *attr,
9637 json_object *json_path)
5e4d4c8a
AK
9638{
9639 char esi_buf[ESI_STR_LEN];
9640 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9641 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9642 ATTR_ES_PEER_ROUTER);
9643 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9644 ATTR_ES_PEER_ACTIVE);
9645 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9646 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9647 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9648 if (json_path) {
9649 json_object *json_es_info = NULL;
9650
9651 json_object_string_add(
9652 json_path, "esi",
9653 esi_buf);
9654 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9655 json_es_info = json_object_new_object();
9656 if (es_local)
9657 json_object_boolean_true_add(
9658 json_es_info, "localEs");
9659 if (peer_active)
9660 json_object_boolean_true_add(
9661 json_es_info, "peerActive");
9662 if (peer_proxy)
9663 json_object_boolean_true_add(
9664 json_es_info, "peerProxy");
9665 if (peer_router)
9666 json_object_boolean_true_add(
9667 json_es_info, "peerRouter");
9668 if (attr->mm_sync_seqnum)
9669 json_object_int_add(
9670 json_es_info, "peerSeq",
9671 attr->mm_sync_seqnum);
9672 json_object_object_add(
9673 json_path, "es_info",
9674 json_es_info);
9675 }
9676 } else {
9677 if (bgp_evpn_attr_is_sync(attr))
9678 vty_out(vty,
9679 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9680 esi_buf,
9681 es_local ? "local-es":"",
9682 peer_proxy ? "proxy " : "",
9683 peer_active ? "active ":"",
9684 peer_router ? "router ":"",
9685 attr->mm_sync_seqnum);
9686 else
9687 vty_out(vty, " ESI %s %s\n",
9688 esi_buf,
9689 es_local ? "local-es":"");
9690 }
9691}
9692
4933eaaf
DS
9693void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9694 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9695 enum rpki_states rpki_curr_state,
9696 json_object *json_paths)
d62a17ae 9697{
9698 char buf[INET6_ADDRSTRLEN];
9699 char buf1[BUFSIZ];
515c2602 9700 struct attr *attr = path->attr;
d62a17ae 9701 int sockunion_vty_out(struct vty *, union sockunion *);
9702 time_t tbuf;
9703 json_object *json_bestpath = NULL;
9704 json_object *json_cluster_list = NULL;
9705 json_object *json_cluster_list_list = NULL;
9706 json_object *json_ext_community = NULL;
9707 json_object *json_last_update = NULL;
7fd077aa 9708 json_object *json_pmsi = NULL;
d62a17ae 9709 json_object *json_nexthop_global = NULL;
9710 json_object *json_nexthop_ll = NULL;
9711 json_object *json_nexthops = NULL;
9712 json_object *json_path = NULL;
9713 json_object *json_peer = NULL;
9714 json_object *json_string = NULL;
9715 json_object *json_adv_to = NULL;
9716 int first = 0;
9717 struct listnode *node, *nnode;
9718 struct peer *peer;
9719 int addpath_capable;
9720 int has_adj;
9721 unsigned int first_as;
1defdda8 9722 bool nexthop_self =
9b6d8fcf 9723 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9724 int i;
2ba93fd6
DA
9725 char *nexthop_hostname =
9726 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9727
9728 if (json_paths) {
9729 json_path = json_object_new_object();
9730 json_peer = json_object_new_object();
9731 json_nexthop_global = json_object_new_object();
9732 }
9733
8304dabf
AD
9734 if (safi == SAFI_EVPN) {
9735 if (!json_paths)
9736 vty_out(vty, " Route %pRN", bn);
9737 }
9738
44c69747 9739 if (path->extra) {
b57ba6d2 9740 char tag_buf[30];
d62a17ae 9741
d62a17ae 9742 tag_buf[0] = '\0';
9b6d8fcf
DS
9743 if (path->extra && path->extra->num_labels) {
9744 bgp_evpn_label2str(path->extra->label,
9745 path->extra->num_labels, tag_buf,
a4d82a8a 9746 sizeof(tag_buf));
d62a17ae 9747 }
d7325ee7 9748 if (safi == SAFI_EVPN) {
44c69747 9749 if (!json_paths) {
44c69747
LK
9750 if (tag_buf[0] != '\0')
9751 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9752 } else {
9753 if (tag_buf[0])
9754 json_object_string_add(json_path, "VNI",
9755 tag_buf);
9756 }
d7325ee7
DD
9757 }
9758
44c69747 9759 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9760 struct bgp_path_info *parent_ri;
9bcb3eef 9761 struct bgp_dest *dest, *pdest;
d62a17ae 9762
9b6d8fcf 9763 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9764 dest = parent_ri->net;
9765 if (dest && dest->pdest) {
9766 pdest = dest->pdest;
9767 prefix_rd2str(
9768 (struct prefix_rd *)bgp_dest_get_prefix(
9769 pdest),
9770 buf1, sizeof(buf1));
d7325ee7 9771 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9772 vty_out(vty,
58bff4d1 9773 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9774 buf1,
9775 (struct prefix_evpn *)
9776 bgp_dest_get_prefix(
9777 dest),
9778 tag_buf);
58bff4d1
AK
9779 if (attr->es_flags & ATTR_ES_L3_NHG)
9780 vty_out(vty, ", L3NHG %s",
9781 (attr->es_flags
9782 & ATTR_ES_L3_NHG_ACTIVE)
9783 ? "active"
9784 : "inactive");
9785 vty_out(vty, "\n");
9786
d7325ee7 9787 } else
2dbe669b
DA
9788 vty_out(vty,
9789 " Imported from %s:%pFX\n",
9790 buf1,
9791 (struct prefix_evpn *)
9792 bgp_dest_get_prefix(
9793 dest));
d62a17ae 9794 }
9795 }
9796 }
d62a17ae 9797
8304dabf
AD
9798 if (safi == SAFI_EVPN
9799 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9800 char gwip_buf[INET6_ADDRSTRLEN];
9801
9802 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
9803 inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
9804 gwip_buf, sizeof(gwip_buf));
9805 else
9806 inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
9807 gwip_buf, sizeof(gwip_buf));
9808
9809 if (json_paths)
9810 json_object_string_add(json_path, "gatewayIP",
9811 gwip_buf);
9812 else
9813 vty_out(vty, " Gateway IP %s", gwip_buf);
9814 }
9815
9816 if (safi == SAFI_EVPN)
9817 vty_out(vty, "\n");
9818
05864da7
DS
9819 /* Line1 display AS-path, Aggregator */
9820 if (attr->aspath) {
9821 if (json_paths) {
9822 if (!attr->aspath->json)
9823 aspath_str_update(attr->aspath, true);
9824 json_object_lock(attr->aspath->json);
9825 json_object_object_add(json_path, "aspath",
9826 attr->aspath->json);
9827 } else {
9828 if (attr->aspath->segments)
9829 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9830 else
05864da7 9831 vty_out(vty, " Local");
d62a17ae 9832 }
05864da7 9833 }
d62a17ae 9834
05864da7
DS
9835 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9836 if (json_paths)
9837 json_object_boolean_true_add(json_path, "removed");
9838 else
9839 vty_out(vty, ", (removed)");
9840 }
d62a17ae 9841
05864da7
DS
9842 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9843 if (json_paths)
9844 json_object_boolean_true_add(json_path, "stale");
9845 else
9846 vty_out(vty, ", (stale)");
9847 }
d62a17ae 9848
05864da7
DS
9849 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9850 if (json_paths) {
9851 json_object_int_add(json_path, "aggregatorAs",
9852 attr->aggregator_as);
c949c771
DA
9853 json_object_string_addf(json_path, "aggregatorId",
9854 "%pI4", &attr->aggregator_addr);
05864da7 9855 } else {
88d495a9
DA
9856 vty_out(vty, ", (aggregated by %u %pI4)",
9857 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9858 }
05864da7 9859 }
d62a17ae 9860
05864da7
DS
9861 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9862 PEER_FLAG_REFLECTOR_CLIENT)) {
9863 if (json_paths)
9864 json_object_boolean_true_add(json_path,
9865 "rxedFromRrClient");
9866 else
9867 vty_out(vty, ", (Received from a RR-client)");
9868 }
d62a17ae 9869
05864da7
DS
9870 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9871 PEER_FLAG_RSERVER_CLIENT)) {
9872 if (json_paths)
9873 json_object_boolean_true_add(json_path,
9874 "rxedFromRsClient");
9875 else
9876 vty_out(vty, ", (Received from a RS-client)");
9877 }
d62a17ae 9878
05864da7
DS
9879 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9880 if (json_paths)
9881 json_object_boolean_true_add(json_path,
9882 "dampeningHistoryEntry");
9883 else
9884 vty_out(vty, ", (history entry)");
9885 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9886 if (json_paths)
9887 json_object_boolean_true_add(json_path,
9888 "dampeningSuppressed");
9889 else
9890 vty_out(vty, ", (suppressed due to dampening)");
9891 }
d62a17ae 9892
05864da7
DS
9893 if (!json_paths)
9894 vty_out(vty, "\n");
d62a17ae 9895
05864da7
DS
9896 /* Line2 display Next-hop, Neighbor, Router-id */
9897 /* Display the nexthop */
9bcb3eef 9898 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9899
9900 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9901 || bn_p->family == AF_EVPN)
05864da7
DS
9902 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9903 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9904 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9905 || safi == SAFI_EVPN) {
515c2602 9906 if (json_paths) {
c949c771
DA
9907 json_object_string_addf(
9908 json_nexthop_global, "ip", "%pI4",
9909 &attr->mp_nexthop_global_in);
515c2602 9910
939a97f4 9911 if (path->peer->hostname)
515c2602
DA
9912 json_object_string_add(
9913 json_nexthop_global, "hostname",
939a97f4 9914 path->peer->hostname);
aef999a2
DA
9915 } else {
9916 if (nexthop_hostname)
9917 vty_out(vty, " %pI4(%s)",
9918 &attr->mp_nexthop_global_in,
9919 nexthop_hostname);
9920 else
9921 vty_out(vty, " %pI4",
9922 &attr->mp_nexthop_global_in);
9923 }
d62a17ae 9924 } else {
515c2602 9925 if (json_paths) {
c949c771
DA
9926 json_object_string_addf(json_nexthop_global,
9927 "ip", "%pI4",
9928 &attr->nexthop);
515c2602 9929
939a97f4 9930 if (path->peer->hostname)
515c2602
DA
9931 json_object_string_add(
9932 json_nexthop_global, "hostname",
939a97f4 9933 path->peer->hostname);
aef999a2
DA
9934 } else {
9935 if (nexthop_hostname)
9936 vty_out(vty, " %pI4(%s)",
9937 &attr->nexthop,
9938 nexthop_hostname);
9939 else
9940 vty_out(vty, " %pI4",
9941 &attr->nexthop);
9942 }
d62a17ae 9943 }
9944
05864da7
DS
9945 if (json_paths)
9946 json_object_string_add(json_nexthop_global, "afi",
9947 "ipv4");
9948 } else {
9949 if (json_paths) {
c949c771
DA
9950 json_object_string_addf(json_nexthop_global, "ip",
9951 "%pI6",
9952 &attr->mp_nexthop_global);
515c2602 9953
939a97f4 9954 if (path->peer->hostname)
515c2602
DA
9955 json_object_string_add(json_nexthop_global,
9956 "hostname",
939a97f4 9957 path->peer->hostname);
515c2602 9958
05864da7
DS
9959 json_object_string_add(json_nexthop_global, "afi",
9960 "ipv6");
9961 json_object_string_add(json_nexthop_global, "scope",
9962 "global");
9963 } else {
aef999a2
DA
9964 if (nexthop_hostname)
9965 vty_out(vty, " %pI6(%s)",
9966 &attr->mp_nexthop_global,
9967 nexthop_hostname);
9968 else
9969 vty_out(vty, " %pI6",
9970 &attr->mp_nexthop_global);
d62a17ae 9971 }
05864da7 9972 }
d62a17ae 9973
05864da7
DS
9974 /* Display the IGP cost or 'inaccessible' */
9975 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9976 if (json_paths)
9977 json_object_boolean_false_add(json_nexthop_global,
9978 "accessible");
9979 else
9980 vty_out(vty, " (inaccessible)");
9981 } else {
9982 if (path->extra && path->extra->igpmetric) {
d62a17ae 9983 if (json_paths)
05864da7
DS
9984 json_object_int_add(json_nexthop_global,
9985 "metric",
9986 path->extra->igpmetric);
d62a17ae 9987 else
05864da7
DS
9988 vty_out(vty, " (metric %u)",
9989 path->extra->igpmetric);
d62a17ae 9990 }
9991
05864da7 9992 /* IGP cost is 0, display this only for json */
d62a17ae 9993 else {
d62a17ae 9994 if (json_paths)
05864da7
DS
9995 json_object_int_add(json_nexthop_global,
9996 "metric", 0);
d62a17ae 9997 }
d62a17ae 9998
05864da7
DS
9999 if (json_paths)
10000 json_object_boolean_true_add(json_nexthop_global,
10001 "accessible");
10002 }
d62a17ae 10003
05864da7
DS
10004 /* Display peer "from" output */
10005 /* This path was originated locally */
10006 if (path->peer == bgp->peer_self) {
d62a17ae 10007
05864da7 10008 if (safi == SAFI_EVPN
b54892e0 10009 || (bn_p->family == AF_INET
05864da7 10010 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10011 if (json_paths)
05864da7
DS
10012 json_object_string_add(json_peer, "peerId",
10013 "0.0.0.0");
d62a17ae 10014 else
05864da7
DS
10015 vty_out(vty, " from 0.0.0.0 ");
10016 } else {
d62a17ae 10017 if (json_paths)
05864da7
DS
10018 json_object_string_add(json_peer, "peerId",
10019 "::");
d62a17ae 10020 else
05864da7 10021 vty_out(vty, " from :: ");
d62a17ae 10022 }
d62a17ae 10023
4e9a9863 10024 if (json_paths)
c949c771
DA
10025 json_object_string_addf(json_peer, "routerId", "%pI4",
10026 &bgp->router_id);
4e9a9863 10027 else
23d0a753 10028 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10029 }
d62a17ae 10030
05864da7
DS
10031 /* We RXed this path from one of our peers */
10032 else {
10033
10034 if (json_paths) {
10035 json_object_string_add(json_peer, "peerId",
10036 sockunion2str(&path->peer->su,
10037 buf,
10038 SU_ADDRSTRLEN));
c949c771
DA
10039 json_object_string_addf(json_peer, "routerId", "%pI4",
10040 &path->peer->remote_id);
05864da7
DS
10041
10042 if (path->peer->hostname)
10043 json_object_string_add(json_peer, "hostname",
10044 path->peer->hostname);
10045
10046 if (path->peer->domainname)
10047 json_object_string_add(json_peer, "domainname",
10048 path->peer->domainname);
10049
10050 if (path->peer->conf_if)
10051 json_object_string_add(json_peer, "interface",
10052 path->peer->conf_if);
10053 } else {
10054 if (path->peer->conf_if) {
10055 if (path->peer->hostname
892fedb6
DA
10056 && CHECK_FLAG(path->peer->bgp->flags,
10057 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10058 vty_out(vty, " from %s(%s)",
10059 path->peer->hostname,
10060 path->peer->conf_if);
d62a17ae 10061 else
05864da7 10062 vty_out(vty, " from %s",
9b6d8fcf 10063 path->peer->conf_if);
d62a17ae 10064 } else {
05864da7 10065 if (path->peer->hostname
892fedb6
DA
10066 && CHECK_FLAG(path->peer->bgp->flags,
10067 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10068 vty_out(vty, " from %s(%s)",
10069 path->peer->hostname,
10070 path->peer->host);
d62a17ae 10071 else
05864da7
DS
10072 vty_out(vty, " from %s",
10073 sockunion2str(&path->peer->su,
10074 buf,
10075 SU_ADDRSTRLEN));
d62a17ae 10076 }
d62a17ae 10077
05864da7 10078 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10079 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10080 else
10081 vty_out(vty, " (%s)",
10082 inet_ntop(AF_INET,
10083 &path->peer->remote_id, buf1,
10084 sizeof(buf1)));
d62a17ae 10085 }
05864da7 10086 }
9df8b37c 10087
05864da7
DS
10088 /*
10089 * Note when vrfid of nexthop is different from that of prefix
10090 */
10091 if (path->extra && path->extra->bgp_orig) {
10092 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10093
05864da7
DS
10094 if (json_paths) {
10095 const char *vn;
9df8b37c 10096
05864da7
DS
10097 if (path->extra->bgp_orig->inst_type
10098 == BGP_INSTANCE_TYPE_DEFAULT)
10099 vn = VRF_DEFAULT_NAME;
10100 else
10101 vn = path->extra->bgp_orig->name;
9df8b37c 10102
05864da7 10103 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10104
05864da7
DS
10105 if (nexthop_vrfid == VRF_UNKNOWN) {
10106 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10107 } else {
05864da7
DS
10108 json_object_int_add(json_path, "nhVrfId",
10109 (int)nexthop_vrfid);
9df8b37c 10110 }
05864da7
DS
10111 } else {
10112 if (nexthop_vrfid == VRF_UNKNOWN)
10113 vty_out(vty, " vrf ?");
137147c6
DS
10114 else {
10115 struct vrf *vrf;
10116
10117 vrf = vrf_lookup_by_id(nexthop_vrfid);
10118 vty_out(vty, " vrf %s(%u)",
10119 VRF_LOGNAME(vrf), nexthop_vrfid);
10120 }
9df8b37c 10121 }
05864da7 10122 }
9df8b37c 10123
05864da7
DS
10124 if (nexthop_self) {
10125 if (json_paths) {
10126 json_object_boolean_true_add(json_path,
10127 "announceNexthopSelf");
10128 } else {
10129 vty_out(vty, " announce-nh-self");
9df8b37c 10130 }
05864da7 10131 }
9df8b37c 10132
05864da7
DS
10133 if (!json_paths)
10134 vty_out(vty, "\n");
d62a17ae 10135
05864da7
DS
10136 /* display the link-local nexthop */
10137 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10138 if (json_paths) {
10139 json_nexthop_ll = json_object_new_object();
c949c771
DA
10140 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10141 &attr->mp_nexthop_local);
515c2602 10142
939a97f4 10143 if (path->peer->hostname)
515c2602
DA
10144 json_object_string_add(json_nexthop_ll,
10145 "hostname",
939a97f4 10146 path->peer->hostname);
515c2602 10147
05864da7
DS
10148 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10149 json_object_string_add(json_nexthop_ll, "scope",
10150 "link-local");
d62a17ae 10151
05864da7
DS
10152 json_object_boolean_true_add(json_nexthop_ll,
10153 "accessible");
d62a17ae 10154
05864da7 10155 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10156 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10157 "used");
10158 else
10159 json_object_boolean_true_add(
10160 json_nexthop_global, "used");
10161 } else {
10162 vty_out(vty, " (%s) %s\n",
10163 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10164 buf, INET6_ADDRSTRLEN),
10165 attr->mp_nexthop_prefer_global
10166 ? "(prefer-global)"
10167 : "(used)");
d62a17ae 10168 }
05864da7
DS
10169 }
10170 /* If we do not have a link-local nexthop then we must flag the
10171 global as "used" */
10172 else {
10173 if (json_paths)
10174 json_object_boolean_true_add(json_nexthop_global,
10175 "used");
10176 }
d62a17ae 10177
b5e140c8 10178 if (safi == SAFI_EVPN &&
5e4d4c8a 10179 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10180 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10181 }
10182
05864da7
DS
10183 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10184 * Int/Ext/Local, Atomic, best */
10185 if (json_paths)
10186 json_object_string_add(json_path, "origin",
10187 bgp_origin_long_str[attr->origin]);
10188 else
10189 vty_out(vty, " Origin %s",
10190 bgp_origin_long_str[attr->origin]);
9df8b37c 10191
05864da7 10192 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10193 if (json_paths)
05864da7 10194 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10195 else
05864da7
DS
10196 vty_out(vty, ", metric %u", attr->med);
10197 }
9df8b37c 10198
05864da7
DS
10199 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10200 if (json_paths)
0fbac0b4 10201 json_object_int_add(json_path, "locPrf",
05864da7
DS
10202 attr->local_pref);
10203 else
10204 vty_out(vty, ", localpref %u", attr->local_pref);
10205 }
9df8b37c 10206
05864da7
DS
10207 if (attr->weight != 0) {
10208 if (json_paths)
10209 json_object_int_add(json_path, "weight", attr->weight);
10210 else
10211 vty_out(vty, ", weight %u", attr->weight);
10212 }
9df8b37c 10213
05864da7
DS
10214 if (attr->tag != 0) {
10215 if (json_paths)
10216 json_object_int_add(json_path, "tag", attr->tag);
10217 else
10218 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10219 }
9df8b37c 10220
05864da7
DS
10221 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10222 if (json_paths)
10223 json_object_boolean_false_add(json_path, "valid");
10224 else
10225 vty_out(vty, ", invalid");
10226 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10227 if (json_paths)
10228 json_object_boolean_true_add(json_path, "valid");
10229 else
10230 vty_out(vty, ", valid");
10231 }
9df8b37c 10232
7d3cae70
DA
10233 if (json_paths)
10234 json_object_int_add(json_path, "version", bn->version);
10235
05864da7
DS
10236 if (path->peer != bgp->peer_self) {
10237 if (path->peer->as == path->peer->local_as) {
10238 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10239 if (json_paths)
10240 json_object_string_add(
10241 json_peer, "type",
10242 "confed-internal");
d62a17ae 10243 else
05864da7 10244 vty_out(vty, ", confed-internal");
d62a17ae 10245 } else {
05864da7
DS
10246 if (json_paths)
10247 json_object_string_add(
10248 json_peer, "type", "internal");
10249 else
10250 vty_out(vty, ", internal");
9df8b37c 10251 }
05864da7
DS
10252 } else {
10253 if (bgp_confederation_peers_check(bgp,
10254 path->peer->as)) {
10255 if (json_paths)
10256 json_object_string_add(
10257 json_peer, "type",
10258 "confed-external");
d62a17ae 10259 else
05864da7 10260 vty_out(vty, ", confed-external");
d62a17ae 10261 } else {
05864da7
DS
10262 if (json_paths)
10263 json_object_string_add(
10264 json_peer, "type", "external");
10265 else
10266 vty_out(vty, ", external");
d62a17ae 10267 }
10268 }
05864da7
DS
10269 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10270 if (json_paths) {
10271 json_object_boolean_true_add(json_path, "aggregated");
10272 json_object_boolean_true_add(json_path, "local");
10273 } else {
10274 vty_out(vty, ", aggregated, local");
10275 }
10276 } else if (path->type != ZEBRA_ROUTE_BGP) {
10277 if (json_paths)
10278 json_object_boolean_true_add(json_path, "sourced");
10279 else
10280 vty_out(vty, ", sourced");
10281 } else {
10282 if (json_paths) {
10283 json_object_boolean_true_add(json_path, "sourced");
10284 json_object_boolean_true_add(json_path, "local");
10285 } else {
10286 vty_out(vty, ", sourced, local");
d62a17ae 10287 }
05864da7 10288 }
718e3744 10289
05864da7 10290 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10291 if (json_paths)
05864da7
DS
10292 json_object_boolean_true_add(json_path,
10293 "atomicAggregate");
d62a17ae 10294 else
05864da7
DS
10295 vty_out(vty, ", atomic-aggregate");
10296 }
d62a17ae 10297
05864da7
DS
10298 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10299 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10300 && bgp_path_info_mpath_count(path))) {
10301 if (json_paths)
10302 json_object_boolean_true_add(json_path, "multipath");
10303 else
10304 vty_out(vty, ", multipath");
10305 }
50e05855 10306
05864da7
DS
10307 // Mark the bestpath(s)
10308 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10309 first_as = aspath_get_first_as(attr->aspath);
718e3744 10310
05864da7
DS
10311 if (json_paths) {
10312 if (!json_bestpath)
10313 json_bestpath = json_object_new_object();
10314 json_object_int_add(json_bestpath, "bestpathFromAs",
10315 first_as);
10316 } else {
10317 if (first_as)
10318 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10319 else
05864da7 10320 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10321 }
05864da7 10322 }
718e3744 10323
05864da7
DS
10324 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10325 if (json_paths) {
10326 if (!json_bestpath)
10327 json_bestpath = json_object_new_object();
10328 json_object_boolean_true_add(json_bestpath, "overall");
10329 json_object_string_add(
10330 json_bestpath, "selectionReason",
10331 bgp_path_selection_reason2str(bn->reason));
10332 } else {
10333 vty_out(vty, ", best");
10334 vty_out(vty, " (%s)",
10335 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10336 }
05864da7 10337 }
718e3744 10338
4027d19b 10339 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10340 if (json_paths)
10341 json_object_string_add(
10342 json_path, "rpkiValidationState",
4027d19b 10343 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10344 else
1d327209 10345 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10346 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10347 }
10348
05864da7
DS
10349 if (json_bestpath)
10350 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10351
05864da7
DS
10352 if (!json_paths)
10353 vty_out(vty, "\n");
10354
10355 /* Line 4 display Community */
29e72930 10356 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10357 if (json_paths) {
10358 if (!attr->community->json)
10359 community_str(attr->community, true);
10360 json_object_lock(attr->community->json);
10361 json_object_object_add(json_path, "community",
10362 attr->community->json);
10363 } else {
10364 vty_out(vty, " Community: %s\n",
10365 attr->community->str);
d62a17ae 10366 }
05864da7 10367 }
718e3744 10368
05864da7
DS
10369 /* Line 5 display Extended-community */
10370 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10371 if (json_paths) {
10372 json_ext_community = json_object_new_object();
10373 json_object_string_add(json_ext_community, "string",
10374 attr->ecommunity->str);
10375 json_object_object_add(json_path, "extendedCommunity",
10376 json_ext_community);
d62a17ae 10377 } else {
05864da7
DS
10378 vty_out(vty, " Extended Community: %s\n",
10379 attr->ecommunity->str);
d62a17ae 10380 }
05864da7 10381 }
718e3744 10382
05864da7
DS
10383 /* Line 6 display Large community */
10384 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10385 if (json_paths) {
10386 if (!attr->lcommunity->json)
10387 lcommunity_str(attr->lcommunity, true);
10388 json_object_lock(attr->lcommunity->json);
10389 json_object_object_add(json_path, "largeCommunity",
10390 attr->lcommunity->json);
10391 } else {
10392 vty_out(vty, " Large Community: %s\n",
10393 attr->lcommunity->str);
d62a17ae 10394 }
05864da7 10395 }
718e3744 10396
05864da7
DS
10397 /* Line 7 display Originator, Cluster-id */
10398 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10399 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10400 char buf[BUFSIZ] = {0};
10401
05864da7 10402 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10403 if (json_paths)
c949c771
DA
10404 json_object_string_addf(json_path,
10405 "originatorId", "%pI4",
10406 &attr->originator_id);
d62a17ae 10407 else
23d0a753
DA
10408 vty_out(vty, " Originator: %pI4",
10409 &attr->originator_id);
d62a17ae 10410 }
856ca177 10411
05864da7 10412 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10413 struct cluster_list *cluster =
10414 bgp_attr_get_cluster(attr);
05864da7 10415 int i;
d62a17ae 10416
10417 if (json_paths) {
05864da7
DS
10418 json_cluster_list = json_object_new_object();
10419 json_cluster_list_list =
10420 json_object_new_array();
10421
779fee93 10422 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10423 json_string = json_object_new_string(
779fee93
DS
10424 inet_ntop(AF_INET,
10425 &cluster->list[i],
10426 buf, sizeof(buf)));
05864da7
DS
10427 json_object_array_add(
10428 json_cluster_list_list,
10429 json_string);
10430 }
718e3744 10431
05864da7
DS
10432 /*
10433 * struct cluster_list does not have
10434 * "str" variable like aspath and community
10435 * do. Add this someday if someone asks
10436 * for it.
10437 * json_object_string_add(json_cluster_list,
779fee93 10438 * "string", cluster->str);
05864da7
DS
10439 */
10440 json_object_object_add(json_cluster_list,
10441 "list",
10442 json_cluster_list_list);
10443 json_object_object_add(json_path, "clusterList",
10444 json_cluster_list);
0dc8ee70 10445 } else {
05864da7
DS
10446 vty_out(vty, ", Cluster list: ");
10447
779fee93 10448 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10449 vty_out(vty, "%pI4 ",
779fee93 10450 &cluster->list[i]);
05864da7 10451 }
0dc8ee70 10452 }
d62a17ae 10453 }
718e3744 10454
d62a17ae 10455 if (!json_paths)
10456 vty_out(vty, "\n");
05864da7 10457 }
d62a17ae 10458
05864da7 10459 if (path->extra && path->extra->damp_info)
b4f7f45b 10460 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10461
05864da7
DS
10462 /* Remote Label */
10463 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10464 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10465 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10466
05864da7
DS
10467 if (json_paths)
10468 json_object_int_add(json_path, "remoteLabel", label);
10469 else
10470 vty_out(vty, " Remote label: %d\n", label);
10471 }
d62a17ae 10472
e496b420
HS
10473 /* Remote SID */
10474 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10475 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10476 if (json_paths)
10477 json_object_string_add(json_path, "remoteSid", buf);
10478 else
10479 vty_out(vty, " Remote SID: %s\n", buf);
10480 }
10481
05864da7
DS
10482 /* Label Index */
10483 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10484 if (json_paths)
10485 json_object_int_add(json_path, "labelIndex",
10486 attr->label_index);
10487 else
10488 vty_out(vty, " Label Index: %d\n",
10489 attr->label_index);
10490 }
d62a17ae 10491
05864da7
DS
10492 /* Line 8 display Addpath IDs */
10493 if (path->addpath_rx_id
10494 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10495 if (json_paths) {
10496 json_object_int_add(json_path, "addpathRxId",
10497 path->addpath_rx_id);
d62a17ae 10498
05864da7
DS
10499 /* Keep backwards compatibility with the old API
10500 * by putting TX All's ID in the old field
10501 */
10502 json_object_int_add(
10503 json_path, "addpathTxId",
10504 path->tx_addpath
10505 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10506
05864da7
DS
10507 /* ... but create a specific field for each
10508 * strategy
10509 */
10510 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10511 json_object_int_add(
10512 json_path,
10513 bgp_addpath_names(i)->id_json_name,
10514 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10515 }
05864da7
DS
10516 } else {
10517 vty_out(vty, " AddPath ID: RX %u, ",
10518 path->addpath_rx_id);
d62a17ae 10519
05864da7 10520 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10521 }
05864da7 10522 }
520d5d76 10523
05864da7
DS
10524 /* If we used addpath to TX a non-bestpath we need to display
10525 * "Advertised to" on a path-by-path basis
10526 */
10527 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10528 first = 1;
dcc68b5e 10529
05864da7
DS
10530 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10531 addpath_capable =
10532 bgp_addpath_encode_tx(peer, afi, safi);
10533 has_adj = bgp_adj_out_lookup(
10534 peer, path->net,
10535 bgp_addpath_id_for_peer(peer, afi, safi,
10536 &path->tx_addpath));
10537
10538 if ((addpath_capable && has_adj)
10539 || (!addpath_capable && has_adj
10540 && CHECK_FLAG(path->flags,
10541 BGP_PATH_SELECTED))) {
10542 if (json_path && !json_adv_to)
10543 json_adv_to = json_object_new_object();
dcc68b5e 10544
05864da7
DS
10545 route_vty_out_advertised_to(
10546 vty, peer, &first,
10547 " Advertised to:", json_adv_to);
d62a17ae 10548 }
10549 }
718e3744 10550
05864da7
DS
10551 if (json_path) {
10552 if (json_adv_to) {
10553 json_object_object_add(
10554 json_path, "advertisedTo", json_adv_to);
d62a17ae 10555 }
05864da7
DS
10556 } else {
10557 if (!first) {
10558 vty_out(vty, "\n");
d62a17ae 10559 }
10560 }
05864da7 10561 }
b05a1c8b 10562
05864da7
DS
10563 /* Line 9 display Uptime */
10564 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10565 if (json_paths) {
10566 json_last_update = json_object_new_object();
10567 json_object_int_add(json_last_update, "epoch", tbuf);
10568 json_object_string_add(json_last_update, "string",
10569 ctime(&tbuf));
10570 json_object_object_add(json_path, "lastUpdate",
10571 json_last_update);
10572 } else
10573 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10574
05864da7
DS
10575 /* Line 10 display PMSI tunnel attribute, if present */
10576 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10577 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10578 bgp_attr_get_pmsi_tnl_type(attr),
10579 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10580
05864da7
DS
10581 if (json_paths) {
10582 json_pmsi = json_object_new_object();
10583 json_object_string_add(json_pmsi, "tunnelType", str);
10584 json_object_int_add(json_pmsi, "label",
10585 label2vni(&attr->label));
10586 json_object_object_add(json_path, "pmsi", json_pmsi);
10587 } else
10588 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10589 str, label2vni(&attr->label));
d62a17ae 10590 }
f1aa5d8a 10591
92269aa2
DS
10592 /* Output some debug about internal state of the dest flags */
10593 if (json_paths) {
10594 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10595 json_object_boolean_true_add(json_path, "processScheduled");
10596 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10597 json_object_boolean_true_add(json_path, "userCleared");
10598 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10599 json_object_boolean_true_add(json_path, "labelChanged");
10600 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10601 json_object_boolean_true_add(json_path, "registeredForLabel");
10602 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10603 json_object_boolean_true_add(json_path, "selectDefered");
10604 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10605 json_object_boolean_true_add(json_path, "fibInstalled");
10606 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10607 json_object_boolean_true_add(json_path, "fibPending");
10608 }
10609
d62a17ae 10610 /* We've constructed the json object for this path, add it to the json
10611 * array of paths
10612 */
10613 if (json_paths) {
10614 if (json_nexthop_global || json_nexthop_ll) {
10615 json_nexthops = json_object_new_array();
f1aa5d8a 10616
d62a17ae 10617 if (json_nexthop_global)
10618 json_object_array_add(json_nexthops,
10619 json_nexthop_global);
f1aa5d8a 10620
d62a17ae 10621 if (json_nexthop_ll)
10622 json_object_array_add(json_nexthops,
10623 json_nexthop_ll);
f1aa5d8a 10624
d62a17ae 10625 json_object_object_add(json_path, "nexthops",
10626 json_nexthops);
10627 }
10628
10629 json_object_object_add(json_path, "peer", json_peer);
10630 json_object_array_add(json_paths, json_path);
05864da7 10631 }
b366b518
BB
10632}
10633
96ade3ed 10634#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10635#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10636#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10637
d62a17ae 10638static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10639 const char *prefix_list_str, afi_t afi,
10640 safi_t safi, enum bgp_show_type type);
10641static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10642 const char *filter, afi_t afi, safi_t safi,
10643 enum bgp_show_type type);
10644static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10645 const char *rmap_str, afi_t afi, safi_t safi,
10646 enum bgp_show_type type);
10647static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10648 const char *com, int exact, afi_t afi,
10649 safi_t safi);
10650static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10651 const char *prefix, afi_t afi, safi_t safi,
10652 enum bgp_show_type type);
a4d82a8a 10653static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10654 afi_t afi, safi_t safi, enum bgp_show_type type,
10655 bool use_json);
7f323236
DW
10656static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10657 const char *comstr, int exact, afi_t afi,
96c81f66 10658 safi_t safi, uint16_t show_flags);
d62a17ae 10659
1ae44dfc 10660static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10661 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10662 void *output_arg, const char *rd, int is_last,
96f3485c 10663 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10664 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10665 enum rpki_states rpki_target_state)
d62a17ae 10666{
40381db7 10667 struct bgp_path_info *pi;
9bcb3eef 10668 struct bgp_dest *dest;
2aad8c42
MS
10669 bool header = true;
10670 bool json_detail_header = false;
d62a17ae 10671 int display;
1ae44dfc
LB
10672 unsigned long output_count = 0;
10673 unsigned long total_count = 0;
d62a17ae 10674 struct prefix *p;
d62a17ae 10675 json_object *json_paths = NULL;
10676 int first = 1;
96f3485c
MK
10677 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10678 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10679 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10680
1ae44dfc 10681 if (output_cum && *output_cum != 0)
2aad8c42 10682 header = false;
1ae44dfc 10683
9386b588 10684 if (use_json && !*json_header_depth) {
96f3485c
MK
10685 if (all)
10686 *json_header_depth = 1;
10687 else {
10688 vty_out(vty, "{\n");
10689 *json_header_depth = 2;
10690 }
10691
d62a17ae 10692 vty_out(vty,
23d0a753
DA
10693 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10694 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10695 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10696 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10697 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10698 ? VRF_DEFAULT_NAME
10699 : bgp->name,
10700 table->version, &bgp->router_id,
01eced22 10701 bgp->default_local_pref, bgp->as);
9386b588 10702 if (rd) {
445c2480 10703 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10704 ++*json_header_depth;
10705 }
d62a17ae 10706 }
718e3744 10707
445c2480
DS
10708 if (use_json && rd) {
10709 vty_out(vty, " \"%s\" : { ", rd);
10710 }
10711
2aad8c42
MS
10712 /* Check for 'json detail', where we need header output once per dest */
10713 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10714 type != bgp_show_type_dampend_paths &&
10715 type != bgp_show_type_damp_neighbor &&
10716 type != bgp_show_type_flap_statistics &&
10717 type != bgp_show_type_flap_neighbor)
10718 json_detail_header = true;
10719
d62a17ae 10720 /* Start processing of routes. */
9bcb3eef
DS
10721 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10722 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10723 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10724 bool json_detail = json_detail_header;
b54892e0 10725
9bcb3eef 10726 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10727 if (pi == NULL)
98ce9a06 10728 continue;
d62a17ae 10729
98ce9a06 10730 display = 0;
98ce9a06
DS
10731 if (use_json)
10732 json_paths = json_object_new_array();
10733 else
10734 json_paths = NULL;
d62a17ae 10735
6f94b685 10736 for (; pi; pi = pi->next) {
98ce9a06 10737 total_count++;
1e2ce4f1 10738
7d3cae70
DA
10739 if (type == bgp_show_type_prefix_version) {
10740 uint32_t version =
10741 strtoul(output_arg, NULL, 10);
10742 if (dest->version < version)
10743 continue;
10744 }
10745
a70a28a5
DA
10746 if (type == bgp_show_type_community_alias) {
10747 char *alias = output_arg;
10748 char **communities;
10749 int num;
10750 bool found = false;
10751
10752 if (pi->attr->community) {
10753 frrstr_split(pi->attr->community->str,
10754 " ", &communities, &num);
10755 for (int i = 0; i < num; i++) {
10756 const char *com2alias =
10757 bgp_community2alias(
10758 communities[i]);
cd9cc0e6
IR
10759 if (!found
10760 && strcmp(alias, com2alias)
10761 == 0)
a70a28a5 10762 found = true;
cd9cc0e6
IR
10763 XFREE(MTYPE_TMP,
10764 communities[i]);
a70a28a5 10765 }
cd9cc0e6 10766 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10767 }
10768
10769 if (!found && pi->attr->lcommunity) {
10770 frrstr_split(pi->attr->lcommunity->str,
10771 " ", &communities, &num);
10772 for (int i = 0; i < num; i++) {
10773 const char *com2alias =
10774 bgp_community2alias(
10775 communities[i]);
cd9cc0e6
IR
10776 if (!found
10777 && strcmp(alias, com2alias)
10778 == 0)
a70a28a5 10779 found = true;
cd9cc0e6
IR
10780 XFREE(MTYPE_TMP,
10781 communities[i]);
a70a28a5 10782 }
cd9cc0e6 10783 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10784 }
10785
10786 if (!found)
10787 continue;
10788 }
10789
1e2ce4f1
DS
10790 if (type == bgp_show_type_rpki) {
10791 if (dest_p->family == AF_INET
10792 || dest_p->family == AF_INET6)
4027d19b 10793 rpki_curr_state = hook_call(
1e2ce4f1
DS
10794 bgp_rpki_prefix_status,
10795 pi->peer, pi->attr, dest_p);
4027d19b
DS
10796 if (rpki_target_state != RPKI_NOT_BEING_USED
10797 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10798 continue;
10799 }
10800
98ce9a06
DS
10801 if (type == bgp_show_type_flap_statistics
10802 || type == bgp_show_type_flap_neighbor
10803 || type == bgp_show_type_dampend_paths
10804 || type == bgp_show_type_damp_neighbor) {
40381db7 10805 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10806 continue;
10807 }
10808 if (type == bgp_show_type_regexp) {
10809 regex_t *regex = output_arg;
d62a17ae 10810
40381db7 10811 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10812 == REG_NOMATCH)
10813 continue;
10814 }
10815 if (type == bgp_show_type_prefix_list) {
10816 struct prefix_list *plist = output_arg;
d62a17ae 10817
9bcb3eef 10818 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10819 != PREFIX_PERMIT)
10820 continue;
10821 }
10822 if (type == bgp_show_type_filter_list) {
10823 struct as_list *as_list = output_arg;
d62a17ae 10824
40381db7 10825 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10826 != AS_FILTER_PERMIT)
10827 continue;
10828 }
10829 if (type == bgp_show_type_route_map) {
10830 struct route_map *rmap = output_arg;
9b6d8fcf 10831 struct bgp_path_info path;
98ce9a06 10832 struct attr dummy_attr;
b68885f9 10833 route_map_result_t ret;
d62a17ae 10834
6f4f49b2 10835 dummy_attr = *pi->attr;
d62a17ae 10836
40381db7 10837 path.peer = pi->peer;
9b6d8fcf 10838 path.attr = &dummy_attr;
d62a17ae 10839
1782514f 10840 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 10841 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
10842 if (ret == RMAP_DENYMATCH)
10843 continue;
10844 }
10845 if (type == bgp_show_type_neighbor
10846 || type == bgp_show_type_flap_neighbor
10847 || type == bgp_show_type_damp_neighbor) {
10848 union sockunion *su = output_arg;
10849
40381db7
DS
10850 if (pi->peer == NULL
10851 || pi->peer->su_remote == NULL
10852 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10853 continue;
10854 }
10855 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10856 uint32_t destination;
d62a17ae 10857
9bcb3eef 10858 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10859 if (IN_CLASSC(destination)
9bcb3eef 10860 && dest_p->prefixlen == 24)
98ce9a06
DS
10861 continue;
10862 if (IN_CLASSB(destination)
9bcb3eef 10863 && dest_p->prefixlen == 16)
98ce9a06
DS
10864 continue;
10865 if (IN_CLASSA(destination)
9bcb3eef 10866 && dest_p->prefixlen == 8)
98ce9a06
DS
10867 continue;
10868 }
10869 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10870 p = output_arg;
9bcb3eef 10871 if (!prefix_match(p, dest_p))
98ce9a06
DS
10872 continue;
10873 }
10874 if (type == bgp_show_type_community_all) {
40381db7 10875 if (!pi->attr->community)
98ce9a06
DS
10876 continue;
10877 }
10878 if (type == bgp_show_type_community) {
10879 struct community *com = output_arg;
d62a17ae 10880
40381db7
DS
10881 if (!pi->attr->community
10882 || !community_match(pi->attr->community,
98ce9a06
DS
10883 com))
10884 continue;
10885 }
10886 if (type == bgp_show_type_community_exact) {
10887 struct community *com = output_arg;
d62a17ae 10888
40381db7
DS
10889 if (!pi->attr->community
10890 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10891 continue;
10892 }
10893 if (type == bgp_show_type_community_list) {
10894 struct community_list *list = output_arg;
d62a17ae 10895
40381db7 10896 if (!community_list_match(pi->attr->community,
a4d82a8a 10897 list))
98ce9a06
DS
10898 continue;
10899 }
a4d82a8a 10900 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10901 struct community_list *list = output_arg;
d62a17ae 10902
98ce9a06 10903 if (!community_list_exact_match(
40381db7 10904 pi->attr->community, list))
98ce9a06
DS
10905 continue;
10906 }
10907 if (type == bgp_show_type_lcommunity) {
10908 struct lcommunity *lcom = output_arg;
d62a17ae 10909
40381db7
DS
10910 if (!pi->attr->lcommunity
10911 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10912 lcom))
10913 continue;
10914 }
36a206db 10915
10916 if (type == bgp_show_type_lcommunity_exact) {
10917 struct lcommunity *lcom = output_arg;
10918
10919 if (!pi->attr->lcommunity
10920 || !lcommunity_cmp(pi->attr->lcommunity,
10921 lcom))
10922 continue;
10923 }
98ce9a06
DS
10924 if (type == bgp_show_type_lcommunity_list) {
10925 struct community_list *list = output_arg;
d62a17ae 10926
40381db7 10927 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10928 list))
98ce9a06
DS
10929 continue;
10930 }
36a206db 10931 if (type
10932 == bgp_show_type_lcommunity_list_exact) {
10933 struct community_list *list = output_arg;
10934
10935 if (!lcommunity_list_exact_match(
10936 pi->attr->lcommunity, list))
10937 continue;
10938 }
98ce9a06 10939 if (type == bgp_show_type_lcommunity_all) {
40381db7 10940 if (!pi->attr->lcommunity)
98ce9a06
DS
10941 continue;
10942 }
10943 if (type == bgp_show_type_dampend_paths
10944 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10945 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10946 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10947 continue;
10948 }
10949
10950 if (!use_json && header) {
23d0a753
DA
10951 vty_out(vty,
10952 "BGP table version is %" PRIu64
10953 ", local router ID is %pI4, vrf id ",
10954 table->version, &bgp->router_id);
9df8b37c
PZ
10955 if (bgp->vrf_id == VRF_UNKNOWN)
10956 vty_out(vty, "%s", VRFID_NONE_STR);
10957 else
10958 vty_out(vty, "%u", bgp->vrf_id);
10959 vty_out(vty, "\n");
01eced22
AD
10960 vty_out(vty, "Default local pref %u, ",
10961 bgp->default_local_pref);
10962 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10963 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10964 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10965 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 10966 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 10967 if (type == bgp_show_type_dampend_paths
10968 || type == bgp_show_type_damp_neighbor)
98ce9a06 10969 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10970 else if (type == bgp_show_type_flap_statistics
10971 || type == bgp_show_type_flap_neighbor)
98ce9a06 10972 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10973 else
ae248832
MK
10974 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10975 : BGP_SHOW_HEADER));
2aad8c42
MS
10976 header = false;
10977
10978 } else if (json_detail && json_paths != NULL) {
10979 const struct prefix_rd *prd;
10980 json_object *jtemp;
10981
10982 /* Use common detail header, for most types;
10983 * need a json 'object'.
10984 */
10985
10986 jtemp = json_object_new_object();
10987 prd = bgp_rd_from_dest(dest, safi);
10988
10989 route_vty_out_detail_header(
10990 vty, bgp, dest, prd, table->afi,
10991 safi, jtemp);
10992
10993 json_object_array_add(json_paths, jtemp);
10994
10995 json_detail = false;
d62a17ae 10996 }
2aad8c42 10997
98ce9a06
DS
10998 if (rd != NULL && !display && !output_count) {
10999 if (!use_json)
11000 vty_out(vty,
11001 "Route Distinguisher: %s\n",
11002 rd);
d62a17ae 11003 }
98ce9a06
DS
11004 if (type == bgp_show_type_dampend_paths
11005 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11006 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11007 AFI_IP, safi, use_json,
11008 json_paths);
98ce9a06
DS
11009 else if (type == bgp_show_type_flap_statistics
11010 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11011 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11012 AFI_IP, safi, use_json,
11013 json_paths);
f280c93b
DA
11014 else {
11015 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11016 route_vty_out_detail(
11017 vty, bgp, dest, pi,
11018 family2afi(dest_p->family),
11019 safi, RPKI_NOT_BEING_USED,
11020 json_paths);
11021 else
11022 route_vty_out(vty, dest_p, pi, display,
11023 safi, json_paths, wide);
11024 }
98ce9a06 11025 display++;
d62a17ae 11026 }
11027
98ce9a06
DS
11028 if (display) {
11029 output_count++;
11030 if (!use_json)
11031 continue;
11032
625d2931 11033 /* encode prefix */
9bcb3eef 11034 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11035 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11036
1840384b 11037
b54892e0
DS
11038 bgp_fs_nlri_get_string(
11039 (unsigned char *)
9bcb3eef
DS
11040 dest_p->u.prefix_flowspec.ptr,
11041 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11042 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11043 family2afi(dest_p->u
11044 .prefix_flowspec.family));
625d2931 11045 if (first)
b54892e0 11046 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11047 dest_p->u.prefix_flowspec
b54892e0 11048 .prefixlen);
625d2931 11049 else
b54892e0 11050 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11051 dest_p->u.prefix_flowspec
b54892e0 11052 .prefixlen);
625d2931 11053 } else {
625d2931 11054 if (first)
1b78780b 11055 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11056 else
1b78780b 11057 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11058 }
98ce9a06 11059 vty_out(vty, "%s",
f4ec52f7
DA
11060 json_object_to_json_string_ext(
11061 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 11062 json_object_free(json_paths);
449feb8e 11063 json_paths = NULL;
98ce9a06 11064 first = 0;
1f83ed02
DS
11065 } else
11066 json_object_free(json_paths);
98ce9a06
DS
11067 }
11068
1ae44dfc
LB
11069 if (output_cum) {
11070 output_count += *output_cum;
11071 *output_cum = output_count;
11072 }
11073 if (total_cum) {
11074 total_count += *total_cum;
11075 *total_cum = total_count;
11076 }
d62a17ae 11077 if (use_json) {
9386b588 11078 if (rd) {
a4d82a8a 11079 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11080 }
11081 if (is_last) {
a4d82a8a
PZ
11082 unsigned long i;
11083 for (i = 0; i < *json_header_depth; ++i)
11084 vty_out(vty, " } ");
96f3485c
MK
11085 if (!all)
11086 vty_out(vty, "\n");
9386b588 11087 }
d62a17ae 11088 } else {
1ae44dfc
LB
11089 if (is_last) {
11090 /* No route is displayed */
11091 if (output_count == 0) {
11092 if (type == bgp_show_type_normal)
11093 vty_out(vty,
11094 "No BGP prefixes displayed, %ld exist\n",
11095 total_count);
11096 } else
d62a17ae 11097 vty_out(vty,
1ae44dfc
LB
11098 "\nDisplayed %ld routes and %ld total paths\n",
11099 output_count, total_count);
11100 }
d62a17ae 11101 }
718e3744 11102
d62a17ae 11103 return CMD_SUCCESS;
718e3744 11104}
11105
1ae44dfc
LB
11106int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11107 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11108 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11109{
9bcb3eef 11110 struct bgp_dest *dest, *next;
1ae44dfc
LB
11111 unsigned long output_cum = 0;
11112 unsigned long total_cum = 0;
9386b588 11113 unsigned long json_header_depth = 0;
67009e22 11114 struct bgp_table *itable;
0136788c 11115 bool show_msg;
96c81f66 11116 uint16_t show_flags = 0;
0136788c
LB
11117
11118 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11119
96f3485c
MK
11120 if (use_json)
11121 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11122
9bcb3eef
DS
11123 for (dest = bgp_table_top(table); dest; dest = next) {
11124 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11125
9bcb3eef
DS
11126 next = bgp_route_next(dest);
11127 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11128 continue;
67009e22 11129
9bcb3eef 11130 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11131 if (itable != NULL) {
1ae44dfc 11132 struct prefix_rd prd;
06b9f471 11133 char rd[RD_ADDRSTRLEN];
1ae44dfc 11134
9bcb3eef 11135 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11136 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11137 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11138 rd, next == NULL, &output_cum,
11139 &total_cum, &json_header_depth,
1e2ce4f1 11140 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11141 if (next == NULL)
11142 show_msg = false;
1ae44dfc
LB
11143 }
11144 }
0136788c
LB
11145 if (show_msg) {
11146 if (output_cum == 0)
11147 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11148 total_cum);
11149 else
11150 vty_out(vty,
11151 "\nDisplayed %ld routes and %ld total paths\n",
11152 output_cum, total_cum);
11153 }
1ae44dfc
LB
11154 return CMD_SUCCESS;
11155}
2aad8c42 11156
d62a17ae 11157static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11158 enum bgp_show_type type, void *output_arg,
96c81f66 11159 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11160{
d62a17ae 11161 struct bgp_table *table;
9386b588 11162 unsigned long json_header_depth = 0;
96f3485c 11163 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11164
d62a17ae 11165 if (bgp == NULL) {
11166 bgp = bgp_get_default();
11167 }
fee0f4c6 11168
d62a17ae 11169 if (bgp == NULL) {
11170 if (!use_json)
11171 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11172 else
11173 vty_out(vty, "{}\n");
d62a17ae 11174 return CMD_WARNING;
11175 }
4dd6177e 11176
cd8c2a27
MS
11177 /* Labeled-unicast routes live in the unicast table. */
11178 if (safi == SAFI_LABELED_UNICAST)
11179 safi = SAFI_UNICAST;
11180
1ae44dfc 11181 table = bgp->rib[afi][safi];
d62a17ae 11182 /* use MPLS and ENCAP specific shows until they are merged */
11183 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11184 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11185 output_arg, use_json);
d62a17ae 11186 }
dba3c1d3
PG
11187
11188 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11189 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11190 output_arg, use_json,
11191 1, NULL, NULL);
11192 }
fee0f4c6 11193
96f3485c 11194 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11195 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11196 rpki_target_state);
fee0f4c6 11197}
11198
d62a17ae 11199static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11200 safi_t safi, uint16_t show_flags)
f186de26 11201{
d62a17ae 11202 struct listnode *node, *nnode;
11203 struct bgp *bgp;
11204 int is_first = 1;
9f049418 11205 bool route_output = false;
96f3485c 11206 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11207
d62a17ae 11208 if (use_json)
11209 vty_out(vty, "{\n");
9f689658 11210
d62a17ae 11211 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11212 route_output = true;
d62a17ae 11213 if (use_json) {
11214 if (!is_first)
11215 vty_out(vty, ",\n");
11216 else
11217 is_first = 0;
11218
11219 vty_out(vty, "\"%s\":",
11220 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11221 ? VRF_DEFAULT_NAME
d62a17ae 11222 : bgp->name);
11223 } else {
11224 vty_out(vty, "\nInstance %s:\n",
11225 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11226 ? VRF_DEFAULT_NAME
d62a17ae 11227 : bgp->name);
11228 }
11229 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11230 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11231 }
9f689658 11232
d62a17ae 11233 if (use_json)
11234 vty_out(vty, "}\n");
9f049418
DS
11235 else if (!route_output)
11236 vty_out(vty, "%% BGP instance not found\n");
f186de26 11237}
11238
718e3744 11239/* Header of detailed BGP route information */
d62a17ae 11240void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11241 struct bgp_dest *dest,
11242 const struct prefix_rd *prd,
d62a17ae 11243 afi_t afi, safi_t safi, json_object *json)
11244{
40381db7 11245 struct bgp_path_info *pi;
b54892e0 11246 const struct prefix *p;
d62a17ae 11247 struct peer *peer;
11248 struct listnode *node, *nnode;
06b9f471 11249 char buf1[RD_ADDRSTRLEN];
0291c246 11250 char prefix_str[BUFSIZ];
d62a17ae 11251 int count = 0;
11252 int best = 0;
11253 int suppress = 0;
c5f1e1b2
C
11254 int accept_own = 0;
11255 int route_filter_translated_v4 = 0;
11256 int route_filter_v4 = 0;
11257 int route_filter_translated_v6 = 0;
11258 int route_filter_v6 = 0;
11259 int llgr_stale = 0;
11260 int no_llgr = 0;
11261 int accept_own_nexthop = 0;
11262 int blackhole = 0;
d62a17ae 11263 int no_export = 0;
11264 int no_advertise = 0;
11265 int local_as = 0;
c5f1e1b2 11266 int no_peer = 0;
d62a17ae 11267 int first = 1;
11268 int has_valid_label = 0;
11269 mpls_label_t label = 0;
11270 json_object *json_adv_to = NULL;
9bedbb1e 11271
9bcb3eef
DS
11272 p = bgp_dest_get_prefix(dest);
11273 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11274
11275 if (has_valid_label)
9bcb3eef 11276 label = label_pton(&dest->local_label);
d62a17ae 11277
44c69747 11278 if (safi == SAFI_EVPN) {
d62a17ae 11279
44c69747 11280 if (!json) {
2dbe669b 11281 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11282 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11283 : "",
2dbe669b 11284 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11285 } else {
11286 json_object_string_add(json, "rd",
11287 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11288 "");
11289 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11290 }
11291 } else {
11292 if (!json) {
9119ef3a
DA
11293 vty_out(vty,
11294 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11295 "\n",
d62a17ae 11296 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11297 ? prefix_rd2str(prd, buf1,
11298 sizeof(buf1))
11299 : ""),
9119ef3a
DA
11300 safi == SAFI_MPLS_VPN ? ":" : "", p,
11301 dest->version);
cd1964ff 11302
9119ef3a 11303 } else {
44c69747
LK
11304 json_object_string_add(json, "prefix",
11305 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11306 json_object_int_add(json, "version", dest->version);
11307
11308 }
44c69747
LK
11309 }
11310
11311 if (has_valid_label) {
11312 if (json)
11313 json_object_int_add(json, "localLabel", label);
11314 else
d62a17ae 11315 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11316 }
11317
11318 if (!json)
d62a17ae 11319 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11320 vty_out(vty, "not allocated\n");
718e3744 11321
9bcb3eef 11322 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11323 count++;
40381db7 11324 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11325 best = count;
4056a5f6 11326 if (bgp_path_suppressed(pi))
d62a17ae 11327 suppress = 1;
cee9c031 11328
40381db7 11329 if (pi->attr->community == NULL)
cee9c031
QY
11330 continue;
11331
11332 no_advertise += community_include(
40381db7
DS
11333 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11334 no_export += community_include(pi->attr->community,
cee9c031 11335 COMMUNITY_NO_EXPORT);
40381db7 11336 local_as += community_include(pi->attr->community,
cee9c031 11337 COMMUNITY_LOCAL_AS);
40381db7 11338 accept_own += community_include(pi->attr->community,
cee9c031
QY
11339 COMMUNITY_ACCEPT_OWN);
11340 route_filter_translated_v4 += community_include(
40381db7 11341 pi->attr->community,
cee9c031
QY
11342 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11343 route_filter_translated_v6 += community_include(
40381db7 11344 pi->attr->community,
cee9c031
QY
11345 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11346 route_filter_v4 += community_include(
40381db7 11347 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11348 route_filter_v6 += community_include(
40381db7
DS
11349 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11350 llgr_stale += community_include(pi->attr->community,
cee9c031 11351 COMMUNITY_LLGR_STALE);
40381db7 11352 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11353 COMMUNITY_NO_LLGR);
11354 accept_own_nexthop +=
40381db7 11355 community_include(pi->attr->community,
cee9c031 11356 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11357 blackhole += community_include(pi->attr->community,
cee9c031 11358 COMMUNITY_BLACKHOLE);
40381db7 11359 no_peer += community_include(pi->attr->community,
cee9c031 11360 COMMUNITY_NO_PEER);
d62a17ae 11361 }
718e3744 11362 }
718e3744 11363
d62a17ae 11364 if (!json) {
11365 vty_out(vty, "Paths: (%d available", count);
11366 if (best) {
11367 vty_out(vty, ", best #%d", best);
b84060bb
PG
11368 if (safi == SAFI_UNICAST) {
11369 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11370 vty_out(vty, ", table %s",
11371 VRF_DEFAULT_NAME);
11372 else
11373 vty_out(vty, ", vrf %s",
11374 bgp->name);
11375 }
d62a17ae 11376 } else
11377 vty_out(vty, ", no best path");
11378
c5f1e1b2
C
11379 if (accept_own)
11380 vty_out(vty,
11381 ", accept own local route exported and imported in different VRF");
11382 else if (route_filter_translated_v4)
11383 vty_out(vty,
11384 ", mark translated RTs for VPNv4 route filtering");
11385 else if (route_filter_v4)
11386 vty_out(vty,
11387 ", attach RT as-is for VPNv4 route filtering");
11388 else if (route_filter_translated_v6)
11389 vty_out(vty,
11390 ", mark translated RTs for VPNv6 route filtering");
11391 else if (route_filter_v6)
11392 vty_out(vty,
11393 ", attach RT as-is for VPNv6 route filtering");
11394 else if (llgr_stale)
11395 vty_out(vty,
11396 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11397 else if (no_llgr)
11398 vty_out(vty,
11399 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11400 else if (accept_own_nexthop)
11401 vty_out(vty,
11402 ", accept local nexthop");
11403 else if (blackhole)
11404 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11405 else if (no_export)
11406 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11407 else if (no_advertise)
11408 vty_out(vty, ", not advertised to any peer");
d62a17ae 11409 else if (local_as)
11410 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11411 else if (no_peer)
11412 vty_out(vty,
11413 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11414
11415 if (suppress)
11416 vty_out(vty,
11417 ", Advertisements suppressed by an aggregate.");
11418 vty_out(vty, ")\n");
11419 }
718e3744 11420
d62a17ae 11421 /* If we are not using addpath then we can display Advertised to and
11422 * that will
11423 * show what peers we advertised the bestpath to. If we are using
11424 * addpath
11425 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11426 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11427 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11428 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11429 if (json && !json_adv_to)
11430 json_adv_to = json_object_new_object();
11431
11432 route_vty_out_advertised_to(
11433 vty, peer, &first,
11434 " Advertised to non peer-group peers:\n ",
11435 json_adv_to);
11436 }
11437 }
11438
11439 if (json) {
11440 if (json_adv_to) {
11441 json_object_object_add(json, "advertisedTo",
11442 json_adv_to);
11443 }
11444 } else {
11445 if (first)
11446 vty_out(vty, " Not advertised to any peer");
11447 vty_out(vty, "\n");
11448 }
11449 }
718e3744 11450}
11451
edfee30d 11452static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11453 struct bgp_dest *bgp_node, struct vty *vty,
11454 struct bgp *bgp, afi_t afi, safi_t safi,
11455 json_object *json, enum bgp_path_type pathtype,
4027d19b 11456 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11457{
11458 struct bgp_path_info *pi;
11459 int header = 1;
11460 char rdbuf[RD_ADDRSTRLEN];
11461 json_object *json_header = NULL;
11462 json_object *json_paths = NULL;
4933eaaf 11463 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11464
9bcb3eef 11465 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11466 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11467
11468 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11469 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11470 pi->peer, pi->attr, p);
4933eaaf 11471
4027d19b
DS
11472 if (rpki_target_state != RPKI_NOT_BEING_USED
11473 && rpki_curr_state != rpki_target_state)
4933eaaf 11474 continue;
44c69747
LK
11475
11476 if (json && !json_paths) {
11477 /* Instantiate json_paths only if path is valid */
11478 json_paths = json_object_new_array();
11479 if (pfx_rd) {
11480 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11481 json_header = json_object_new_object();
11482 } else
11483 json_header = json;
11484 }
11485
11486 if (header) {
11487 route_vty_out_detail_header(
11488 vty, bgp, bgp_node, pfx_rd,
11489 AFI_IP, safi, json_header);
11490 header = 0;
11491 }
11492 (*display)++;
11493
11494 if (pathtype == BGP_PATH_SHOW_ALL
11495 || (pathtype == BGP_PATH_SHOW_BESTPATH
11496 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11497 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11498 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11499 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11500 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11501 safi, rpki_curr_state, json_paths);
44c69747
LK
11502 }
11503
11504 if (json && json_paths) {
11505 json_object_object_add(json_header, "paths", json_paths);
11506
11507 if (pfx_rd)
11508 json_object_object_add(json, rdbuf, json_header);
11509 }
11510}
11511
2aad8c42
MS
11512/*
11513 * Return rd based on safi
11514 */
11515static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11516 safi_t safi)
11517{
11518 switch (safi) {
11519 case SAFI_MPLS_VPN:
11520 case SAFI_ENCAP:
11521 case SAFI_EVPN:
11522 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11523 default:
11524 return NULL;
11525
11526 }
11527}
11528
718e3744 11529/* Display specified route of BGP table. */
d62a17ae 11530static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11531 struct bgp_table *rib, const char *ip_str,
11532 afi_t afi, safi_t safi,
4027d19b 11533 enum rpki_states rpki_target_state,
d62a17ae 11534 struct prefix_rd *prd, int prefix_check,
9f049418 11535 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11536{
11537 int ret;
d62a17ae 11538 int display = 0;
11539 struct prefix match;
9bcb3eef
DS
11540 struct bgp_dest *dest;
11541 struct bgp_dest *rm;
d62a17ae 11542 struct bgp_table *table;
11543 json_object *json = NULL;
11544 json_object *json_paths = NULL;
11545
11546 /* Check IP address argument. */
11547 ret = str2prefix(ip_str, &match);
11548 if (!ret) {
11549 vty_out(vty, "address is malformed\n");
11550 return CMD_WARNING;
11551 }
718e3744 11552
d62a17ae 11553 match.family = afi2family(afi);
b05a1c8b 11554
44c69747 11555 if (use_json)
d62a17ae 11556 json = json_object_new_object();
718e3744 11557
44c69747 11558 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11559 for (dest = bgp_table_top(rib); dest;
11560 dest = bgp_route_next(dest)) {
11561 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11562
9bcb3eef 11563 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11564 continue;
9bcb3eef 11565 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11566 if (!table)
ea47320b 11567 continue;
d62a17ae 11568
4953391b
DA
11569 rm = bgp_node_match(table, &match);
11570 if (rm == NULL)
ea47320b 11571 continue;
d62a17ae 11572
9bcb3eef 11573 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11574 if (prefix_check
b54892e0 11575 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11576 bgp_dest_unlock_node(rm);
ea47320b
DL
11577 continue;
11578 }
d62a17ae 11579
9bcb3eef 11580 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11581 bgp, afi, safi, json, pathtype,
4027d19b 11582 &display, rpki_target_state);
44c69747 11583
9bcb3eef 11584 bgp_dest_unlock_node(rm);
44c69747
LK
11585 }
11586 } else if (safi == SAFI_EVPN) {
9bcb3eef 11587 struct bgp_dest *longest_pfx;
cded3b72 11588 bool is_exact_pfxlen_match = false;
44c69747 11589
9bcb3eef
DS
11590 for (dest = bgp_table_top(rib); dest;
11591 dest = bgp_route_next(dest)) {
11592 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11593
9bcb3eef 11594 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11595 continue;
9bcb3eef 11596 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11597 if (!table)
11598 continue;
11599
11600 longest_pfx = NULL;
cded3b72 11601 is_exact_pfxlen_match = false;
44c69747
LK
11602 /*
11603 * Search through all the prefixes for a match. The
11604 * pfx's are enumerated in ascending order of pfxlens.
11605 * So, the last pfx match is the longest match. Set
11606 * is_exact_pfxlen_match when we get exact pfxlen match
11607 */
11608 for (rm = bgp_table_top(table); rm;
11609 rm = bgp_route_next(rm)) {
b54892e0 11610 const struct prefix *rm_p =
9bcb3eef 11611 bgp_dest_get_prefix(rm);
44c69747
LK
11612 /*
11613 * Get prefixlen of the ip-prefix within type5
11614 * evpn route
11615 */
b54892e0
DS
11616 if (evpn_type5_prefix_match(rm_p, &match)
11617 && rm->info) {
44c69747
LK
11618 longest_pfx = rm;
11619 int type5_pfxlen =
b54892e0
DS
11620 bgp_evpn_get_type5_prefixlen(
11621 rm_p);
44c69747 11622 if (type5_pfxlen == match.prefixlen) {
cded3b72 11623 is_exact_pfxlen_match = true;
9bcb3eef 11624 bgp_dest_unlock_node(rm);
44c69747
LK
11625 break;
11626 }
d62a17ae 11627 }
11628 }
ea47320b 11629
44c69747
LK
11630 if (!longest_pfx)
11631 continue;
11632
11633 if (prefix_check && !is_exact_pfxlen_match)
11634 continue;
11635
11636 rm = longest_pfx;
9bcb3eef 11637 bgp_dest_lock_node(rm);
44c69747 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);
d62a17ae 11644 }
98a9dbc7 11645 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11646 if (use_json)
11647 json_paths = json_object_new_array();
11648
63a0b7a9
PG
11649 display = bgp_flowspec_display_match_per_ip(afi, rib,
11650 &match, prefix_check,
11651 vty,
11652 use_json,
11653 json_paths);
d5f20468
SP
11654 if (use_json) {
11655 if (display)
11656 json_object_object_add(json, "paths",
11657 json_paths);
11658 else
11659 json_object_free(json_paths);
11660 }
d62a17ae 11661 } else {
4953391b
DA
11662 dest = bgp_node_match(rib, &match);
11663 if (dest != NULL) {
9bcb3eef 11664 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11665 if (!prefix_check
9bcb3eef
DS
11666 || dest_p->prefixlen == match.prefixlen) {
11667 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11668 safi, json, pathtype,
4027d19b 11669 &display, rpki_target_state);
d62a17ae 11670 }
11671
9bcb3eef 11672 bgp_dest_unlock_node(dest);
d62a17ae 11673 }
11674 }
e5eee9af 11675
d62a17ae 11676 if (use_json) {
996c9314 11677 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11678 json, JSON_C_TO_STRING_PRETTY |
11679 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11680 json_object_free(json);
11681 } else {
11682 if (!display) {
11683 vty_out(vty, "%% Network not in table\n");
11684 return CMD_WARNING;
11685 }
11686 }
b05a1c8b 11687
d62a17ae 11688 return CMD_SUCCESS;
718e3744 11689}
11690
fee0f4c6 11691/* Display specified route of Main RIB */
d62a17ae 11692static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11693 afi_t afi, safi_t safi, struct prefix_rd *prd,
11694 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11695 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11696{
9b86009a 11697 if (!bgp) {
d62a17ae 11698 bgp = bgp_get_default();
9b86009a
RW
11699 if (!bgp) {
11700 if (!use_json)
11701 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11702 else
11703 vty_out(vty, "{}\n");
9b86009a
RW
11704 return CMD_WARNING;
11705 }
11706 }
d62a17ae 11707
11708 /* labeled-unicast routes live in the unicast table */
11709 if (safi == SAFI_LABELED_UNICAST)
11710 safi = SAFI_UNICAST;
11711
11712 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11713 afi, safi, rpki_target_state, prd,
8aa22bbb 11714 prefix_check, pathtype, use_json);
d62a17ae 11715}
11716
11717static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11718 struct cmd_token **argv, bool exact, afi_t afi,
11719 safi_t safi, bool uj)
d62a17ae 11720{
11721 struct lcommunity *lcom;
11722 struct buffer *b;
11723 int i;
11724 char *str;
11725 int first = 0;
96c81f66 11726 uint16_t show_flags = 0;
4f28b2b5 11727 int ret;
96f3485c
MK
11728
11729 if (uj)
11730 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11731
11732 b = buffer_new(1024);
11733 for (i = 0; i < argc; i++) {
11734 if (first)
11735 buffer_putc(b, ' ');
11736 else {
11737 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11738 first = 1;
11739 buffer_putstr(b, argv[i]->arg);
11740 }
11741 }
11742 }
11743 buffer_putc(b, '\0');
57d187bc 11744
d62a17ae 11745 str = buffer_getstr(b);
11746 buffer_free(b);
57d187bc 11747
d62a17ae 11748 lcom = lcommunity_str2com(str);
11749 XFREE(MTYPE_TMP, str);
11750 if (!lcom) {
11751 vty_out(vty, "%% Large-community malformed\n");
11752 return CMD_WARNING;
11753 }
57d187bc 11754
4f28b2b5 11755 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11756 (exact ? bgp_show_type_lcommunity_exact
11757 : bgp_show_type_lcommunity),
11758 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11759
11760 lcommunity_free(&lcom);
11761 return ret;
57d187bc
JS
11762}
11763
d62a17ae 11764static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11765 const char *lcom, bool exact, afi_t afi,
11766 safi_t safi, bool uj)
57d187bc 11767{
d62a17ae 11768 struct community_list *list;
96c81f66 11769 uint16_t show_flags = 0;
96f3485c
MK
11770
11771 if (uj)
11772 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11773
57d187bc 11774
e237b0d2 11775 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11776 LARGE_COMMUNITY_LIST_MASTER);
11777 if (list == NULL) {
11778 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11779 lcom);
11780 return CMD_WARNING;
11781 }
57d187bc 11782
36a206db 11783 return bgp_show(vty, bgp, afi, safi,
11784 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11785 : bgp_show_type_lcommunity_list),
1e2ce4f1 11786 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11787}
11788
52951b63
DS
11789DEFUN (show_ip_bgp_large_community_list,
11790 show_ip_bgp_large_community_list_cmd,
77a3a95e 11791 "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
11792 SHOW_STR
11793 IP_STR
11794 BGP_STR
11795 BGP_INSTANCE_HELP_STR
9bedbb1e 11796 BGP_AFI_HELP_STR
4dd6177e 11797 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11798 "Display routes matching the large-community-list\n"
11799 "large-community-list number\n"
11800 "large-community-list name\n"
36a206db 11801 "Exact match of the large-communities\n"
52951b63
DS
11802 JSON_STR)
11803{
d62a17ae 11804 afi_t afi = AFI_IP6;
11805 safi_t safi = SAFI_UNICAST;
11806 int idx = 0;
36a206db 11807 bool exact_match = 0;
4d678463 11808 struct bgp *bgp = NULL;
9f049418 11809 bool uj = use_json(argc, argv);
d62a17ae 11810
ef3364f0
DA
11811 if (uj)
11812 argc--;
4d678463 11813
ef3364f0
DA
11814 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11815 &bgp, uj);
11816 if (!idx)
11817 return CMD_WARNING;
d62a17ae 11818
11819 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11820
11821 const char *clist_number_or_name = argv[++idx]->arg;
11822
11823 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11824 exact_match = 1;
11825
11826 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11827 exact_match, afi, safi, uj);
52951b63
DS
11828}
11829DEFUN (show_ip_bgp_large_community,
11830 show_ip_bgp_large_community_cmd,
36a206db 11831 "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
11832 SHOW_STR
11833 IP_STR
11834 BGP_STR
11835 BGP_INSTANCE_HELP_STR
9bedbb1e 11836 BGP_AFI_HELP_STR
4dd6177e 11837 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11838 "Display routes matching the large-communities\n"
11839 "List of large-community numbers\n"
36a206db 11840 "Exact match of the large-communities\n"
52951b63
DS
11841 JSON_STR)
11842{
d62a17ae 11843 afi_t afi = AFI_IP6;
11844 safi_t safi = SAFI_UNICAST;
11845 int idx = 0;
36a206db 11846 bool exact_match = 0;
4d678463 11847 struct bgp *bgp = NULL;
9f049418 11848 bool uj = use_json(argc, argv);
96c81f66 11849 uint16_t show_flags = 0;
d62a17ae 11850
96f3485c
MK
11851 if (uj) {
11852 argc--;
11853 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11854 }
4d678463 11855
96f3485c
MK
11856 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11857 &bgp, uj);
11858 if (!idx)
11859 return CMD_WARNING;
d62a17ae 11860
36a206db 11861 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11862 if (argv_find(argv, argc, "exact-match", &idx))
11863 exact_match = 1;
11864 return bgp_show_lcommunity(vty, bgp, argc, argv,
11865 exact_match, afi, safi, uj);
11866 } else
d62a17ae 11867 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11868 bgp_show_type_lcommunity_all, NULL, show_flags,
11869 RPKI_NOT_BEING_USED);
52951b63
DS
11870}
11871
71f1613a
DA
11872static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11873 safi_t safi, struct json_object *json_array);
d62a17ae 11874static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11875 safi_t safi, struct json_object *json);
e01ca200 11876
7b2ff250 11877
9ab0cf58
PG
11878DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11879 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11880 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11881 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11882{
11883 bool uj = use_json(argc, argv);
11884 struct bgp *bgp = NULL;
ec76a1d1
DA
11885 safi_t safi = SAFI_UNICAST;
11886 afi_t afi = AFI_IP6;
4265b261 11887 int idx = 0;
6c9d22e2
PG
11888 struct json_object *json_all = NULL;
11889 struct json_object *json_afi_safi = NULL;
4265b261
PG
11890
11891 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11892 &bgp, false);
71f1613a 11893 if (!idx)
4265b261 11894 return CMD_WARNING;
6c9d22e2 11895
4265b261 11896 if (uj)
6c9d22e2 11897 json_all = json_object_new_object();
4265b261 11898
9ab0cf58
PG
11899 FOREACH_AFI_SAFI (afi, safi) {
11900 /*
11901 * So limit output to those afi/safi pairs that
11902 * actually have something interesting in them
11903 */
11904 if (strmatch(get_afi_safi_str(afi, safi, true),
11905 "Unknown")) {
11906 continue;
11907 }
11908 if (uj) {
11909 json_afi_safi = json_object_new_array();
11910 json_object_object_add(
11911 json_all,
11912 get_afi_safi_str(afi, safi, true),
11913 json_afi_safi);
11914 } else {
11915 json_afi_safi = NULL;
6c9d22e2 11916 }
9ab0cf58
PG
11917
11918 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11919 }
6c9d22e2
PG
11920
11921 if (uj) {
9ab0cf58
PG
11922 vty_out(vty, "%s",
11923 json_object_to_json_string_ext(
11924 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11925 json_object_free(json_all);
4265b261 11926 }
6c9d22e2 11927
4265b261
PG
11928 return CMD_SUCCESS;
11929}
11930
7b2ff250 11931/* BGP route print out function without JSON */
14718643
PG
11932DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11933 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11934 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11935 SHOW_STR
11936 IP_STR
11937 BGP_STR
11938 BGP_INSTANCE_HELP_STR
11939 L2VPN_HELP_STR
11940 EVPN_HELP_STR
11941 "BGP RIB advertisement statistics\n"
11942 JSON_STR)
11943{
ec76a1d1
DA
11944 afi_t afi = AFI_IP6;
11945 safi_t safi = SAFI_UNICAST;
14718643
PG
11946 struct bgp *bgp = NULL;
11947 int idx = 0, ret;
11948 bool uj = use_json(argc, argv);
11949 struct json_object *json_afi_safi = NULL, *json = NULL;
11950
11951 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11952 &bgp, false);
11953 if (!idx)
11954 return CMD_WARNING;
11955
11956 if (uj)
11957 json_afi_safi = json_object_new_array();
11958 else
11959 json_afi_safi = NULL;
11960
11961 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11962
11963 if (uj) {
11964 json = json_object_new_object();
11965 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11966 json_afi_safi);
11967 vty_out(vty, "%s", json_object_to_json_string_ext(
11968 json, JSON_C_TO_STRING_PRETTY));
11969 json_object_free(json);
11970 }
11971 return ret;
11972}
11973
893cccd0 11974/* BGP route print out function without JSON */
9ab0cf58
PG
11975DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11976 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11977 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11978 "]]\
893cccd0 11979 statistics [json]",
9ab0cf58
PG
11980 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11981 BGP_SAFI_WITH_LABEL_HELP_STR
11982 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11983{
ec76a1d1
DA
11984 afi_t afi = AFI_IP6;
11985 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11986 struct bgp *bgp = NULL;
11987 int idx = 0, ret;
11988 bool uj = use_json(argc, argv);
6c9d22e2 11989 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11990
11991 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11992 &bgp, false);
11993 if (!idx)
11994 return CMD_WARNING;
6c9d22e2 11995
893cccd0 11996 if (uj)
6c9d22e2
PG
11997 json_afi_safi = json_object_new_array();
11998 else
11999 json_afi_safi = NULL;
12000
12001 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12002
12003 if (uj) {
12004 json = json_object_new_object();
12005 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12006 json_afi_safi);
9ab0cf58
PG
12007 vty_out(vty, "%s",
12008 json_object_to_json_string_ext(
12009 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
12010 json_object_free(json);
12011 }
12012 return ret;
893cccd0 12013}
7b2ff250
DW
12014
12015/* BGP route print out function without JSON */
96f3485c 12016DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
12017 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12018 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12019 "]]\
96f3485c 12020 <[all$all] dampening <parameters>\
7b2ff250
DW
12021 |route-map WORD\
12022 |prefix-list WORD\
de71d43e 12023 |filter-list AS_PATH_FILTER_NAME\
96870ecb 12024 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
7b2ff250
DW
12025 |A.B.C.D/M longer-prefixes\
12026 |X:X::X:X/M longer-prefixes\
893cccd0 12027 >",
9ab0cf58
PG
12028 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12029 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12030 "Display the entries for all address families\n"
9ab0cf58
PG
12031 "Display detailed information about dampening\n"
12032 "Display detail of configured dampening parameters\n"
12033 "Display routes matching the route-map\n"
12034 "A route-map to match on\n"
12035 "Display routes conforming to the prefix-list\n"
12036 "Prefix-list name\n"
12037 "Display routes conforming to the filter-list\n"
12038 "Regular expression access list name\n"
12039 "Display routes matching the community-list\n"
12040 "community-list number\n"
12041 "community-list name\n"
12042 "Exact match of the communities\n"
12043 "IPv4 prefix\n"
12044 "Display route and more specific routes\n"
12045 "IPv6 prefix\n"
12046 "Display route and more specific routes\n")
718e3744 12047{
d62a17ae 12048 afi_t afi = AFI_IP6;
12049 safi_t safi = SAFI_UNICAST;
12050 int exact_match = 0;
d62a17ae 12051 struct bgp *bgp = NULL;
12052 int idx = 0;
96c81f66 12053 uint16_t show_flags = 0;
96f3485c
MK
12054
12055 /* [<ipv4|ipv6> [all]] */
12056 if (all) {
12057 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12058 if (argv_find(argv, argc, "ipv4", &idx))
12059 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12060
12061 if (argv_find(argv, argc, "ipv6", &idx))
12062 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12063 }
d62a17ae 12064
12065 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12066 &bgp, false);
d62a17ae 12067 if (!idx)
12068 return CMD_WARNING;
12069
d62a17ae 12070 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 12071 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
12072 return bgp_show_dampening_parameters(vty, afi, safi,
12073 show_flags);
d62a17ae 12074 }
c016b6c7 12075
d62a17ae 12076 if (argv_find(argv, argc, "prefix-list", &idx))
12077 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
12078 safi, bgp_show_type_prefix_list);
12079
12080 if (argv_find(argv, argc, "filter-list", &idx))
12081 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
12082 safi, bgp_show_type_filter_list);
12083
d62a17ae 12084 if (argv_find(argv, argc, "route-map", &idx))
12085 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
12086 safi, bgp_show_type_route_map);
12087
d62a17ae 12088 if (argv_find(argv, argc, "community-list", &idx)) {
12089 const char *clist_number_or_name = argv[++idx]->arg;
12090 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12091 exact_match = 1;
12092 return bgp_show_community_list(vty, bgp, clist_number_or_name,
12093 exact_match, afi, safi);
12094 }
12095 /* prefix-longer */
12096 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12097 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12098 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
12099 safi,
12100 bgp_show_type_prefix_longer);
12101
7b2ff250
DW
12102 return CMD_WARNING;
12103}
12104
12105/* BGP route print out function with JSON */
a70a28a5
DA
12106DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
12107 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12108 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12109 "]]\
96f3485c 12110 [all$all]\
cf4898bc
QY
12111 [cidr-only\
12112 |dampening <flap-statistics|dampened-paths>\
12113 |community [AA:NN|local-AS|no-advertise|no-export\
12114 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12115 |accept-own|accept-own-nexthop|route-filter-v6\
12116 |route-filter-v4|route-filter-translated-v6\
12117 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 12118 |rpki <invalid|valid|notfound>\
7d3cae70 12119 |version (1-4294967295)\
b4ad2fae 12120 |alias ALIAS_NAME\
f280c93b 12121 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12122 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12123 BGP_SAFI_WITH_LABEL_HELP_STR
12124 "Display the entries for all address families\n"
12125 "Display only routes with non-natural netmasks\n"
12126 "Display detailed information about dampening\n"
12127 "Display flap statistics of routes\n"
12128 "Display paths suppressed due to dampening\n"
12129 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12130 "Do not send outside local AS (well-known community)\n"
12131 "Do not advertise to any peer (well-known community)\n"
12132 "Do not export to next AS (well-known community)\n"
12133 "Graceful shutdown (well-known community)\n"
12134 "Do not export to any peer (well-known community)\n"
12135 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12136 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12137 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12138 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12139 "Should accept VPN route with local nexthop (well-known community)\n"
12140 "RT VPNv6 route filtering (well-known community)\n"
12141 "RT VPNv4 route filtering (well-known community)\n"
12142 "RT translated VPNv6 route filtering (well-known community)\n"
12143 "RT translated VPNv4 route filtering (well-known community)\n"
12144 "Exact match of the communities\n"
12145 "RPKI route types\n"
12146 "A valid path as determined by rpki\n"
12147 "A invalid path as determined by rpki\n"
12148 "A path that has no rpki data\n"
12149 "Display prefixes with matching version numbers\n"
12150 "Version number and above\n"
12151 "Display prefixes with matching BGP community alias\n"
12152 "BGP community alias\n" JSON_STR
12153 "Display detailed version of JSON output\n"
12154 "Increase table width for longer prefixes\n")
7b2ff250
DW
12155{
12156 afi_t afi = AFI_IP6;
12157 safi_t safi = SAFI_UNICAST;
12158 enum bgp_show_type sh_type = bgp_show_type_normal;
12159 struct bgp *bgp = NULL;
12160 int idx = 0;
d0086e8e 12161 int exact_match = 0;
96f3485c 12162 char *community = NULL;
7d3cae70 12163 char *prefix_version = NULL;
a70a28a5 12164 char *bgp_community_alias = NULL;
96f3485c 12165 bool first = true;
96c81f66 12166 uint16_t show_flags = 0;
4027d19b 12167 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12168
12169 if (uj) {
9f049418 12170 argc--;
96f3485c
MK
12171 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12172 }
12173
f280c93b
DA
12174 if (detail)
12175 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12176
96f3485c
MK
12177 /* [<ipv4|ipv6> [all]] */
12178 if (all) {
12179 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12180
12181 if (argv_find(argv, argc, "ipv4", &idx))
12182 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12183
12184 if (argv_find(argv, argc, "ipv6", &idx))
12185 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12186 }
12187
12188 if (wide)
12189 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12190
12191 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12192 &bgp, uj);
7b2ff250
DW
12193 if (!idx)
12194 return CMD_WARNING;
12195
7b2ff250 12196 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12197 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12198
12199 if (argv_find(argv, argc, "dampening", &idx)) {
12200 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12201 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12202 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12203 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12204 }
12205
12206 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12207 char *maybecomm = NULL;
d0086e8e 12208
79bc257a
RW
12209 if (idx + 1 < argc) {
12210 if (argv[idx + 1]->type == VARIABLE_TKN)
12211 maybecomm = argv[idx + 1]->arg;
12212 else
12213 maybecomm = argv[idx + 1]->text;
12214 }
12215
cf4898bc
QY
12216 if (maybecomm && !strmatch(maybecomm, "json")
12217 && !strmatch(maybecomm, "exact-match"))
12218 community = maybecomm;
d0086e8e 12219
cf4898bc
QY
12220 if (argv_find(argv, argc, "exact-match", &idx))
12221 exact_match = 1;
d0086e8e 12222
96f3485c
MK
12223 if (!community)
12224 sh_type = bgp_show_type_community_all;
12225 }
12226
1e2ce4f1
DS
12227 if (argv_find(argv, argc, "rpki", &idx)) {
12228 sh_type = bgp_show_type_rpki;
12229 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12230 rpki_target_state = RPKI_VALID;
1e2ce4f1 12231 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12232 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12233 }
12234
7d3cae70
DA
12235 /* Display prefixes with matching version numbers */
12236 if (argv_find(argv, argc, "version", &idx)) {
12237 sh_type = bgp_show_type_prefix_version;
12238 prefix_version = argv[idx + 1]->arg;
12239 }
12240
a70a28a5
DA
12241 /* Display prefixes with matching BGP community alias */
12242 if (argv_find(argv, argc, "alias", &idx)) {
12243 sh_type = bgp_show_type_community_alias;
12244 bgp_community_alias = argv[idx + 1]->arg;
12245 }
12246
96f3485c
MK
12247 if (!all) {
12248 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12249 if (community)
12250 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12251 exact_match, afi, safi,
12252 show_flags);
7d3cae70
DA
12253 else if (prefix_version)
12254 return bgp_show(vty, bgp, afi, safi, sh_type,
12255 prefix_version, show_flags,
12256 rpki_target_state);
a70a28a5
DA
12257 else if (bgp_community_alias)
12258 return bgp_show(vty, bgp, afi, safi, sh_type,
12259 bgp_community_alias, show_flags,
12260 rpki_target_state);
cf4898bc 12261 else
96f3485c 12262 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12263 show_flags, rpki_target_state);
96f3485c
MK
12264 } else {
12265 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12266 * AFI_IP6 */
12267
12268 if (uj)
12269 vty_out(vty, "{\n");
12270
12271 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12272 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12273 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12274 ? AFI_IP
12275 : AFI_IP6;
12276 FOREACH_SAFI (safi) {
96f3485c
MK
12277 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12278 continue;
12279
12280 if (uj) {
12281 if (first)
12282 first = false;
12283 else
12284 vty_out(vty, ",\n");
12285 vty_out(vty, "\"%s\":{\n",
12286 get_afi_safi_str(afi, safi,
12287 true));
12288 } else
12289 vty_out(vty,
12290 "\nFor address family: %s\n",
12291 get_afi_safi_str(afi, safi,
12292 false));
12293
12294 if (community)
12295 bgp_show_community(vty, bgp, community,
12296 exact_match, afi,
12297 safi, show_flags);
7d3cae70
DA
12298 else if (prefix_version)
12299 return bgp_show(vty, bgp, afi, safi,
12300 sh_type, prefix_version,
12301 show_flags,
12302 rpki_target_state);
a70a28a5
DA
12303 else if (bgp_community_alias)
12304 return bgp_show(
12305 vty, bgp, afi, safi, sh_type,
12306 bgp_community_alias, show_flags,
12307 rpki_target_state);
96f3485c
MK
12308 else
12309 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12310 NULL, show_flags,
4027d19b 12311 rpki_target_state);
96f3485c
MK
12312 if (uj)
12313 vty_out(vty, "}\n");
12314 }
12315 } else {
12316 /* show <ip> bgp all: for each AFI and SAFI*/
12317 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12318 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12319 continue;
12320
12321 if (uj) {
12322 if (first)
12323 first = false;
12324 else
12325 vty_out(vty, ",\n");
d0086e8e 12326
96f3485c
MK
12327 vty_out(vty, "\"%s\":{\n",
12328 get_afi_safi_str(afi, safi,
12329 true));
12330 } else
12331 vty_out(vty,
12332 "\nFor address family: %s\n",
12333 get_afi_safi_str(afi, safi,
12334 false));
12335
12336 if (community)
12337 bgp_show_community(vty, bgp, community,
12338 exact_match, afi,
12339 safi, show_flags);
7d3cae70
DA
12340 else if (prefix_version)
12341 return bgp_show(vty, bgp, afi, safi,
12342 sh_type, prefix_version,
12343 show_flags,
12344 rpki_target_state);
96f3485c
MK
12345 else
12346 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12347 NULL, show_flags,
4027d19b 12348 rpki_target_state);
96f3485c
MK
12349 if (uj)
12350 vty_out(vty, "}\n");
12351 }
12352 }
12353 if (uj)
12354 vty_out(vty, "}\n");
12355 }
12356 return CMD_SUCCESS;
a636c635 12357}
47fc97cc 12358
718e3744 12359DEFUN (show_ip_bgp_route,
12360 show_ip_bgp_route_cmd,
8aa22bbb 12361 "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 12362 SHOW_STR
12363 IP_STR
12364 BGP_STR
a636c635 12365 BGP_INSTANCE_HELP_STR
4f280b15 12366 BGP_AFI_HELP_STR
4dd6177e 12367 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12368 "Network in the BGP routing table to display\n"
0c7b1b01 12369 "IPv4 prefix\n"
8c3deaae 12370 "Network in the BGP routing table to display\n"
0c7b1b01 12371 "IPv6 prefix\n"
4092b06c 12372 "Display only the bestpath\n"
b05a1c8b 12373 "Display only multipaths\n"
8aa22bbb
DS
12374 "Display only paths that match the specified rpki state\n"
12375 "A valid path as determined by rpki\n"
12376 "A invalid path as determined by rpki\n"
12377 "A path that has no rpki data\n"
9973d184 12378 JSON_STR)
4092b06c 12379{
d62a17ae 12380 int prefix_check = 0;
ae19d7dd 12381
d62a17ae 12382 afi_t afi = AFI_IP6;
12383 safi_t safi = SAFI_UNICAST;
12384 char *prefix = NULL;
12385 struct bgp *bgp = NULL;
12386 enum bgp_path_type path_type;
9f049418 12387 bool uj = use_json(argc, argv);
b05a1c8b 12388
d62a17ae 12389 int idx = 0;
ae19d7dd 12390
d62a17ae 12391 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12392 &bgp, uj);
d62a17ae 12393 if (!idx)
12394 return CMD_WARNING;
c41247f5 12395
d62a17ae 12396 if (!bgp) {
12397 vty_out(vty,
12398 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12399 return CMD_WARNING;
12400 }
a636c635 12401
d62a17ae 12402 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12403 if (argv_find(argv, argc, "A.B.C.D", &idx)
12404 || argv_find(argv, argc, "X:X::X:X", &idx))
12405 prefix_check = 0;
12406 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12407 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12408 prefix_check = 1;
12409
12410 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12411 && afi != AFI_IP6) {
12412 vty_out(vty,
12413 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12414 return CMD_WARNING;
12415 }
12416 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12417 && afi != AFI_IP) {
12418 vty_out(vty,
12419 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12420 return CMD_WARNING;
12421 }
12422
12423 prefix = argv[idx]->arg;
12424
12425 /* [<bestpath|multipath>] */
12426 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12427 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12428 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12429 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12430 else
360660c6 12431 path_type = BGP_PATH_SHOW_ALL;
a636c635 12432
d62a17ae 12433 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12434 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12435}
12436
8c3deaae
QY
12437DEFUN (show_ip_bgp_regexp,
12438 show_ip_bgp_regexp_cmd,
3e5b31b3 12439 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12440 SHOW_STR
12441 IP_STR
12442 BGP_STR
b00b230a 12443 BGP_INSTANCE_HELP_STR
4f280b15 12444 BGP_AFI_HELP_STR
4dd6177e 12445 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12446 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12447 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12448 JSON_STR)
8c3deaae 12449{
d62a17ae 12450 afi_t afi = AFI_IP6;
12451 safi_t safi = SAFI_UNICAST;
12452 struct bgp *bgp = NULL;
3e5b31b3
DA
12453 bool uj = use_json(argc, argv);
12454 char *regstr = NULL;
8c3deaae 12455
d62a17ae 12456 int idx = 0;
12457 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12458 &bgp, false);
d62a17ae 12459 if (!idx)
12460 return CMD_WARNING;
8c3deaae 12461
d62a17ae 12462 // get index of regex
3e5b31b3
DA
12463 if (argv_find(argv, argc, "REGEX", &idx))
12464 regstr = argv[idx]->arg;
8c3deaae 12465
5f71d11c 12466 assert(regstr);
3e5b31b3
DA
12467 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12468 bgp_show_type_regexp, uj);
8c3deaae
QY
12469}
12470
ae248832 12471DEFPY (show_ip_bgp_instance_all,
a636c635 12472 show_ip_bgp_instance_all_cmd,
ae248832 12473 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12474 SHOW_STR
a636c635 12475 IP_STR
4092b06c 12476 BGP_STR
a636c635 12477 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12478 BGP_AFI_HELP_STR
4dd6177e 12479 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12480 JSON_STR
12481 "Increase table width for longer prefixes\n")
4092b06c 12482{
54d05dea 12483 afi_t afi = AFI_IP6;
d62a17ae 12484 safi_t safi = SAFI_UNICAST;
12485 struct bgp *bgp = NULL;
d62a17ae 12486 int idx = 0;
96c81f66 12487 uint16_t show_flags = 0;
ae19d7dd 12488
96f3485c 12489 if (uj) {
d62a17ae 12490 argc--;
96f3485c
MK
12491 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12492 }
12493
12494 if (wide)
12495 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12496
9f049418
DS
12497 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12498 &bgp, uj);
12499 if (!idx)
12500 return CMD_WARNING;
12501
96f3485c 12502 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12503 return CMD_SUCCESS;
e3e29b32
LB
12504}
12505
a4d82a8a 12506static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12507 afi_t afi, safi_t safi, enum bgp_show_type type,
12508 bool use_json)
718e3744 12509{
d62a17ae 12510 regex_t *regex;
12511 int rc;
96c81f66 12512 uint16_t show_flags = 0;
96f3485c
MK
12513
12514 if (use_json)
12515 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12516
c3900853 12517 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12518 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12519 regstr);
12520 return CMD_WARNING_CONFIG_FAILED;
12521 }
12522
d62a17ae 12523 regex = bgp_regcomp(regstr);
12524 if (!regex) {
12525 vty_out(vty, "Can't compile regexp %s\n", regstr);
12526 return CMD_WARNING;
12527 }
a636c635 12528
1e2ce4f1
DS
12529 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12530 RPKI_NOT_BEING_USED);
d62a17ae 12531 bgp_regex_free(regex);
12532 return rc;
e3e29b32
LB
12533}
12534
d62a17ae 12535static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12536 const char *prefix_list_str, afi_t afi,
12537 safi_t safi, enum bgp_show_type type)
e3e29b32 12538{
d62a17ae 12539 struct prefix_list *plist;
96c81f66 12540 uint16_t show_flags = 0;
718e3744 12541
d62a17ae 12542 plist = prefix_list_lookup(afi, prefix_list_str);
12543 if (plist == NULL) {
12544 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12545 prefix_list_str);
12546 return CMD_WARNING;
12547 }
718e3744 12548
1e2ce4f1
DS
12549 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12550 RPKI_NOT_BEING_USED);
4092b06c
DS
12551}
12552
d62a17ae 12553static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12554 const char *filter, afi_t afi, safi_t safi,
12555 enum bgp_show_type type)
4092b06c 12556{
d62a17ae 12557 struct as_list *as_list;
96c81f66 12558 uint16_t show_flags = 0;
718e3744 12559
d62a17ae 12560 as_list = as_list_lookup(filter);
12561 if (as_list == NULL) {
12562 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12563 filter);
12564 return CMD_WARNING;
12565 }
a636c635 12566
1e2ce4f1
DS
12567 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12568 RPKI_NOT_BEING_USED);
718e3744 12569}
12570
d62a17ae 12571static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12572 const char *rmap_str, afi_t afi, safi_t safi,
12573 enum bgp_show_type type)
718e3744 12574{
d62a17ae 12575 struct route_map *rmap;
96c81f66 12576 uint16_t show_flags = 0;
bb46e94f 12577
d62a17ae 12578 rmap = route_map_lookup_by_name(rmap_str);
12579 if (!rmap) {
12580 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12581 return CMD_WARNING;
12582 }
12583
1e2ce4f1
DS
12584 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12585 RPKI_NOT_BEING_USED);
d62a17ae 12586}
12587
7f323236
DW
12588static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12589 const char *comstr, int exact, afi_t afi,
96c81f66 12590 safi_t safi, uint16_t show_flags)
d62a17ae 12591{
12592 struct community *com;
d62a17ae 12593 int ret = 0;
12594
7f323236 12595 com = community_str2com(comstr);
d62a17ae 12596 if (!com) {
7f323236 12597 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12598 return CMD_WARNING;
12599 }
12600
12601 ret = bgp_show(vty, bgp, afi, safi,
12602 (exact ? bgp_show_type_community_exact
12603 : bgp_show_type_community),
1e2ce4f1 12604 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12605 community_free(&com);
46c3ce83 12606
d62a17ae 12607 return ret;
718e3744 12608}
12609
d62a17ae 12610static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12611 const char *com, int exact, afi_t afi,
12612 safi_t safi)
50ef26d4 12613{
d62a17ae 12614 struct community_list *list;
96c81f66 12615 uint16_t show_flags = 0;
50ef26d4 12616
e237b0d2 12617 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12618 if (list == NULL) {
12619 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12620 return CMD_WARNING;
12621 }
718e3744 12622
d62a17ae 12623 return bgp_show(vty, bgp, afi, safi,
12624 (exact ? bgp_show_type_community_list_exact
12625 : bgp_show_type_community_list),
1e2ce4f1 12626 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12627}
12628
d62a17ae 12629static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12630 const char *prefix, afi_t afi, safi_t safi,
12631 enum bgp_show_type type)
718e3744 12632{
d62a17ae 12633 int ret;
12634 struct prefix *p;
96c81f66 12635 uint16_t show_flags = 0;
47fc97cc 12636
d62a17ae 12637 p = prefix_new();
95cbbd2a 12638
d62a17ae 12639 ret = str2prefix(prefix, p);
12640 if (!ret) {
12641 vty_out(vty, "%% Malformed Prefix\n");
12642 return CMD_WARNING;
12643 }
47e9b292 12644
1e2ce4f1
DS
12645 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12646 RPKI_NOT_BEING_USED);
63265b5c 12647 prefix_free(&p);
d62a17ae 12648 return ret;
12649}
12650
d62a17ae 12651enum bgp_stats {
12652 BGP_STATS_MAXBITLEN = 0,
12653 BGP_STATS_RIB,
12654 BGP_STATS_PREFIXES,
12655 BGP_STATS_TOTPLEN,
12656 BGP_STATS_UNAGGREGATEABLE,
12657 BGP_STATS_MAX_AGGREGATEABLE,
12658 BGP_STATS_AGGREGATES,
12659 BGP_STATS_SPACE,
12660 BGP_STATS_ASPATH_COUNT,
12661 BGP_STATS_ASPATH_MAXHOPS,
12662 BGP_STATS_ASPATH_TOTHOPS,
12663 BGP_STATS_ASPATH_MAXSIZE,
12664 BGP_STATS_ASPATH_TOTSIZE,
12665 BGP_STATS_ASN_HIGHEST,
12666 BGP_STATS_MAX,
a636c635 12667};
2815e61f 12668
9ab0cf58 12669#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12670#define TABLE_STATS_IDX_JSON 1
12671
12672static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12673 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12674 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12675 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12676 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12677 "unaggregateablePrefixes"},
12678 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12679 "maximumAggregateablePrefixes"},
12680 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12681 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12682 [BGP_STATS_SPACE] = {"Address space advertised",
12683 "addressSpaceAdvertised"},
9ab0cf58
PG
12684 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12685 "advertisementsWithPaths"},
12686 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12687 "longestAsPath"},
12688 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12689 "largestAsPath"},
12690 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12691 "averageAsPathLengthHops"},
12692 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12693 "averageAsPathSizeBytes"},
12694 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12695 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12696};
2815e61f 12697
d62a17ae 12698struct bgp_table_stats {
12699 struct bgp_table *table;
12700 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12701 double total_space;
ff7924f6
PJ
12702};
12703
9bcb3eef 12704static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12705 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12706{
9bcb3eef 12707 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12708 struct bgp_path_info *pi;
b54892e0 12709 const struct prefix *rn_p;
d62a17ae 12710
9bcb3eef 12711 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12712 return;
d62a17ae 12713
9bcb3eef 12714 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12715 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12716 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12717
9c14ec72 12718 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12719 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12720 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12721
9bcb3eef 12722 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12723 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12724 /* announced address space */
12725 if (space)
b54892e0 12726 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12727 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12728 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12729
9c14ec72 12730
9bcb3eef 12731 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12732 ts->counts[BGP_STATS_RIB]++;
12733
05864da7
DS
12734 if (CHECK_FLAG(pi->attr->flag,
12735 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12736 ts->counts[BGP_STATS_AGGREGATES]++;
12737
12738 /* as-path stats */
05864da7 12739 if (pi->attr->aspath) {
9c14ec72
RW
12740 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12741 unsigned int size = aspath_size(pi->attr->aspath);
12742 as_t highest = aspath_highest(pi->attr->aspath);
12743
12744 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12745
12746 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12747 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12748
12749 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12750 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12751
12752 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12753 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12754 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12755 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12756 }
12757 }
12758}
12759
12760static int bgp_table_stats_walker(struct thread *t)
12761{
9bcb3eef
DS
12762 struct bgp_dest *dest, *ndest;
12763 struct bgp_dest *top;
9c14ec72
RW
12764 struct bgp_table_stats *ts = THREAD_ARG(t);
12765 unsigned int space = 0;
12766
12767 if (!(top = bgp_table_top(ts->table)))
12768 return 0;
12769
12770 switch (ts->table->afi) {
12771 case AFI_IP:
12772 space = IPV4_MAX_BITLEN;
12773 break;
12774 case AFI_IP6:
12775 space = IPV6_MAX_BITLEN;
12776 break;
3ba7b4af
TA
12777 case AFI_L2VPN:
12778 space = EVPN_ROUTE_PREFIXLEN;
12779 break;
9c14ec72
RW
12780 default:
12781 return 0;
12782 }
12783
12784 ts->counts[BGP_STATS_MAXBITLEN] = space;
12785
9bcb3eef 12786 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12787 if (ts->table->safi == SAFI_MPLS_VPN
12788 || ts->table->safi == SAFI_ENCAP
12789 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12790 struct bgp_table *table;
12791
9bcb3eef 12792 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12793 if (!table)
12794 continue;
12795
12796 top = bgp_table_top(table);
9bcb3eef
DS
12797 for (ndest = bgp_table_top(table); ndest;
12798 ndest = bgp_route_next(ndest))
12799 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12800 } else {
9bcb3eef 12801 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12802 }
12803 }
9c14ec72 12804
d62a17ae 12805 return 0;
2815e61f 12806}
ff7924f6 12807
71f1613a
DA
12808static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12809 struct json_object *json_array)
12810{
12811 struct listnode *node, *nnode;
12812 struct bgp *bgp;
12813
12814 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12815 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12816}
12817
12818static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12819 safi_t safi, struct json_object *json_array)
2815e61f 12820{
d62a17ae 12821 struct bgp_table_stats ts;
12822 unsigned int i;
893cccd0
PG
12823 int ret = CMD_SUCCESS;
12824 char temp_buf[20];
6c9d22e2
PG
12825 struct json_object *json = NULL;
12826
12827 if (json_array)
12828 json = json_object_new_object();
019386c2 12829
d62a17ae 12830 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12831 char warning_msg[50];
12832
12833 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12834 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12835 safi);
6c9d22e2
PG
12836
12837 if (!json)
893cccd0
PG
12838 vty_out(vty, "%s\n", warning_msg);
12839 else
9ab0cf58 12840 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12841
893cccd0
PG
12842 ret = CMD_WARNING;
12843 goto end_table_stats;
d62a17ae 12844 }
019386c2 12845
893cccd0 12846 if (!json)
5290ceab
DA
12847 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12848 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12849 else
12850 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12851
d62a17ae 12852 /* labeled-unicast routes live in the unicast table */
12853 if (safi == SAFI_LABELED_UNICAST)
12854 safi = SAFI_UNICAST;
019386c2 12855
d62a17ae 12856 memset(&ts, 0, sizeof(ts));
12857 ts.table = bgp->rib[afi][safi];
12858 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12859
d62a17ae 12860 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12861 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12862 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12863 continue;
12864
12865 switch (i) {
d62a17ae 12866 case BGP_STATS_ASPATH_TOTHOPS:
12867 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12868 if (!json) {
9ab0cf58
PG
12869 snprintf(
12870 temp_buf, sizeof(temp_buf), "%12.2f",
12871 ts.counts[i]
12872 ? (float)ts.counts[i]
12873 / (float)ts.counts
12874 [BGP_STATS_ASPATH_COUNT]
12875 : 0);
893cccd0 12876 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12877 table_stats_strs[i]
12878 [TABLE_STATS_IDX_VTY],
893cccd0 12879 temp_buf);
9ab0cf58
PG
12880 } else {
12881 json_object_double_add(
12882 json,
12883 table_stats_strs[i]
12884 [TABLE_STATS_IDX_JSON],
12885 ts.counts[i]
12886 ? (double)ts.counts[i]
12887 / (double)ts.counts
d62a17ae 12888 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12889 : 0);
12890 }
d62a17ae 12891 break;
12892 case BGP_STATS_TOTPLEN:
6c9d22e2 12893 if (!json) {
9ab0cf58
PG
12894 snprintf(
12895 temp_buf, sizeof(temp_buf), "%12.2f",
12896 ts.counts[i]
12897 ? (float)ts.counts[i]
12898 / (float)ts.counts
12899 [BGP_STATS_PREFIXES]
12900 : 0);
893cccd0 12901 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12902 table_stats_strs[i]
12903 [TABLE_STATS_IDX_VTY],
893cccd0 12904 temp_buf);
9ab0cf58
PG
12905 } else {
12906 json_object_double_add(
12907 json,
12908 table_stats_strs[i]
12909 [TABLE_STATS_IDX_JSON],
12910 ts.counts[i]
12911 ? (double)ts.counts[i]
12912 / (double)ts.counts
d62a17ae 12913 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12914 : 0);
12915 }
d62a17ae 12916 break;
12917 case BGP_STATS_SPACE:
6c9d22e2
PG
12918 if (!json) {
12919 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12920 ts.total_space);
893cccd0 12921 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12922 table_stats_strs[i]
12923 [TABLE_STATS_IDX_VTY],
893cccd0 12924 temp_buf);
9ab0cf58
PG
12925 } else {
12926 json_object_double_add(
12927 json,
12928 table_stats_strs[i]
12929 [TABLE_STATS_IDX_JSON],
12930 (double)ts.total_space);
12931 }
8d0ab76d 12932 if (afi == AFI_IP6) {
6c9d22e2
PG
12933 if (!json) {
12934 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12935 "%12g",
12936 ts.total_space
12937 * pow(2.0, -128 + 32));
6c9d22e2
PG
12938 vty_out(vty, "%30s: %s\n",
12939 "/32 equivalent %s\n",
12940 temp_buf);
9ab0cf58
PG
12941 } else {
12942 json_object_double_add(
12943 json, "/32equivalent",
12944 (double)(ts.total_space
12945 * pow(2.0,
12946 -128 + 32)));
12947 }
6c9d22e2
PG
12948 if (!json) {
12949 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12950 "%12g",
12951 ts.total_space
12952 * pow(2.0, -128 + 48));
6c9d22e2
PG
12953 vty_out(vty, "%30s: %s\n",
12954 "/48 equivalent %s\n",
12955 temp_buf);
9ab0cf58
PG
12956 } else {
12957 json_object_double_add(
12958 json, "/48equivalent",
12959 (double)(ts.total_space
12960 * pow(2.0,
12961 -128 + 48)));
12962 }
8d0ab76d 12963 } else {
6c9d22e2
PG
12964 if (!json) {
12965 snprintf(temp_buf, sizeof(temp_buf),
12966 "%12.2f",
9ab0cf58
PG
12967 ts.total_space * 100.
12968 * pow(2.0, -32));
6c9d22e2 12969 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12970 "% announced ", temp_buf);
12971 } else {
12972 json_object_double_add(
12973 json, "%announced",
12974 (double)(ts.total_space * 100.
12975 * pow(2.0, -32)));
12976 }
6c9d22e2
PG
12977 if (!json) {
12978 snprintf(temp_buf, sizeof(temp_buf),
12979 "%12.2f",
9ab0cf58
PG
12980 ts.total_space
12981 * pow(2.0, -32 + 8));
6c9d22e2
PG
12982 vty_out(vty, "%30s: %s\n",
12983 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12984 } else {
12985 json_object_double_add(
12986 json, "/8equivalent",
12987 (double)(ts.total_space
12988 * pow(2.0, -32 + 8)));
12989 }
6c9d22e2
PG
12990 if (!json) {
12991 snprintf(temp_buf, sizeof(temp_buf),
12992 "%12.2f",
9ab0cf58
PG
12993 ts.total_space
12994 * pow(2.0, -32 + 24));
6c9d22e2 12995 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12996 "/24 equivalent ", temp_buf);
12997 } else {
12998 json_object_double_add(
12999 json, "/24equivalent",
13000 (double)(ts.total_space
13001 * pow(2.0, -32 + 24)));
13002 }
8d0ab76d 13003 }
d62a17ae 13004 break;
13005 default:
6c9d22e2
PG
13006 if (!json) {
13007 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13008 ts.counts[i]);
893cccd0 13009 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13010 table_stats_strs[i]
13011 [TABLE_STATS_IDX_VTY],
13012 temp_buf);
13013 } else {
13014 json_object_int_add(
13015 json,
13016 table_stats_strs[i]
13017 [TABLE_STATS_IDX_JSON],
13018 ts.counts[i]);
13019 }
d62a17ae 13020 }
893cccd0
PG
13021 if (!json)
13022 vty_out(vty, "\n");
d62a17ae 13023 }
9ab0cf58 13024end_table_stats:
6c9d22e2
PG
13025 if (json)
13026 json_object_array_add(json_array, json);
893cccd0 13027 return ret;
d62a17ae 13028}
13029
71f1613a
DA
13030static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13031 safi_t safi, struct json_object *json_array)
13032{
13033 if (!bgp) {
13034 bgp_table_stats_all(vty, afi, safi, json_array);
13035 return CMD_SUCCESS;
13036 }
13037
13038 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13039}
13040
d62a17ae 13041enum bgp_pcounts {
13042 PCOUNT_ADJ_IN = 0,
13043 PCOUNT_DAMPED,
13044 PCOUNT_REMOVED,
13045 PCOUNT_HISTORY,
13046 PCOUNT_STALE,
13047 PCOUNT_VALID,
13048 PCOUNT_ALL,
13049 PCOUNT_COUNTED,
7e3d9632 13050 PCOUNT_BPATH_SELECTED,
d62a17ae 13051 PCOUNT_PFCNT, /* the figure we display to users */
13052 PCOUNT_MAX,
a636c635 13053};
718e3744 13054
2b64873d 13055static const char *const pcount_strs[] = {
9d303b37
DL
13056 [PCOUNT_ADJ_IN] = "Adj-in",
13057 [PCOUNT_DAMPED] = "Damped",
13058 [PCOUNT_REMOVED] = "Removed",
13059 [PCOUNT_HISTORY] = "History",
13060 [PCOUNT_STALE] = "Stale",
13061 [PCOUNT_VALID] = "Valid",
13062 [PCOUNT_ALL] = "All RIB",
13063 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13064 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13065 [PCOUNT_PFCNT] = "Useable",
13066 [PCOUNT_MAX] = NULL,
a636c635 13067};
718e3744 13068
d62a17ae 13069struct peer_pcounts {
13070 unsigned int count[PCOUNT_MAX];
13071 const struct peer *peer;
13072 const struct bgp_table *table;
54317cba 13073 safi_t safi;
a636c635 13074};
47fc97cc 13075
9bcb3eef 13076static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13077{
54317cba
JW
13078 const struct bgp_adj_in *ain;
13079 const struct bgp_path_info *pi;
d62a17ae 13080 const struct peer *peer = pc->peer;
13081
54317cba
JW
13082 for (ain = rn->adj_in; ain; ain = ain->next)
13083 if (ain->peer == peer)
13084 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13085
9bcb3eef 13086 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13087
54317cba
JW
13088 if (pi->peer != peer)
13089 continue;
d62a17ae 13090
54317cba 13091 pc->count[PCOUNT_ALL]++;
d62a17ae 13092
54317cba
JW
13093 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13094 pc->count[PCOUNT_DAMPED]++;
13095 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13096 pc->count[PCOUNT_HISTORY]++;
13097 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13098 pc->count[PCOUNT_REMOVED]++;
13099 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13100 pc->count[PCOUNT_STALE]++;
13101 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13102 pc->count[PCOUNT_VALID]++;
13103 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13104 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13105 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13106 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13107
13108 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13109 pc->count[PCOUNT_COUNTED]++;
13110 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13111 flog_err(
13112 EC_LIB_DEVELOPMENT,
13113 "Attempting to count but flags say it is unusable");
13114 } else {
40381db7 13115 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13116 flog_err(
13117 EC_LIB_DEVELOPMENT,
13118 "Not counted but flags say we should");
d62a17ae 13119 }
13120 }
54317cba
JW
13121}
13122
13123static int bgp_peer_count_walker(struct thread *t)
13124{
9bcb3eef 13125 struct bgp_dest *rn, *rm;
54317cba
JW
13126 const struct bgp_table *table;
13127 struct peer_pcounts *pc = THREAD_ARG(t);
13128
13129 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13130 || pc->safi == SAFI_EVPN) {
13131 /* Special handling for 2-level routing tables. */
13132 for (rn = bgp_table_top(pc->table); rn;
13133 rn = bgp_route_next(rn)) {
9bcb3eef 13134 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13135 if (table != NULL)
13136 for (rm = bgp_table_top(table); rm;
13137 rm = bgp_route_next(rm))
13138 bgp_peer_count_proc(rm, pc);
13139 }
13140 } else
13141 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13142 bgp_peer_count_proc(rn, pc);
13143
d62a17ae 13144 return 0;
718e3744 13145}
13146
d62a17ae 13147static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13148 safi_t safi, bool use_json)
856ca177 13149{
d62a17ae 13150 struct peer_pcounts pcounts = {.peer = peer};
13151 unsigned int i;
13152 json_object *json = NULL;
13153 json_object *json_loop = NULL;
856ca177 13154
d62a17ae 13155 if (use_json) {
13156 json = json_object_new_object();
13157 json_loop = json_object_new_object();
13158 }
718e3744 13159
d62a17ae 13160 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13161 || !peer->bgp->rib[afi][safi]) {
13162 if (use_json) {
13163 json_object_string_add(
13164 json, "warning",
13165 "No such neighbor or address family");
13166 vty_out(vty, "%s\n", json_object_to_json_string(json));
13167 json_object_free(json);
d5f20468 13168 json_object_free(json_loop);
d62a17ae 13169 } else
13170 vty_out(vty, "%% No such neighbor or address family\n");
13171
13172 return CMD_WARNING;
13173 }
2a71e9ce 13174
d62a17ae 13175 memset(&pcounts, 0, sizeof(pcounts));
13176 pcounts.peer = peer;
13177 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13178 pcounts.safi = safi;
d62a17ae 13179
13180 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13181 * stats for the thread-walk (i.e. ensure this can't be blamed on
13182 * on just vty_read()).
13183 */
d62a17ae 13184 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13185
13186 if (use_json) {
13187 json_object_string_add(json, "prefixCountsFor", peer->host);
13188 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13189 get_afi_safi_str(afi, safi, true));
d62a17ae 13190 json_object_int_add(json, "pfxCounter",
13191 peer->pcount[afi][safi]);
13192
13193 for (i = 0; i < PCOUNT_MAX; i++)
13194 json_object_int_add(json_loop, pcount_strs[i],
13195 pcounts.count[i]);
13196
13197 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13198
13199 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13200 json_object_string_add(json, "pfxctDriftFor",
13201 peer->host);
13202 json_object_string_add(
13203 json, "recommended",
13204 "Please report this bug, with the above command output");
13205 }
996c9314
LB
13206 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13207 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 13208 json_object_free(json);
13209 } else {
13210
13211 if (peer->hostname
892fedb6 13212 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13213 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13214 peer->hostname, peer->host,
5cb5f4d0 13215 get_afi_safi_str(afi, safi, false));
d62a17ae 13216 } else {
13217 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13218 get_afi_safi_str(afi, safi, false));
d62a17ae 13219 }
13220
6cde4b45 13221 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13222 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13223
13224 for (i = 0; i < PCOUNT_MAX; i++)
13225 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13226 pcounts.count[i]);
13227
13228 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13229 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13230 vty_out(vty,
13231 "Please report this bug, with the above command output\n");
13232 }
13233 }
13234
13235 return CMD_SUCCESS;
718e3744 13236}
13237
a636c635
DW
13238DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13239 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13240 "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 13241 SHOW_STR
13242 IP_STR
13243 BGP_STR
8386ac43 13244 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13245 BGP_AFI_HELP_STR
13246 BGP_SAFI_HELP_STR
0b16f239
DS
13247 "Detailed information on TCP and BGP neighbor connections\n"
13248 "Neighbor to display information about\n"
13249 "Neighbor to display information about\n"
91d37724 13250 "Neighbor on BGP configured interface\n"
a636c635 13251 "Display detailed prefix count information\n"
9973d184 13252 JSON_STR)
0b16f239 13253{
d62a17ae 13254 afi_t afi = AFI_IP6;
13255 safi_t safi = SAFI_UNICAST;
13256 struct peer *peer;
13257 int idx = 0;
13258 struct bgp *bgp = NULL;
9f049418
DS
13259 bool uj = use_json(argc, argv);
13260
13261 if (uj)
13262 argc--;
856ca177 13263
d62a17ae 13264 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13265 &bgp, uj);
d62a17ae 13266 if (!idx)
13267 return CMD_WARNING;
0b16f239 13268
d62a17ae 13269 argv_find(argv, argc, "neighbors", &idx);
13270 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13271 if (!peer)
13272 return CMD_WARNING;
bb46e94f 13273
29c8d9da 13274 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13275}
0b16f239 13276
d6902373
PG
13277#ifdef KEEP_OLD_VPN_COMMANDS
13278DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13279 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13280 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13281 SHOW_STR
13282 IP_STR
13283 BGP_STR
d6902373 13284 BGP_VPNVX_HELP_STR
91d37724 13285 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13286 "Detailed information on TCP and BGP neighbor connections\n"
13287 "Neighbor to display information about\n"
13288 "Neighbor to display information about\n"
91d37724 13289 "Neighbor on BGP configured interface\n"
a636c635 13290 "Display detailed prefix count information\n"
9973d184 13291 JSON_STR)
a636c635 13292{
d62a17ae 13293 int idx_peer = 6;
13294 struct peer *peer;
9f049418 13295 bool uj = use_json(argc, argv);
a636c635 13296
d62a17ae 13297 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13298 if (!peer)
13299 return CMD_WARNING;
13300
13301 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13302}
13303
d6902373
PG
13304DEFUN (show_ip_bgp_vpn_all_route_prefix,
13305 show_ip_bgp_vpn_all_route_prefix_cmd,
13306 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13307 SHOW_STR
13308 IP_STR
13309 BGP_STR
d6902373 13310 BGP_VPNVX_HELP_STR
91d37724
QY
13311 "Display information about all VPNv4 NLRIs\n"
13312 "Network in the BGP routing table to display\n"
3a2d747c 13313 "Network in the BGP routing table to display\n"
9973d184 13314 JSON_STR)
91d37724 13315{
d62a17ae 13316 int idx = 0;
13317 char *network = NULL;
13318 struct bgp *bgp = bgp_get_default();
13319 if (!bgp) {
13320 vty_out(vty, "Can't find default instance\n");
13321 return CMD_WARNING;
13322 }
87e34b58 13323
d62a17ae 13324 if (argv_find(argv, argc, "A.B.C.D", &idx))
13325 network = argv[idx]->arg;
13326 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13327 network = argv[idx]->arg;
13328 else {
13329 vty_out(vty, "Unable to figure out Network\n");
13330 return CMD_WARNING;
13331 }
87e34b58 13332
d62a17ae 13333 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13334 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13335 use_json(argc, argv));
91d37724 13336}
d6902373 13337#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13338
44c69747
LK
13339DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13340 show_bgp_l2vpn_evpn_route_prefix_cmd,
13341 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13342 SHOW_STR
4c63a661
PG
13343 BGP_STR
13344 L2VPN_HELP_STR
13345 EVPN_HELP_STR
44c69747
LK
13346 "Network in the BGP routing table to display\n"
13347 "Network in the BGP routing table to display\n"
4c63a661
PG
13348 "Network in the BGP routing table to display\n"
13349 "Network in the BGP routing table to display\n"
13350 JSON_STR)
13351{
d62a17ae 13352 int idx = 0;
13353 char *network = NULL;
44c69747 13354 int prefix_check = 0;
a636c635 13355
44c69747
LK
13356 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13357 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13358 network = argv[idx]->arg;
44c69747 13359 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13360 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13361 network = argv[idx]->arg;
44c69747
LK
13362 prefix_check = 1;
13363 } else {
d62a17ae 13364 vty_out(vty, "Unable to figure out Network\n");
13365 return CMD_WARNING;
13366 }
44c69747
LK
13367 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13368 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13369 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13370}
13371
2f9bc755
DS
13372static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13373 struct bgp_table *table, int *header1,
13374 int *header2, json_object *json,
13375 json_object *json_scode,
13376 json_object *json_ocode, bool wide)
13377{
13378 uint64_t version = table ? table->version : 0;
13379
13380 if (*header1) {
13381 if (json) {
13382 json_object_int_add(json, "bgpTableVersion", version);
c949c771
DA
13383 json_object_string_addf(json, "bgpLocalRouterId",
13384 "%pI4", &bgp->router_id);
2f9bc755
DS
13385 json_object_int_add(json, "defaultLocPrf",
13386 bgp->default_local_pref);
13387 json_object_int_add(json, "localAS", bgp->as);
13388 json_object_object_add(json, "bgpStatusCodes",
13389 json_scode);
13390 json_object_object_add(json, "bgpOriginCodes",
13391 json_ocode);
13392 } else {
13393 vty_out(vty,
23d0a753
DA
13394 "BGP table version is %" PRIu64
13395 ", local router ID is %pI4, vrf id ",
13396 version, &bgp->router_id);
2f9bc755
DS
13397 if (bgp->vrf_id == VRF_UNKNOWN)
13398 vty_out(vty, "%s", VRFID_NONE_STR);
13399 else
13400 vty_out(vty, "%u", bgp->vrf_id);
13401 vty_out(vty, "\n");
13402 vty_out(vty, "Default local pref %u, ",
13403 bgp->default_local_pref);
13404 vty_out(vty, "local AS %u\n", bgp->as);
13405 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13406 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13407 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13408 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13409 }
13410 *header1 = 0;
13411 }
13412 if (*header2) {
13413 if (!json)
13414 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13415 : BGP_SHOW_HEADER));
13416 *header2 = 0;
13417 }
13418}
13419
d9478df0
TA
13420static void
13421show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13422 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13423 const char *rmap_name, json_object *json, json_object *json_ar,
13424 json_object *json_scode, json_object *json_ocode,
96c81f66 13425 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13426 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13427{
d62a17ae 13428 struct bgp_adj_in *ain;
13429 struct bgp_adj_out *adj;
9bcb3eef 13430 struct bgp_dest *dest;
d62a17ae 13431 struct bgp *bgp;
d62a17ae 13432 struct attr attr;
13433 int ret;
13434 struct update_subgroup *subgrp;
d62a17ae 13435 struct peer_af *paf;
f99def61 13436 bool route_filtered;
96f3485c
MK
13437 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13438 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13439 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13440 || (safi == SAFI_EVPN))
13441 ? true
13442 : false;
a636c635 13443
d62a17ae 13444 bgp = peer->bgp;
a636c635 13445
d62a17ae 13446 subgrp = peer_subgroup(peer, afi, safi);
13447
6392aaa6 13448 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13449 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13450 if (use_json) {
13451 json_object_int_add(json, "bgpTableVersion",
13452 table->version);
c949c771
DA
13453 json_object_string_addf(json, "bgpLocalRouterId",
13454 "%pI4", &bgp->router_id);
01eced22
AD
13455 json_object_int_add(json, "defaultLocPrf",
13456 bgp->default_local_pref);
13457 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13458 json_object_object_add(json, "bgpStatusCodes",
13459 json_scode);
13460 json_object_object_add(json, "bgpOriginCodes",
13461 json_ocode);
07d0c4ed
DA
13462 json_object_string_add(
13463 json, "bgpOriginatingDefaultNetwork",
13464 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13465 } else {
23d0a753
DA
13466 vty_out(vty,
13467 "BGP table version is %" PRIu64
13468 ", local router ID is %pI4, vrf id ",
13469 table->version, &bgp->router_id);
9df8b37c
PZ
13470 if (bgp->vrf_id == VRF_UNKNOWN)
13471 vty_out(vty, "%s", VRFID_NONE_STR);
13472 else
13473 vty_out(vty, "%u", bgp->vrf_id);
13474 vty_out(vty, "\n");
01eced22
AD
13475 vty_out(vty, "Default local pref %u, ",
13476 bgp->default_local_pref);
13477 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13478 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13479 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13480 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13481 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13482
07d0c4ed
DA
13483 vty_out(vty, "Originating default network %s\n\n",
13484 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13485 }
d9478df0 13486 *header1 = 0;
d62a17ae 13487 }
a636c635 13488
9bcb3eef 13489 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13490 if (type == bgp_show_adj_route_received
13491 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13492 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13493 if (ain->peer != peer)
ea47320b 13494 continue;
6392aaa6 13495
d9478df0
TA
13496 show_adj_route_header(vty, bgp, table, header1,
13497 header2, json, json_scode,
13498 json_ocode, wide);
13499
13500 if ((safi == SAFI_MPLS_VPN)
13501 || (safi == SAFI_ENCAP)
13502 || (safi == SAFI_EVPN)) {
13503 if (use_json)
13504 json_object_string_add(
13505 json_ar, "rd", rd_str);
13506 else if (show_rd && rd_str) {
13507 vty_out(vty,
13508 "Route Distinguisher: %s\n",
13509 rd_str);
13510 show_rd = false;
13511 }
13512 }
6392aaa6 13513
6f4f49b2 13514 attr = *ain->attr;
f99def61
AD
13515 route_filtered = false;
13516
13517 /* Filter prefix using distribute list,
13518 * filter list or prefix list
13519 */
b54892e0 13520 const struct prefix *rn_p =
9bcb3eef 13521 bgp_dest_get_prefix(dest);
b54892e0
DS
13522 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13523 safi))
13524 == FILTER_DENY)
f99def61
AD
13525 route_filtered = true;
13526
13527 /* Filter prefix using route-map */
b54892e0
DS
13528 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13529 safi, rmap_name, NULL,
13530 0, NULL);
6392aaa6 13531
13c8e163
AD
13532 if (type == bgp_show_adj_route_filtered &&
13533 !route_filtered && ret != RMAP_DENY) {
b755861b 13534 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13535 continue;
d62a17ae 13536 }
6392aaa6 13537
d9478df0
TA
13538 if (type == bgp_show_adj_route_received
13539 && (route_filtered || ret == RMAP_DENY))
13540 (*filtered_count)++;
6392aaa6 13541
7d3cae70 13542 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13543 use_json, json_ar, wide);
b755861b 13544 bgp_attr_undup(&attr, ain->attr);
d9478df0 13545 (*output_count)++;
d62a17ae 13546 }
6392aaa6 13547 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13548 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13549 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13550 if (paf->peer != peer || !adj->attr)
924c3f6a 13551 continue;
d62a17ae 13552
d9478df0
TA
13553 show_adj_route_header(vty, bgp, table,
13554 header1, header2,
13555 json, json_scode,
13556 json_ocode, wide);
d62a17ae 13557
b54892e0 13558 const struct prefix *rn_p =
9bcb3eef 13559 bgp_dest_get_prefix(dest);
b54892e0 13560
6f4f49b2 13561 attr = *adj->attr;
b755861b 13562 ret = bgp_output_modifier(
b54892e0 13563 peer, rn_p, &attr, afi, safi,
b755861b 13564 rmap_name);
f46d8e1e 13565
b755861b 13566 if (ret != RMAP_DENY) {
d9478df0
TA
13567 if ((safi == SAFI_MPLS_VPN)
13568 || (safi == SAFI_ENCAP)
13569 || (safi == SAFI_EVPN)) {
13570 if (use_json)
13571 json_object_string_add(
13572 json_ar,
13573 "rd",
13574 rd_str);
13575 else if (show_rd
13576 && rd_str) {
13577 vty_out(vty,
13578 "Route Distinguisher: %s\n",
13579 rd_str);
13580 show_rd = false;
13581 }
13582 }
b54892e0 13583 route_vty_out_tmp(
7d3cae70
DA
13584 vty, dest, rn_p, &attr,
13585 safi, use_json, json_ar,
ae248832 13586 wide);
d9478df0 13587 (*output_count)++;
b755861b 13588 } else {
d9478df0 13589 (*filtered_count)++;
a2addae8 13590 }
b755861b
PM
13591
13592 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13593 }
f20ce998
DS
13594 } else if (type == bgp_show_adj_route_bestpath) {
13595 struct bgp_path_info *pi;
13596
d9478df0
TA
13597 show_adj_route_header(vty, bgp, table, header1, header2,
13598 json, json_scode, json_ocode,
13599 wide);
f20ce998
DS
13600
13601 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13602 pi = pi->next) {
13603 if (pi->peer != peer)
13604 continue;
13605
13606 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13607 continue;
13608
7d3cae70 13609 route_vty_out_tmp(vty, dest,
f20ce998
DS
13610 bgp_dest_get_prefix(dest),
13611 pi->attr, safi, use_json,
13612 json_ar, wide);
d9478df0 13613 (*output_count)++;
f20ce998 13614 }
d62a17ae 13615 }
13616 }
a636c635 13617}
2a71e9ce 13618
d62a17ae 13619static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13620 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13621 const char *rmap_name, uint16_t show_flags)
0b16f239 13622{
d9478df0
TA
13623 struct bgp *bgp;
13624 struct bgp_table *table;
d62a17ae 13625 json_object *json = NULL;
d9478df0
TA
13626 json_object *json_scode = NULL;
13627 json_object *json_ocode = NULL;
13628 json_object *json_ar = NULL;
96f3485c 13629 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13630
d9478df0
TA
13631 /* Init BGP headers here so they're only displayed once
13632 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13633 */
13634 int header1 = 1;
13635 int header2 = 1;
13636
13637 /*
13638 * Initialize variables for each RD
13639 * All prefixes under an RD is aggregated within "json_routes"
13640 */
13641 char rd_str[BUFSIZ] = {0};
13642 json_object *json_routes = NULL;
13643
13644
13645 /* For 2-tier tables, prefix counts need to be
13646 * maintained across multiple runs of show_adj_route()
13647 */
13648 unsigned long output_count_per_rd;
13649 unsigned long filtered_count_per_rd;
13650 unsigned long output_count = 0;
13651 unsigned long filtered_count = 0;
13652
13653 if (use_json) {
d62a17ae 13654 json = json_object_new_object();
d9478df0
TA
13655 json_ar = json_object_new_object();
13656 json_scode = json_object_new_object();
13657 json_ocode = json_object_new_object();
13658
13659 json_object_string_add(json_scode, "suppressed", "s");
13660 json_object_string_add(json_scode, "damped", "d");
13661 json_object_string_add(json_scode, "history", "h");
13662 json_object_string_add(json_scode, "valid", "*");
13663 json_object_string_add(json_scode, "best", ">");
13664 json_object_string_add(json_scode, "multipath", "=");
13665 json_object_string_add(json_scode, "internal", "i");
13666 json_object_string_add(json_scode, "ribFailure", "r");
13667 json_object_string_add(json_scode, "stale", "S");
13668 json_object_string_add(json_scode, "removed", "R");
13669
13670 json_object_string_add(json_ocode, "igp", "i");
13671 json_object_string_add(json_ocode, "egp", "e");
13672 json_object_string_add(json_ocode, "incomplete", "?");
13673 }
0b16f239 13674
d62a17ae 13675 if (!peer || !peer->afc[afi][safi]) {
13676 if (use_json) {
13677 json_object_string_add(
13678 json, "warning",
13679 "No such neighbor or address family");
13680 vty_out(vty, "%s\n", json_object_to_json_string(json));
13681 json_object_free(json);
690c3134
MW
13682 json_object_free(json_ar);
13683 json_object_free(json_scode);
13684 json_object_free(json_ocode);
d62a17ae 13685 } else
13686 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13687
d62a17ae 13688 return CMD_WARNING;
13689 }
13690
6392aaa6
PM
13691 if ((type == bgp_show_adj_route_received
13692 || type == bgp_show_adj_route_filtered)
d62a17ae 13693 && !CHECK_FLAG(peer->af_flags[afi][safi],
13694 PEER_FLAG_SOFT_RECONFIG)) {
13695 if (use_json) {
13696 json_object_string_add(
13697 json, "warning",
13698 "Inbound soft reconfiguration not enabled");
13699 vty_out(vty, "%s\n", json_object_to_json_string(json));
13700 json_object_free(json);
690c3134
MW
13701 json_object_free(json_ar);
13702 json_object_free(json_scode);
13703 json_object_free(json_ocode);
d62a17ae 13704 } else
13705 vty_out(vty,
13706 "%% Inbound soft reconfiguration not enabled\n");
13707
13708 return CMD_WARNING;
13709 }
0b16f239 13710
d9478df0
TA
13711 bgp = peer->bgp;
13712
13713 /* labeled-unicast routes live in the unicast table */
13714 if (safi == SAFI_LABELED_UNICAST)
13715 table = bgp->rib[afi][SAFI_UNICAST];
13716 else
13717 table = bgp->rib[afi][safi];
13718
13719 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13720 || (safi == SAFI_EVPN)) {
13721
13722 struct bgp_dest *dest;
13723
13724 for (dest = bgp_table_top(table); dest;
13725 dest = bgp_route_next(dest)) {
13726 table = bgp_dest_get_bgp_table_info(dest);
13727 if (!table)
13728 continue;
13729
13730 output_count_per_rd = 0;
13731 filtered_count_per_rd = 0;
13732
13733 if (use_json)
13734 json_routes = json_object_new_object();
13735
13736 const struct prefix_rd *prd;
13737 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13738 dest);
13739
13740 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13741
13742 show_adj_route(vty, peer, table, afi, safi, type,
13743 rmap_name, json, json_routes, json_scode,
13744 json_ocode, show_flags, &header1,
13745 &header2, rd_str, &output_count_per_rd,
13746 &filtered_count_per_rd);
13747
13748 /* Don't include an empty RD in the output! */
13749 if (json_routes && (output_count_per_rd > 0))
13750 json_object_object_add(json_ar, rd_str,
13751 json_routes);
13752
13753 output_count += output_count_per_rd;
13754 filtered_count += filtered_count_per_rd;
13755 }
13756 } else
13757 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13758 json, json_ar, json_scode, json_ocode,
13759 show_flags, &header1, &header2, rd_str,
13760 &output_count, &filtered_count);
13761
13762 if (use_json) {
13763 json_object_object_add(json, "advertisedRoutes", json_ar);
13764 json_object_int_add(json, "totalPrefixCounter", output_count);
13765 json_object_int_add(json, "filteredPrefixCounter",
13766 filtered_count);
13767
13768 vty_out(vty, "%s\n",
13769 json_object_to_json_string_ext(
13770 json, JSON_C_TO_STRING_PRETTY));
13771
690c3134
MW
13772 /*
13773 * These fields only give up ownership to `json` when `header1`
13774 * is used (set to zero). See code in `show_adj_route` and
13775 * `show_adj_route_header`.
13776 */
13777 if (header1 == 1) {
d9478df0
TA
13778 json_object_free(json_scode);
13779 json_object_free(json_ocode);
13780 }
13781
690c3134 13782 json_object_free(json);
d9478df0
TA
13783 } else if (output_count > 0) {
13784 if (filtered_count > 0)
13785 vty_out(vty,
13786 "\nTotal number of prefixes %ld (%ld filtered)\n",
13787 output_count, filtered_count);
13788 else
13789 vty_out(vty, "\nTotal number of prefixes %ld\n",
13790 output_count);
13791 }
0b16f239 13792
d62a17ae 13793 return CMD_SUCCESS;
a636c635 13794}
50ef26d4 13795
f20ce998
DS
13796DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13797 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13798 "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]",
13799 SHOW_STR
13800 IP_STR
13801 BGP_STR
13802 BGP_INSTANCE_HELP_STR
13803 BGP_AFI_HELP_STR
13804 BGP_SAFI_WITH_LABEL_HELP_STR
13805 "Detailed information on TCP and BGP neighbor connections\n"
13806 "Neighbor to display information about\n"
13807 "Neighbor to display information about\n"
13808 "Neighbor on BGP configured interface\n"
13809 "Display the routes selected by best path\n"
13810 JSON_STR
13811 "Increase table width for longer prefixes\n")
13812{
13813 afi_t afi = AFI_IP6;
13814 safi_t safi = SAFI_UNICAST;
13815 char *rmap_name = NULL;
13816 char *peerstr = NULL;
13817 struct bgp *bgp = NULL;
13818 struct peer *peer;
13819 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13820 int idx = 0;
96c81f66 13821 uint16_t show_flags = 0;
96f3485c
MK
13822
13823 if (uj)
13824 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13825
13826 if (wide)
13827 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13828
13829 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13830 &bgp, uj);
13831
13832 if (!idx)
13833 return CMD_WARNING;
13834
13835 argv_find(argv, argc, "neighbors", &idx);
13836 peerstr = argv[++idx]->arg;
13837
13838 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13839 if (!peer)
13840 return CMD_WARNING;
13841
96f3485c
MK
13842 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13843 show_flags);
f20ce998
DS
13844}
13845
ae248832 13846DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13847 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13848 "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 13849 SHOW_STR
13850 IP_STR
13851 BGP_STR
a636c635 13852 BGP_INSTANCE_HELP_STR
7395a2c9 13853 BGP_AFI_HELP_STR
4dd6177e 13854 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13855 "Display the entries for all address families\n"
718e3744 13856 "Detailed information on TCP and BGP neighbor connections\n"
13857 "Neighbor to display information about\n"
13858 "Neighbor to display information about\n"
91d37724 13859 "Neighbor on BGP configured interface\n"
a636c635 13860 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13861 "Display the received routes from neighbor\n"
13862 "Display the filtered routes received from neighbor\n"
a636c635
DW
13863 "Route-map to modify the attributes\n"
13864 "Name of the route map\n"
ae248832
MK
13865 JSON_STR
13866 "Increase table width for longer prefixes\n")
718e3744 13867{
d62a17ae 13868 afi_t afi = AFI_IP6;
13869 safi_t safi = SAFI_UNICAST;
13870 char *rmap_name = NULL;
13871 char *peerstr = NULL;
d62a17ae 13872 struct bgp *bgp = NULL;
13873 struct peer *peer;
6392aaa6 13874 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13875 int idx = 0;
96f3485c 13876 bool first = true;
96c81f66 13877 uint16_t show_flags = 0;
6392aaa6 13878
96f3485c 13879 if (uj) {
d62a17ae 13880 argc--;
96f3485c
MK
13881 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13882 }
13883
13884 if (all) {
13885 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13886 if (argv_find(argv, argc, "ipv4", &idx))
13887 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13888
13889 if (argv_find(argv, argc, "ipv6", &idx))
13890 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13891 }
13892
13893 if (wide)
13894 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13895
9f049418
DS
13896 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13897 &bgp, uj);
13898 if (!idx)
13899 return CMD_WARNING;
13900
d62a17ae 13901 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13902 argv_find(argv, argc, "neighbors", &idx);
13903 peerstr = argv[++idx]->arg;
8c3deaae 13904
d62a17ae 13905 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13906 if (!peer)
13907 return CMD_WARNING;
856ca177 13908
d62a17ae 13909 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13910 type = bgp_show_adj_route_advertised;
13911 else if (argv_find(argv, argc, "received-routes", &idx))
13912 type = bgp_show_adj_route_received;
13913 else if (argv_find(argv, argc, "filtered-routes", &idx))
13914 type = bgp_show_adj_route_filtered;
13915
d62a17ae 13916 if (argv_find(argv, argc, "route-map", &idx))
13917 rmap_name = argv[++idx]->arg;
95cbbd2a 13918
96f3485c
MK
13919 if (!all)
13920 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13921 show_flags);
13922 if (uj)
13923 vty_out(vty, "{\n");
13924
13925 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13926 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13927 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13928 : AFI_IP6;
13929 FOREACH_SAFI (safi) {
96f3485c
MK
13930 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13931 continue;
13932
13933 if (uj) {
13934 if (first)
13935 first = false;
13936 else
13937 vty_out(vty, ",\n");
13938 vty_out(vty, "\"%s\":",
13939 get_afi_safi_str(afi, safi, true));
13940 } else
13941 vty_out(vty, "\nFor address family: %s\n",
13942 get_afi_safi_str(afi, safi, false));
13943
13944 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13945 show_flags);
13946 }
13947 } else {
13948 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13949 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13950 continue;
13951
13952 if (uj) {
13953 if (first)
13954 first = false;
13955 else
13956 vty_out(vty, ",\n");
13957 vty_out(vty, "\"%s\":",
13958 get_afi_safi_str(afi, safi, true));
13959 } else
13960 vty_out(vty, "\nFor address family: %s\n",
13961 get_afi_safi_str(afi, safi, false));
13962
13963 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13964 show_flags);
13965 }
13966 }
13967 if (uj)
13968 vty_out(vty, "}\n");
13969
13970 return CMD_SUCCESS;
95cbbd2a
ML
13971}
13972
718e3744 13973DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13974 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 13975 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13976 SHOW_STR
13977 IP_STR
13978 BGP_STR
d3120452 13979 BGP_INSTANCE_HELP_STR
8c3deaae
QY
13980 "Address Family\n"
13981 "Address Family\n"
718e3744 13982 "Address Family modifier\n"
13983 "Detailed information on TCP and BGP neighbor connections\n"
13984 "Neighbor to display information about\n"
13985 "Neighbor to display information about\n"
91d37724 13986 "Neighbor on BGP configured interface\n"
718e3744 13987 "Display information received from a BGP neighbor\n"
856ca177 13988 "Display the prefixlist filter\n"
9973d184 13989 JSON_STR)
718e3744 13990{
d62a17ae 13991 afi_t afi = AFI_IP6;
13992 safi_t safi = SAFI_UNICAST;
13993 char *peerstr = NULL;
d62a17ae 13994 char name[BUFSIZ];
d62a17ae 13995 struct peer *peer;
d3120452 13996 int count;
d62a17ae 13997 int idx = 0;
d3120452
IR
13998 struct bgp *bgp = NULL;
13999 bool uj = use_json(argc, argv);
14000
14001 if (uj)
14002 argc--;
14003
14004 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14005 &bgp, uj);
14006 if (!idx)
14007 return CMD_WARNING;
d62a17ae 14008
d62a17ae 14009 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14010 argv_find(argv, argc, "neighbors", &idx);
14011 peerstr = argv[++idx]->arg;
14012
d3120452
IR
14013 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14014 if (!peer)
14015 return CMD_WARNING;
718e3744 14016
4ced1a2c 14017 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14018 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14019 if (count) {
14020 if (!uj)
14021 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14022 get_afi_safi_str(afi, safi, false));
d62a17ae 14023 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14024 } else {
14025 if (uj)
14026 vty_out(vty, "{}\n");
14027 else
14028 vty_out(vty, "No functional output\n");
14029 }
718e3744 14030
d62a17ae 14031 return CMD_SUCCESS;
14032}
14033
14034static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14035 afi_t afi, safi_t safi,
9f049418 14036 enum bgp_show_type type, bool use_json)
d62a17ae 14037{
96c81f66 14038 uint16_t show_flags = 0;
96f3485c
MK
14039
14040 if (use_json)
14041 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14042
d62a17ae 14043 if (!peer || !peer->afc[afi][safi]) {
14044 if (use_json) {
14045 json_object *json_no = NULL;
14046 json_no = json_object_new_object();
14047 json_object_string_add(
14048 json_no, "warning",
14049 "No such neighbor or address family");
14050 vty_out(vty, "%s\n",
14051 json_object_to_json_string(json_no));
14052 json_object_free(json_no);
14053 } else
14054 vty_out(vty, "%% No such neighbor or address family\n");
14055 return CMD_WARNING;
14056 }
47fc97cc 14057
7daf25a3
TA
14058 /* labeled-unicast routes live in the unicast table */
14059 if (safi == SAFI_LABELED_UNICAST)
14060 safi = SAFI_UNICAST;
14061
1e2ce4f1
DS
14062 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14063 RPKI_NOT_BEING_USED);
718e3744 14064}
14065
dba3c1d3
PG
14066DEFUN (show_ip_bgp_flowspec_routes_detailed,
14067 show_ip_bgp_flowspec_routes_detailed_cmd,
14068 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14069 SHOW_STR
14070 IP_STR
14071 BGP_STR
14072 BGP_INSTANCE_HELP_STR
14073 BGP_AFI_HELP_STR
14074 "SAFI Flowspec\n"
14075 "Detailed information on flowspec entries\n"
14076 JSON_STR)
14077{
458c1475 14078 afi_t afi = AFI_IP6;
dba3c1d3
PG
14079 safi_t safi = SAFI_UNICAST;
14080 struct bgp *bgp = NULL;
14081 int idx = 0;
9f049418 14082 bool uj = use_json(argc, argv);
96c81f66 14083 uint16_t show_flags = 0;
9f049418 14084
96f3485c 14085 if (uj) {
9f049418 14086 argc--;
96f3485c
MK
14087 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14088 }
dba3c1d3
PG
14089
14090 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14091 &bgp, uj);
dba3c1d3
PG
14092 if (!idx)
14093 return CMD_WARNING;
14094
96f3485c 14095 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14096 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14097}
14098
718e3744 14099DEFUN (show_ip_bgp_neighbor_routes,
14100 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14101 "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 14102 SHOW_STR
14103 IP_STR
14104 BGP_STR
8386ac43 14105 BGP_INSTANCE_HELP_STR
4f280b15 14106 BGP_AFI_HELP_STR
4dd6177e 14107 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14108 "Detailed information on TCP and BGP neighbor connections\n"
14109 "Neighbor to display information about\n"
14110 "Neighbor to display information about\n"
91d37724 14111 "Neighbor on BGP configured interface\n"
2525cf39 14112 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14113 "Display the dampened routes received from neighbor\n"
14114 "Display routes learned from neighbor\n"
9973d184 14115 JSON_STR)
718e3744 14116{
d62a17ae 14117 char *peerstr = NULL;
14118 struct bgp *bgp = NULL;
14119 afi_t afi = AFI_IP6;
14120 safi_t safi = SAFI_UNICAST;
14121 struct peer *peer;
14122 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14123 int idx = 0;
9f049418
DS
14124 bool uj = use_json(argc, argv);
14125
14126 if (uj)
14127 argc--;
bb46e94f 14128
d62a17ae 14129 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14130 &bgp, uj);
d62a17ae 14131 if (!idx)
14132 return CMD_WARNING;
c493f2d8 14133
d62a17ae 14134 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14135 argv_find(argv, argc, "neighbors", &idx);
14136 peerstr = argv[++idx]->arg;
8c3deaae 14137
d62a17ae 14138 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14139 if (!peer)
d62a17ae 14140 return CMD_WARNING;
bb46e94f 14141
d62a17ae 14142 if (argv_find(argv, argc, "flap-statistics", &idx))
14143 sh_type = bgp_show_type_flap_neighbor;
14144 else if (argv_find(argv, argc, "dampened-routes", &idx))
14145 sh_type = bgp_show_type_damp_neighbor;
14146 else if (argv_find(argv, argc, "routes", &idx))
14147 sh_type = bgp_show_type_neighbor;
2525cf39 14148
d62a17ae 14149 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14150}
6b0655a2 14151
734b349e 14152struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14153
d62a17ae 14154struct bgp_distance {
14155 /* Distance value for the IP source prefix. */
d7c0a89a 14156 uint8_t distance;
718e3744 14157
d62a17ae 14158 /* Name of the access-list to be matched. */
14159 char *access_list;
718e3744 14160};
14161
4f280b15
LB
14162DEFUN (show_bgp_afi_vpn_rd_route,
14163 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14164 "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
14165 SHOW_STR
14166 BGP_STR
14167 BGP_AFI_HELP_STR
14168 "Address Family modifier\n"
14169 "Display information for a route distinguisher\n"
14170 "Route Distinguisher\n"
a111dd97 14171 "All Route Distinguishers\n"
7395a2c9
DS
14172 "Network in the BGP routing table to display\n"
14173 "Network in the BGP routing table to display\n"
14174 JSON_STR)
4f280b15 14175{
d62a17ae 14176 int ret;
14177 struct prefix_rd prd;
14178 afi_t afi = AFI_MAX;
14179 int idx = 0;
4f280b15 14180
ff6566f3
DS
14181 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14182 vty_out(vty, "%% Malformed Address Family\n");
14183 return CMD_WARNING;
14184 }
14185
a111dd97
TA
14186 if (!strcmp(argv[5]->arg, "all"))
14187 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14188 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14189 RPKI_NOT_BEING_USED,
14190 use_json(argc, argv));
14191
d62a17ae 14192 ret = str2prefix_rd(argv[5]->arg, &prd);
14193 if (!ret) {
14194 vty_out(vty, "%% Malformed Route Distinguisher\n");
14195 return CMD_WARNING;
14196 }
ff6566f3 14197
d62a17ae 14198 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14199 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14200 use_json(argc, argv));
4f280b15
LB
14201}
14202
d62a17ae 14203static struct bgp_distance *bgp_distance_new(void)
718e3744 14204{
d62a17ae 14205 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14206}
14207
d62a17ae 14208static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14209{
d62a17ae 14210 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14211}
14212
585f1adc
IR
14213static int bgp_distance_set(struct vty *vty, const char *distance_str,
14214 const char *ip_str, const char *access_list_str)
718e3744 14215{
d62a17ae 14216 int ret;
585f1adc
IR
14217 afi_t afi;
14218 safi_t safi;
d62a17ae 14219 struct prefix p;
585f1adc 14220 uint8_t distance;
9bcb3eef 14221 struct bgp_dest *dest;
d62a17ae 14222 struct bgp_distance *bdistance;
718e3744 14223
585f1adc
IR
14224 afi = bgp_node_afi(vty);
14225 safi = bgp_node_safi(vty);
14226
d62a17ae 14227 ret = str2prefix(ip_str, &p);
14228 if (ret == 0) {
585f1adc 14229 vty_out(vty, "Malformed prefix\n");
d62a17ae 14230 return CMD_WARNING_CONFIG_FAILED;
14231 }
718e3744 14232
585f1adc
IR
14233 distance = atoi(distance_str);
14234
d62a17ae 14235 /* Get BGP distance node. */
9bcb3eef
DS
14236 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14237 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14238 if (bdistance)
9bcb3eef 14239 bgp_dest_unlock_node(dest);
ca2e160d 14240 else {
d62a17ae 14241 bdistance = bgp_distance_new();
9bcb3eef 14242 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14243 }
718e3744 14244
d62a17ae 14245 /* Set distance value. */
14246 bdistance->distance = distance;
718e3744 14247
d62a17ae 14248 /* Reset access-list configuration. */
e1b36e13 14249 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14250 if (access_list_str)
14251 bdistance->access_list =
14252 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14253
d62a17ae 14254 return CMD_SUCCESS;
718e3744 14255}
14256
585f1adc
IR
14257static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14258 const char *ip_str, const char *access_list_str)
718e3744 14259{
d62a17ae 14260 int ret;
585f1adc
IR
14261 afi_t afi;
14262 safi_t safi;
d62a17ae 14263 struct prefix p;
585f1adc 14264 int distance;
9bcb3eef 14265 struct bgp_dest *dest;
d62a17ae 14266 struct bgp_distance *bdistance;
718e3744 14267
585f1adc
IR
14268 afi = bgp_node_afi(vty);
14269 safi = bgp_node_safi(vty);
14270
d62a17ae 14271 ret = str2prefix(ip_str, &p);
14272 if (ret == 0) {
585f1adc 14273 vty_out(vty, "Malformed prefix\n");
d62a17ae 14274 return CMD_WARNING_CONFIG_FAILED;
14275 }
718e3744 14276
9bcb3eef
DS
14277 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14278 if (!dest) {
585f1adc 14279 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14280 return CMD_WARNING_CONFIG_FAILED;
14281 }
718e3744 14282
9bcb3eef 14283 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14284 distance = atoi(distance_str);
1f9a9fff 14285
d62a17ae 14286 if (bdistance->distance != distance) {
585f1adc 14287 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14288 bgp_dest_unlock_node(dest);
d62a17ae 14289 return CMD_WARNING_CONFIG_FAILED;
14290 }
718e3744 14291
0a22ddfb 14292 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14293 bgp_distance_free(bdistance);
718e3744 14294
9bcb3eef
DS
14295 bgp_dest_set_bgp_path_info(dest, NULL);
14296 bgp_dest_unlock_node(dest);
14297 bgp_dest_unlock_node(dest);
718e3744 14298
d62a17ae 14299 return CMD_SUCCESS;
718e3744 14300}
14301
718e3744 14302/* Apply BGP information to distance method. */
b8685f9b 14303uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14304 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14305{
9bcb3eef 14306 struct bgp_dest *dest;
801bb996 14307 struct prefix q = {0};
d62a17ae 14308 struct peer *peer;
14309 struct bgp_distance *bdistance;
14310 struct access_list *alist;
14311 struct bgp_static *bgp_static;
14312
14313 if (!bgp)
14314 return 0;
14315
40381db7 14316 peer = pinfo->peer;
d62a17ae 14317
7b7d48e5
DS
14318 if (pinfo->attr->distance)
14319 return pinfo->attr->distance;
14320
801bb996
CS
14321 /* Check source address.
14322 * Note: for aggregate route, peer can have unspec af type.
14323 */
14324 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14325 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14326 return 0;
14327
9bcb3eef
DS
14328 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14329 if (dest) {
14330 bdistance = bgp_dest_get_bgp_distance_info(dest);
14331 bgp_dest_unlock_node(dest);
d62a17ae 14332
14333 if (bdistance->access_list) {
14334 alist = access_list_lookup(afi, bdistance->access_list);
14335 if (alist
14336 && access_list_apply(alist, p) == FILTER_PERMIT)
14337 return bdistance->distance;
14338 } else
14339 return bdistance->distance;
718e3744 14340 }
718e3744 14341
d62a17ae 14342 /* Backdoor check. */
9bcb3eef
DS
14343 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14344 if (dest) {
14345 bgp_static = bgp_dest_get_bgp_static_info(dest);
14346 bgp_dest_unlock_node(dest);
718e3744 14347
d62a17ae 14348 if (bgp_static->backdoor) {
14349 if (bgp->distance_local[afi][safi])
14350 return bgp->distance_local[afi][safi];
14351 else
14352 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14353 }
718e3744 14354 }
718e3744 14355
d62a17ae 14356 if (peer->sort == BGP_PEER_EBGP) {
14357 if (bgp->distance_ebgp[afi][safi])
14358 return bgp->distance_ebgp[afi][safi];
14359 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14360 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14361 if (bgp->distance_ibgp[afi][safi])
14362 return bgp->distance_ibgp[afi][safi];
14363 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14364 } else {
14365 if (bgp->distance_local[afi][safi])
14366 return bgp->distance_local[afi][safi];
14367 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14368 }
718e3744 14369}
14370
a612fb77
DA
14371/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14372 * we should tell ZEBRA update the routes for a specific
14373 * AFI/SAFI to reflect changes in RIB.
14374 */
585f1adc
IR
14375static void bgp_announce_routes_distance_update(struct bgp *bgp,
14376 afi_t update_afi,
14377 safi_t update_safi)
a612fb77
DA
14378{
14379 afi_t afi;
14380 safi_t safi;
14381
14382 FOREACH_AFI_SAFI (afi, safi) {
14383 if (!bgp_fibupd_safi(safi))
14384 continue;
14385
8b54bc30
DA
14386 if (afi != update_afi && safi != update_safi)
14387 continue;
14388
14389 if (BGP_DEBUG(zebra, ZEBRA))
14390 zlog_debug(
14391 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14392 __func__, afi, safi);
14393 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14394 }
14395}
14396
585f1adc
IR
14397DEFUN (bgp_distance,
14398 bgp_distance_cmd,
14399 "distance bgp (1-255) (1-255) (1-255)",
14400 "Define an administrative distance\n"
14401 "BGP distance\n"
14402 "Distance for routes external to the AS\n"
14403 "Distance for routes internal to the AS\n"
14404 "Distance for local routes\n")
718e3744 14405{
585f1adc 14406 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14407 int idx_number = 2;
14408 int idx_number_2 = 3;
14409 int idx_number_3 = 4;
585f1adc
IR
14410 int distance_ebgp = atoi(argv[idx_number]->arg);
14411 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14412 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14413 afi_t afi;
14414 safi_t safi;
718e3744 14415
d62a17ae 14416 afi = bgp_node_afi(vty);
14417 safi = bgp_node_safi(vty);
718e3744 14418
585f1adc
IR
14419 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14420 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14421 || bgp->distance_local[afi][safi] != distance_local) {
14422 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14423 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14424 bgp->distance_local[afi][safi] = distance_local;
14425 bgp_announce_routes_distance_update(bgp, afi, safi);
14426 }
14427 return CMD_SUCCESS;
14428}
37a87b8f 14429
585f1adc
IR
14430DEFUN (no_bgp_distance,
14431 no_bgp_distance_cmd,
14432 "no distance bgp [(1-255) (1-255) (1-255)]",
14433 NO_STR
14434 "Define an administrative distance\n"
14435 "BGP distance\n"
14436 "Distance for routes external to the AS\n"
14437 "Distance for routes internal to the AS\n"
14438 "Distance for local routes\n")
718e3744 14439{
585f1adc 14440 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14441 afi_t afi;
14442 safi_t safi;
37a87b8f
CS
14443
14444 afi = bgp_node_afi(vty);
14445 safi = bgp_node_safi(vty);
14446
585f1adc
IR
14447 if (bgp->distance_ebgp[afi][safi] != 0
14448 || bgp->distance_ibgp[afi][safi] != 0
14449 || bgp->distance_local[afi][safi] != 0) {
14450 bgp->distance_ebgp[afi][safi] = 0;
14451 bgp->distance_ibgp[afi][safi] = 0;
14452 bgp->distance_local[afi][safi] = 0;
14453 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14454 }
585f1adc
IR
14455 return CMD_SUCCESS;
14456}
37a87b8f 14457
37a87b8f 14458
585f1adc
IR
14459DEFUN (bgp_distance_source,
14460 bgp_distance_source_cmd,
14461 "distance (1-255) A.B.C.D/M",
14462 "Define an administrative distance\n"
14463 "Administrative distance\n"
14464 "IP source prefix\n")
14465{
14466 int idx_number = 1;
14467 int idx_ipv4_prefixlen = 2;
14468 bgp_distance_set(vty, argv[idx_number]->arg,
14469 argv[idx_ipv4_prefixlen]->arg, NULL);
14470 return CMD_SUCCESS;
734b349e
MZ
14471}
14472
585f1adc
IR
14473DEFUN (no_bgp_distance_source,
14474 no_bgp_distance_source_cmd,
14475 "no distance (1-255) A.B.C.D/M",
14476 NO_STR
14477 "Define an administrative distance\n"
14478 "Administrative distance\n"
14479 "IP source prefix\n")
37a87b8f 14480{
585f1adc
IR
14481 int idx_number = 2;
14482 int idx_ipv4_prefixlen = 3;
14483 bgp_distance_unset(vty, argv[idx_number]->arg,
14484 argv[idx_ipv4_prefixlen]->arg, NULL);
14485 return CMD_SUCCESS;
37a87b8f
CS
14486}
14487
585f1adc
IR
14488DEFUN (bgp_distance_source_access_list,
14489 bgp_distance_source_access_list_cmd,
14490 "distance (1-255) A.B.C.D/M WORD",
14491 "Define an administrative distance\n"
14492 "Administrative distance\n"
14493 "IP source prefix\n"
14494 "Access list name\n")
37a87b8f 14495{
585f1adc
IR
14496 int idx_number = 1;
14497 int idx_ipv4_prefixlen = 2;
14498 int idx_word = 3;
14499 bgp_distance_set(vty, argv[idx_number]->arg,
14500 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14501 return CMD_SUCCESS;
14502}
718e3744 14503
585f1adc
IR
14504DEFUN (no_bgp_distance_source_access_list,
14505 no_bgp_distance_source_access_list_cmd,
14506 "no distance (1-255) A.B.C.D/M WORD",
14507 NO_STR
14508 "Define an administrative distance\n"
14509 "Administrative distance\n"
14510 "IP source prefix\n"
14511 "Access list name\n")
14512{
14513 int idx_number = 2;
14514 int idx_ipv4_prefixlen = 3;
14515 int idx_word = 4;
14516 bgp_distance_unset(vty, argv[idx_number]->arg,
14517 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14518 return CMD_SUCCESS;
14519}
37a87b8f 14520
585f1adc
IR
14521DEFUN (ipv6_bgp_distance_source,
14522 ipv6_bgp_distance_source_cmd,
14523 "distance (1-255) X:X::X:X/M",
14524 "Define an administrative distance\n"
14525 "Administrative distance\n"
14526 "IP source prefix\n")
14527{
14528 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14529 return CMD_SUCCESS;
14530}
7ebe9748 14531
585f1adc
IR
14532DEFUN (no_ipv6_bgp_distance_source,
14533 no_ipv6_bgp_distance_source_cmd,
14534 "no distance (1-255) X:X::X:X/M",
14535 NO_STR
14536 "Define an administrative distance\n"
14537 "Administrative distance\n"
14538 "IP source prefix\n")
14539{
14540 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14541 return CMD_SUCCESS;
14542}
37a87b8f 14543
585f1adc
IR
14544DEFUN (ipv6_bgp_distance_source_access_list,
14545 ipv6_bgp_distance_source_access_list_cmd,
14546 "distance (1-255) X:X::X:X/M WORD",
14547 "Define an administrative distance\n"
14548 "Administrative distance\n"
14549 "IP source prefix\n"
14550 "Access list name\n")
14551{
14552 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14553 return CMD_SUCCESS;
718e3744 14554}
14555
585f1adc
IR
14556DEFUN (no_ipv6_bgp_distance_source_access_list,
14557 no_ipv6_bgp_distance_source_access_list_cmd,
14558 "no distance (1-255) X:X::X:X/M WORD",
14559 NO_STR
14560 "Define an administrative distance\n"
14561 "Administrative distance\n"
14562 "IP source prefix\n"
14563 "Access list name\n")
718e3744 14564{
585f1adc
IR
14565 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14566 return CMD_SUCCESS;
14567}
37a87b8f 14568
585f1adc
IR
14569DEFUN (bgp_damp_set,
14570 bgp_damp_set_cmd,
14571 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14572 "BGP Specific commands\n"
14573 "Enable route-flap dampening\n"
14574 "Half-life time for the penalty\n"
14575 "Value to start reusing a route\n"
14576 "Value to start suppressing a route\n"
14577 "Maximum duration to suppress a stable route\n")
14578{
14579 VTY_DECLVAR_CONTEXT(bgp, bgp);
14580 int idx_half_life = 2;
14581 int idx_reuse = 3;
14582 int idx_suppress = 4;
14583 int idx_max_suppress = 5;
37a87b8f
CS
14584 int half = DEFAULT_HALF_LIFE * 60;
14585 int reuse = DEFAULT_REUSE;
14586 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14587 int max = 4 * half;
14588
14589 if (argc == 6) {
14590 half = atoi(argv[idx_half_life]->arg) * 60;
14591 reuse = atoi(argv[idx_reuse]->arg);
14592 suppress = atoi(argv[idx_suppress]->arg);
14593 max = atoi(argv[idx_max_suppress]->arg) * 60;
14594 } else if (argc == 3) {
14595 half = atoi(argv[idx_half_life]->arg) * 60;
14596 max = 4 * half;
14597 }
14598
14599 /*
14600 * These can't be 0 but our SA doesn't understand the
14601 * way our cli is constructed
14602 */
14603 assert(reuse);
14604 assert(half);
14605 if (suppress < reuse) {
14606 vty_out(vty,
14607 "Suppress value cannot be less than reuse value \n");
14608 return 0;
14609 }
14610
14611 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14612 reuse, suppress, max);
14613}
14614
14615DEFUN (bgp_damp_unset,
14616 bgp_damp_unset_cmd,
14617 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14618 NO_STR
14619 "BGP Specific commands\n"
14620 "Enable route-flap dampening\n"
14621 "Half-life time for the penalty\n"
14622 "Value to start reusing a route\n"
14623 "Value to start suppressing a route\n"
14624 "Maximum duration to suppress a stable route\n")
14625{
14626 VTY_DECLVAR_CONTEXT(bgp, bgp);
14627 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14628}
14629
718e3744 14630/* Display specified route of BGP table. */
d62a17ae 14631static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14632 const char *ip_str, afi_t afi, safi_t safi,
14633 struct prefix_rd *prd, int prefix_check)
14634{
14635 int ret;
14636 struct prefix match;
9bcb3eef
DS
14637 struct bgp_dest *dest;
14638 struct bgp_dest *rm;
40381db7
DS
14639 struct bgp_path_info *pi;
14640 struct bgp_path_info *pi_temp;
d62a17ae 14641 struct bgp *bgp;
14642 struct bgp_table *table;
14643
14644 /* BGP structure lookup. */
14645 if (view_name) {
14646 bgp = bgp_lookup_by_name(view_name);
14647 if (bgp == NULL) {
14648 vty_out(vty, "%% Can't find BGP instance %s\n",
14649 view_name);
14650 return CMD_WARNING;
14651 }
14652 } else {
14653 bgp = bgp_get_default();
14654 if (bgp == NULL) {
14655 vty_out(vty, "%% No BGP process is configured\n");
14656 return CMD_WARNING;
14657 }
718e3744 14658 }
718e3744 14659
d62a17ae 14660 /* Check IP address argument. */
14661 ret = str2prefix(ip_str, &match);
14662 if (!ret) {
14663 vty_out(vty, "%% address is malformed\n");
14664 return CMD_WARNING;
14665 }
718e3744 14666
d62a17ae 14667 match.family = afi2family(afi);
14668
14669 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14670 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14671 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14672 dest = bgp_route_next(dest)) {
14673 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14674
9bcb3eef 14675 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14676 continue;
9bcb3eef 14677 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14678 if (!table)
ea47320b 14679 continue;
4953391b
DA
14680 rm = bgp_node_match(table, &match);
14681 if (rm == NULL)
ea47320b 14682 continue;
d62a17ae 14683
9bcb3eef 14684 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14685
ea47320b 14686 if (!prefix_check
b54892e0 14687 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14688 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14689 while (pi) {
14690 if (pi->extra && pi->extra->damp_info) {
14691 pi_temp = pi->next;
ea47320b 14692 bgp_damp_info_free(
19971c9a 14693 pi->extra->damp_info,
5c8846f6 14694 1, afi, safi);
40381db7 14695 pi = pi_temp;
ea47320b 14696 } else
40381db7 14697 pi = pi->next;
d62a17ae 14698 }
ea47320b
DL
14699 }
14700
9bcb3eef 14701 bgp_dest_unlock_node(rm);
d62a17ae 14702 }
14703 } else {
4953391b
DA
14704 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14705 if (dest != NULL) {
9bcb3eef 14706 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14707
d62a17ae 14708 if (!prefix_check
9bcb3eef
DS
14709 || dest_p->prefixlen == match.prefixlen) {
14710 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14711 while (pi) {
14712 if (pi->extra && pi->extra->damp_info) {
14713 pi_temp = pi->next;
d62a17ae 14714 bgp_damp_info_free(
19971c9a 14715 pi->extra->damp_info,
5c8846f6 14716 1, afi, safi);
40381db7 14717 pi = pi_temp;
d62a17ae 14718 } else
40381db7 14719 pi = pi->next;
d62a17ae 14720 }
14721 }
14722
9bcb3eef 14723 bgp_dest_unlock_node(dest);
d62a17ae 14724 }
14725 }
718e3744 14726
d62a17ae 14727 return CMD_SUCCESS;
718e3744 14728}
14729
14730DEFUN (clear_ip_bgp_dampening,
14731 clear_ip_bgp_dampening_cmd,
14732 "clear ip bgp dampening",
14733 CLEAR_STR
14734 IP_STR
14735 BGP_STR
14736 "Clear route flap dampening information\n")
14737{
b4f7f45b 14738 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14739 return CMD_SUCCESS;
718e3744 14740}
14741
14742DEFUN (clear_ip_bgp_dampening_prefix,
14743 clear_ip_bgp_dampening_prefix_cmd,
14744 "clear ip bgp dampening A.B.C.D/M",
14745 CLEAR_STR
14746 IP_STR
14747 BGP_STR
14748 "Clear route flap dampening information\n"
0c7b1b01 14749 "IPv4 prefix\n")
718e3744 14750{
d62a17ae 14751 int idx_ipv4_prefixlen = 4;
14752 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14753 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14754}
14755
14756DEFUN (clear_ip_bgp_dampening_address,
14757 clear_ip_bgp_dampening_address_cmd,
14758 "clear ip bgp dampening A.B.C.D",
14759 CLEAR_STR
14760 IP_STR
14761 BGP_STR
14762 "Clear route flap dampening information\n"
14763 "Network to clear damping information\n")
14764{
d62a17ae 14765 int idx_ipv4 = 4;
14766 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14767 SAFI_UNICAST, NULL, 0);
718e3744 14768}
14769
14770DEFUN (clear_ip_bgp_dampening_address_mask,
14771 clear_ip_bgp_dampening_address_mask_cmd,
14772 "clear ip bgp dampening A.B.C.D A.B.C.D",
14773 CLEAR_STR
14774 IP_STR
14775 BGP_STR
14776 "Clear route flap dampening information\n"
14777 "Network to clear damping information\n"
14778 "Network mask\n")
14779{
d62a17ae 14780 int idx_ipv4 = 4;
14781 int idx_ipv4_2 = 5;
14782 int ret;
14783 char prefix_str[BUFSIZ];
718e3744 14784
d62a17ae 14785 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14786 prefix_str, sizeof(prefix_str));
d62a17ae 14787 if (!ret) {
14788 vty_out(vty, "%% Inconsistent address and mask\n");
14789 return CMD_WARNING;
14790 }
718e3744 14791
d62a17ae 14792 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14793 NULL, 0);
718e3744 14794}
6b0655a2 14795
e3b78da8 14796static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14797{
14798 struct vty *vty = arg;
e3b78da8 14799 struct peer *peer = bucket->data;
825d9834
DS
14800 char buf[SU_ADDRSTRLEN];
14801
14802 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14803 sockunion2str(&peer->su, buf, sizeof(buf)));
14804}
14805
2a0e69ae
DS
14806DEFUN (show_bgp_listeners,
14807 show_bgp_listeners_cmd,
14808 "show bgp listeners",
14809 SHOW_STR
14810 BGP_STR
14811 "Display Listen Sockets and who created them\n")
14812{
14813 bgp_dump_listener_info(vty);
14814
14815 return CMD_SUCCESS;
14816}
14817
825d9834
DS
14818DEFUN (show_bgp_peerhash,
14819 show_bgp_peerhash_cmd,
14820 "show bgp peerhash",
14821 SHOW_STR
14822 BGP_STR
14823 "Display information about the BGP peerhash\n")
14824{
14825 struct list *instances = bm->bgp;
14826 struct listnode *node;
14827 struct bgp *bgp;
14828
14829 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14830 vty_out(vty, "BGP: %s\n", bgp->name);
14831 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14832 vty);
14833 }
14834
14835 return CMD_SUCCESS;
14836}
14837
587ff0fd 14838/* also used for encap safi */
2b791107
DL
14839static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14840 afi_t afi, safi_t safi)
d62a17ae 14841{
9bcb3eef
DS
14842 struct bgp_dest *pdest;
14843 struct bgp_dest *dest;
d62a17ae 14844 struct bgp_table *table;
b54892e0
DS
14845 const struct prefix *p;
14846 const struct prefix_rd *prd;
d62a17ae 14847 struct bgp_static *bgp_static;
14848 mpls_label_t label;
d62a17ae 14849 char rdbuf[RD_ADDRSTRLEN];
14850
14851 /* Network configuration. */
9bcb3eef
DS
14852 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14853 pdest = bgp_route_next(pdest)) {
14854 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14855 if (!table)
ea47320b 14856 continue;
d62a17ae 14857
9bcb3eef
DS
14858 for (dest = bgp_table_top(table); dest;
14859 dest = bgp_route_next(dest)) {
14860 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14861 if (bgp_static == NULL)
ea47320b 14862 continue;
d62a17ae 14863
9bcb3eef
DS
14864 p = bgp_dest_get_prefix(dest);
14865 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14866 pdest);
d62a17ae 14867
ea47320b 14868 /* "network" configuration display. */
06b9f471 14869 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14870 label = decode_label(&bgp_static->label);
14871
8228a9a7 14872 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14873 if (safi == SAFI_MPLS_VPN)
14874 vty_out(vty, " label %u", label);
14875
14876 if (bgp_static->rmap.name)
14877 vty_out(vty, " route-map %s",
14878 bgp_static->rmap.name);
e2a86ad9
DS
14879
14880 if (bgp_static->backdoor)
14881 vty_out(vty, " backdoor");
14882
ea47320b
DL
14883 vty_out(vty, "\n");
14884 }
14885 }
d62a17ae 14886}
14887
2b791107
DL
14888static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14889 afi_t afi, safi_t safi)
d62a17ae 14890{
9bcb3eef
DS
14891 struct bgp_dest *pdest;
14892 struct bgp_dest *dest;
d62a17ae 14893 struct bgp_table *table;
b54892e0
DS
14894 const struct prefix *p;
14895 const struct prefix_rd *prd;
d62a17ae 14896 struct bgp_static *bgp_static;
ff44f570 14897 char buf[PREFIX_STRLEN * 2];
d62a17ae 14898 char buf2[SU_ADDRSTRLEN];
14899 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14900 char esi_buf[ESI_BYTES];
d62a17ae 14901
14902 /* Network configuration. */
9bcb3eef
DS
14903 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14904 pdest = bgp_route_next(pdest)) {
14905 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14906 if (!table)
ea47320b 14907 continue;
d62a17ae 14908
9bcb3eef
DS
14909 for (dest = bgp_table_top(table); dest;
14910 dest = bgp_route_next(dest)) {
14911 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14912 if (bgp_static == NULL)
ea47320b 14913 continue;
d62a17ae 14914
ea47320b 14915 char *macrouter = NULL;
d62a17ae 14916
ea47320b
DL
14917 if (bgp_static->router_mac)
14918 macrouter = prefix_mac2str(
14919 bgp_static->router_mac, NULL, 0);
14920 if (bgp_static->eth_s_id)
0a50c248
AK
14921 esi_to_str(bgp_static->eth_s_id,
14922 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14923 p = bgp_dest_get_prefix(dest);
14924 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14925
ea47320b 14926 /* "network" configuration display. */
06b9f471 14927 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14928 if (p->u.prefix_evpn.route_type == 5) {
14929 char local_buf[PREFIX_STRLEN];
3714a385 14930 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14931 struct prefix_evpn *)p)
14932 ? AF_INET
14933 : AF_INET6;
3714a385 14934 inet_ntop(family,
14935 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14936 local_buf, PREFIX_STRLEN);
772270f3
QY
14937 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14938 p->u.prefix_evpn.prefix_addr
14939 .ip_prefix_length);
197cb530
PG
14940 } else {
14941 prefix2str(p, buf, sizeof(buf));
14942 }
ea47320b 14943
a4d82a8a
PZ
14944 if (bgp_static->gatewayIp.family == AF_INET
14945 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14946 inet_ntop(bgp_static->gatewayIp.family,
14947 &bgp_static->gatewayIp.u.prefix, buf2,
14948 sizeof(buf2));
ea47320b 14949 vty_out(vty,
7bcc8dac 14950 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14951 buf, rdbuf,
14952 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14953 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14954 macrouter);
14955
0a22ddfb 14956 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14957 }
14958 }
3da6fcd5
PG
14959}
14960
718e3744 14961/* Configuration of static route announcement and aggregate
14962 information. */
2b791107
DL
14963void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14964 safi_t safi)
d62a17ae 14965{
9bcb3eef 14966 struct bgp_dest *dest;
b54892e0 14967 const struct prefix *p;
d62a17ae 14968 struct bgp_static *bgp_static;
14969 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14970
2b791107
DL
14971 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14972 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14973 return;
14974 }
d62a17ae 14975
2b791107
DL
14976 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14977 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14978 return;
14979 }
d62a17ae 14980
14981 /* Network configuration. */
9bcb3eef
DS
14982 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14983 dest = bgp_route_next(dest)) {
14984 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14985 if (bgp_static == NULL)
ea47320b 14986 continue;
d62a17ae 14987
9bcb3eef 14988 p = bgp_dest_get_prefix(dest);
d62a17ae 14989
8228a9a7 14990 vty_out(vty, " network %pFX", p);
d62a17ae 14991
ea47320b
DL
14992 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14993 vty_out(vty, " label-index %u",
14994 bgp_static->label_index);
d62a17ae 14995
ea47320b
DL
14996 if (bgp_static->rmap.name)
14997 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14998
14999 if (bgp_static->backdoor)
15000 vty_out(vty, " backdoor");
718e3744 15001
ea47320b
DL
15002 vty_out(vty, "\n");
15003 }
15004
d62a17ae 15005 /* Aggregate-address configuration. */
9bcb3eef
DS
15006 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15007 dest = bgp_route_next(dest)) {
15008 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15009 if (bgp_aggregate == NULL)
ea47320b 15010 continue;
d62a17ae 15011
9bcb3eef 15012 p = bgp_dest_get_prefix(dest);
d62a17ae 15013
8228a9a7 15014 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15015
ea47320b
DL
15016 if (bgp_aggregate->as_set)
15017 vty_out(vty, " as-set");
d62a17ae 15018
ea47320b
DL
15019 if (bgp_aggregate->summary_only)
15020 vty_out(vty, " summary-only");
718e3744 15021
20894f50
DA
15022 if (bgp_aggregate->rmap.name)
15023 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15024
229757f1
DA
15025 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15026 vty_out(vty, " origin %s",
15027 bgp_origin2str(bgp_aggregate->origin));
15028
6aabb15d
RZ
15029 if (bgp_aggregate->match_med)
15030 vty_out(vty, " matching-MED-only");
15031
365ab2e7
RZ
15032 if (bgp_aggregate->suppress_map_name)
15033 vty_out(vty, " suppress-map %s",
15034 bgp_aggregate->suppress_map_name);
15035
ea47320b
DL
15036 vty_out(vty, "\n");
15037 }
d62a17ae 15038}
734b349e 15039
2b791107 15040void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15041 safi_t safi)
d62a17ae 15042{
9bcb3eef 15043 struct bgp_dest *dest;
d62a17ae 15044 struct bgp_distance *bdistance;
15045
15046 /* Distance configuration. */
15047 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15048 && bgp->distance_local[afi][safi]
15049 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15050 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15051 || bgp->distance_local[afi][safi]
15052 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15053 vty_out(vty, " distance bgp %d %d %d\n",
15054 bgp->distance_ebgp[afi][safi],
15055 bgp->distance_ibgp[afi][safi],
15056 bgp->distance_local[afi][safi]);
15057 }
734b349e 15058
9bcb3eef
DS
15059 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15060 dest = bgp_route_next(dest)) {
15061 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15062 if (bdistance != NULL)
56ca3b5b 15063 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15064 bdistance->distance, dest,
d62a17ae 15065 bdistance->access_list ? bdistance->access_list
15066 : "");
ca2e160d 15067 }
718e3744 15068}
15069
15070/* Allocate routing table structure and install commands. */
d62a17ae 15071void bgp_route_init(void)
15072{
15073 afi_t afi;
15074 safi_t safi;
15075
15076 /* Init BGP distance table. */
05c7a1cc 15077 FOREACH_AFI_SAFI (afi, safi)
960035b2 15078 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15079
15080 /* IPv4 BGP commands. */
15081 install_element(BGP_NODE, &bgp_table_map_cmd);
15082 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15083 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15084
554b3b10 15085 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15086
15087 /* IPv4 unicast configuration. */
15088 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15089 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15090 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15091
554b3b10 15092 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15093
15094 /* IPv4 multicast configuration. */
15095 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15096 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15097 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15098 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15099
15100 /* IPv4 labeled-unicast configuration. */
fb985e0c 15101 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15102 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15103
d62a17ae 15104 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15105 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 15106 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15107 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 15108 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 15109 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15110 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15111 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15112
15113 install_element(VIEW_NODE,
15114 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15115 install_element(VIEW_NODE,
15116 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15117 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15118 install_element(VIEW_NODE,
15119 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15120#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15121 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15122#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15123 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15124 install_element(VIEW_NODE,
44c69747 15125 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15126
d62a17ae 15127 /* BGP dampening clear commands */
15128 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15129 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15130
d62a17ae 15131 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15132 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15133
15134 /* prefix count */
15135 install_element(ENABLE_NODE,
15136 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15137#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15138 install_element(ENABLE_NODE,
15139 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15140#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15141
d62a17ae 15142 /* New config IPv6 BGP commands. */
15143 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15144 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15145 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15146
554b3b10 15147 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15148
15149 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15150
fb985e0c
DA
15151 /* IPv6 labeled unicast address family. */
15152 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15153 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15154
d62a17ae 15155 install_element(BGP_NODE, &bgp_distance_cmd);
15156 install_element(BGP_NODE, &no_bgp_distance_cmd);
15157 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15158 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15159 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15160 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15161 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15162 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15163 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15164 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15165 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15166 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15167 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15168 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15169 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15170 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15171 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15172 install_element(BGP_IPV4M_NODE,
15173 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15174 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15175 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15176 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15177 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15178 install_element(BGP_IPV6_NODE,
15179 &ipv6_bgp_distance_source_access_list_cmd);
15180 install_element(BGP_IPV6_NODE,
15181 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15182 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15183 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15184 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15185 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15186 install_element(BGP_IPV6M_NODE,
15187 &ipv6_bgp_distance_source_access_list_cmd);
15188 install_element(BGP_IPV6M_NODE,
15189 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15190
ef5f4b23 15191 /* BGP dampening */
585f1adc
IR
15192 install_element(BGP_NODE, &bgp_damp_set_cmd);
15193 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15194 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15195 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15196 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15197 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15198 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15199 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15200 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15201 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15202 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15203 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15204 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15205 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15206
15207 /* Large Communities */
15208 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15209 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15210
15211 /* show bgp ipv4 flowspec detailed */
15212 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15213
2a0e69ae 15214 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15215 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15216}
15217
15218void bgp_route_finish(void)
15219{
15220 afi_t afi;
15221 safi_t safi;
15222
05c7a1cc
QY
15223 FOREACH_AFI_SAFI (afi, safi) {
15224 bgp_table_unlock(bgp_distance_table[afi][safi]);
15225 bgp_distance_table[afi][safi] = NULL;
15226 }
228da428 15227}