]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #8783 from idryzhov/doc-varname
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
37a87b8f
CS
91#include "northbound.h"
92#include "northbound_cli.h"
93#include "bgpd/bgp_nb.h"
65efcfce 94
e2a86ad9
DS
95#ifndef VTYSH_EXTRACT_PL
96#include "bgpd/bgp_route_clippy.c"
97#endif
aee875b5 98
7fd28dd2
PR
99DEFINE_HOOK(bgp_snmp_update_stats,
100 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 101 (rn, pi, added));
7fd28dd2 102
b5b99af8
DS
103DEFINE_HOOK(bgp_rpki_prefix_status,
104 (struct peer *peer, struct attr *attr,
105 const struct prefix *prefix),
8451921b 106 (peer, attr, prefix));
b5b99af8 107
718e3744 108/* Extern from bgp_dump.c */
dde72586
SH
109extern const char *bgp_origin_str[];
110extern const char *bgp_origin_long_str[];
3742de8d 111
b7d08f5a 112/* PMSI strings. */
113#define PMSI_TNLTYPE_STR_NO_INFO "No info"
114#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
115static const struct message bgp_pmsi_tnltype_str[] = {
116 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
117 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
118 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
119 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
120 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
121 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
122 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
123 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 124 {0}
125};
b7d08f5a 126
9df8b37c
PZ
127#define VRFID_NONE_STR "-"
128
4a11bf2c 129DEFINE_HOOK(bgp_process,
9bcb3eef
DS
130 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
131 struct peer *peer, bool withdraw),
8451921b 132 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 133
4056a5f6
RZ
134/** Test if path is suppressed. */
135static bool bgp_path_suppressed(struct bgp_path_info *pi)
136{
137 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
138 return false;
139
140 return listcount(pi->extra->aggr_suppressors) > 0;
141}
4a11bf2c 142
9bcb3eef 143struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 144 safi_t safi, const struct prefix *p,
d62a17ae 145 struct prefix_rd *prd)
146{
9bcb3eef
DS
147 struct bgp_dest *dest;
148 struct bgp_dest *pdest = NULL;
d62a17ae 149
150 assert(table);
d62a17ae 151
152 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
153 || (safi == SAFI_EVPN)) {
9bcb3eef 154 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 155
9bcb3eef
DS
156 if (!bgp_dest_has_bgp_path_info_data(pdest))
157 bgp_dest_set_bgp_table_info(
158 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 159 else
9bcb3eef
DS
160 bgp_dest_unlock_node(pdest);
161 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 162 }
718e3744 163
9bcb3eef 164 dest = bgp_node_get(table, p);
718e3744 165
d62a17ae 166 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
167 || (safi == SAFI_EVPN))
9bcb3eef 168 dest->pdest = pdest;
718e3744 169
9bcb3eef 170 return dest;
718e3744 171}
6b0655a2 172
9bcb3eef 173struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 174 safi_t safi, const struct prefix *p,
d62a17ae 175 struct prefix_rd *prd)
128ea8ab 176{
9bcb3eef
DS
177 struct bgp_dest *dest;
178 struct bgp_dest *pdest = NULL;
128ea8ab 179
d62a17ae 180 if (!table)
181 return NULL;
128ea8ab 182
d62a17ae 183 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
184 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
185 pdest = bgp_node_lookup(table, (struct prefix *)prd);
186 if (!pdest)
d62a17ae 187 return NULL;
128ea8ab 188
9bcb3eef
DS
189 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
190 bgp_dest_unlock_node(pdest);
d62a17ae 191 return NULL;
192 }
128ea8ab 193
9bcb3eef 194 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 195 }
128ea8ab 196
9bcb3eef 197 dest = bgp_node_lookup(table, p);
128ea8ab 198
9bcb3eef 199 return dest;
128ea8ab 200}
201
18ee8310
DS
202/* Allocate bgp_path_info_extra */
203static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 204{
4b7e6066
DS
205 struct bgp_path_info_extra *new;
206 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
207 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
208 new->label[0] = MPLS_INVALID_LABEL;
209 new->num_labels = 0;
3e3708cb
PG
210 new->bgp_fs_pbr = NULL;
211 new->bgp_fs_iprule = NULL;
d62a17ae 212 return new;
fb982c25
PJ
213}
214
a2e219fe 215void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 216{
4b7e6066 217 struct bgp_path_info_extra *e;
d62a17ae 218
c93a3b77
DS
219 if (!extra || !*extra)
220 return;
d62a17ae 221
c93a3b77 222 e = *extra;
d62a17ae 223
c93a3b77
DS
224 e->damp_info = NULL;
225 if (e->parent) {
40381db7 226 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 227
40381db7 228 if (bpi->net) {
0e70e6c8
DL
229 /* FIXME: since multiple e may have the same e->parent
230 * and e->parent->net is holding a refcount for each
231 * of them, we need to do some fudging here.
232 *
40381db7
DS
233 * WARNING: if bpi->net->lock drops to 0, bpi may be
234 * freed as well (because bpi->net was holding the
235 * last reference to bpi) => write after free!
0e70e6c8
DL
236 */
237 unsigned refcount;
238
40381db7 239 bpi = bgp_path_info_lock(bpi);
c10e14e9 240 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 241 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 242 if (!refcount)
40381db7
DS
243 bpi->net = NULL;
244 bgp_path_info_unlock(bpi);
0e70e6c8 245 }
18ee8310 246 bgp_path_info_unlock(e->parent);
c93a3b77 247 e->parent = NULL;
d62a17ae 248 }
c93a3b77
DS
249
250 if (e->bgp_orig)
251 bgp_unlock(e->bgp_orig);
c26edcda 252
ff3bf9a4
DS
253 if (e->aggr_suppressors)
254 list_delete(&e->aggr_suppressors);
255
60605cbc
AK
256 if (e->mh_info)
257 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 258
ce3c0614
PG
259 if ((*extra)->bgp_fs_iprule)
260 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 261 if ((*extra)->bgp_fs_pbr)
6a154c88 262 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 263 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
264}
265
18ee8310
DS
266/* Get bgp_path_info extra information for the given bgp_path_info, lazy
267 * allocated if required.
fb982c25 268 */
40381db7 269struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 270{
40381db7
DS
271 if (!pi->extra)
272 pi->extra = bgp_path_info_extra_new();
273 return pi->extra;
fb982c25
PJ
274}
275
718e3744 276/* Free bgp route information. */
9b6d8fcf 277static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 278{
05864da7 279 bgp_attr_unintern(&path->attr);
fb018d25 280
9b6d8fcf
DS
281 bgp_unlink_nexthop(path);
282 bgp_path_info_extra_free(&path->extra);
283 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
284 if (path->net)
285 bgp_addpath_free_info_data(&path->tx_addpath,
286 &path->net->tx_addpath);
718e3744 287
9b6d8fcf 288 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 289
9b6d8fcf 290 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 291}
292
9b6d8fcf 293struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 294{
9b6d8fcf
DS
295 path->lock++;
296 return path;
200df115 297}
298
9b6d8fcf 299struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 300{
9b6d8fcf
DS
301 assert(path && path->lock > 0);
302 path->lock--;
d62a17ae 303
9b6d8fcf 304 if (path->lock == 0) {
200df115 305#if 0
306 zlog_debug ("%s: unlocked and freeing", __func__);
307 zlog_backtrace (LOG_DEBUG);
308#endif
9b6d8fcf 309 bgp_path_info_free(path);
d62a17ae 310 return NULL;
311 }
200df115 312
313#if 0
9b6d8fcf 314 if (path->lock == 1)
200df115 315 {
316 zlog_debug ("%s: unlocked to 1", __func__);
317 zlog_backtrace (LOG_DEBUG);
318 }
319#endif
d62a17ae 320
9b6d8fcf 321 return path;
200df115 322}
323
f009ff26 324/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 325static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 326{
327 struct peer *peer;
328 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 329 bool set_flag = false;
f009ff26 330 struct bgp *bgp = NULL;
331 struct bgp_table *table = NULL;
332 afi_t afi = 0;
333 safi_t safi = 0;
f009ff26 334
335 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
336 * then the route selection is deferred
337 */
9bcb3eef 338 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 339 return 0;
340
9bcb3eef 341 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 342 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 343 zlog_debug(
56ca3b5b
DL
344 "Route %pBD is in workqueue and being processed, not deferred.",
345 dest);
b54892e0 346
5f9c1aa2 347 return 0;
348 }
349
9bcb3eef 350 table = bgp_dest_table(dest);
f009ff26 351 if (table) {
352 bgp = table->bgp;
353 afi = table->afi;
354 safi = table->safi;
355 }
356
9bcb3eef 357 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 358 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
359 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
360 continue;
361
362 /* Route selection is deferred if there is a stale path which
363 * which indicates peer is in restart mode
364 */
36235319
QY
365 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
366 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 367 set_flag = true;
f009ff26 368 } else {
369 /* If the peer is graceful restart capable and peer is
370 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
371 */
372 peer = old_pi->peer;
36235319
QY
373 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
374 && BGP_PEER_RESTARTING_MODE(peer)
375 && (old_pi
376 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 377 set_flag = true;
f009ff26 378 }
379 }
380 if (set_flag)
381 break;
382 }
383
384 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
385 * is active
386 */
2ba1fe69 387 if (set_flag && table) {
f009ff26 388 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
389 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
390 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 391 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 392 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
393 zlog_debug("DEFER route %pBD, dest %p", dest,
394 dest);
f009ff26 395 return 0;
396 }
397 }
398 return -1;
399}
400
9bcb3eef 401void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 402{
4b7e6066 403 struct bgp_path_info *top;
718e3744 404
9bcb3eef 405 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 406
6f94b685 407 pi->next = top;
40381db7 408 pi->prev = NULL;
d62a17ae 409 if (top)
40381db7 410 top->prev = pi;
9bcb3eef 411 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 412
40381db7 413 bgp_path_info_lock(pi);
9bcb3eef 414 bgp_dest_lock_node(dest);
40381db7 415 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 416 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 417 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 418}
419
d62a17ae 420/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 421 completion callback *only* */
9bcb3eef 422void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 423{
40381db7
DS
424 if (pi->next)
425 pi->next->prev = pi->prev;
426 if (pi->prev)
427 pi->prev->next = pi->next;
d62a17ae 428 else
9bcb3eef 429 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 430
40381db7
DS
431 bgp_path_info_mpath_dequeue(pi);
432 bgp_path_info_unlock(pi);
7fd28dd2 433 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 434 bgp_dest_unlock_node(dest);
718e3744 435}
436
9bcb3eef 437void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 438{
9bcb3eef 439 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 440 /* set of previous already took care of pcount */
40381db7 441 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 442}
443
18ee8310 444/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
445 called when a route is deleted and then quickly re-added before the
446 deletion has been processed */
9bcb3eef 447void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 448{
9bcb3eef 449 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 450 /* unset of previous already took care of pcount */
40381db7 451 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
452}
453
d62a17ae 454/* Adjust pcount as required */
9bcb3eef 455static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 456{
d62a17ae 457 struct bgp_table *table;
67174041 458
9bcb3eef 459 assert(dest && bgp_dest_table(dest));
40381db7 460 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 461
9bcb3eef 462 table = bgp_dest_table(dest);
67174041 463
40381db7 464 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 465 return;
466
40381db7
DS
467 if (!BGP_PATH_COUNTABLE(pi)
468 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 469
40381db7 470 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 471
472 /* slight hack, but more robust against errors. */
40381db7
DS
473 if (pi->peer->pcount[table->afi][table->safi])
474 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 475 else
450971aa 476 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 477 "Asked to decrement 0 prefix count for peer");
40381db7
DS
478 } else if (BGP_PATH_COUNTABLE(pi)
479 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
480 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
481 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 482 }
1a392d46
PJ
483}
484
40381db7
DS
485static int bgp_label_index_differs(struct bgp_path_info *pi1,
486 struct bgp_path_info *pi2)
28d58fd7 487{
40381db7 488 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 489}
1a392d46 490
18ee8310 491/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
492 * This is here primarily to keep prefix-count in check.
493 */
9bcb3eef 494void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 495 uint32_t flag)
1a392d46 496{
40381db7 497 SET_FLAG(pi->flags, flag);
d62a17ae 498
499 /* early bath if we know it's not a flag that changes countability state
500 */
501 if (!CHECK_FLAG(flag,
1defdda8 502 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 503 return;
504
9bcb3eef 505 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
506}
507
9bcb3eef 508void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 509 uint32_t flag)
1a392d46 510{
40381db7 511 UNSET_FLAG(pi->flags, flag);
d62a17ae 512
513 /* early bath if we know it's not a flag that changes countability state
514 */
515 if (!CHECK_FLAG(flag,
1defdda8 516 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 517 return;
518
9bcb3eef 519 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
520}
521
718e3744 522/* Get MED value. If MED value is missing and "bgp bestpath
523 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 524static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 525{
526 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
527 return attr->med;
528 else {
892fedb6 529 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 530 return BGP_MED_MAX;
531 else
532 return 0;
533 }
718e3744 534}
535
7533cad7
QY
536void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
537 size_t buf_len)
2ec1e66f 538{
40381db7 539 if (pi->addpath_rx_id)
7533cad7
QY
540 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
541 pi->peer->host, pi->addpath_rx_id);
d62a17ae 542 else
7533cad7 543 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 544}
9fbdd100 545
d62a17ae 546/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
547 */
18ee8310
DS
548static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
549 struct bgp_path_info *exist, int *paths_eq,
550 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
551 char *pfx_buf, afi_t afi, safi_t safi,
552 enum bgp_path_selection_reason *reason)
d62a17ae 553{
5df26422 554 const struct prefix *new_p;
d62a17ae 555 struct attr *newattr, *existattr;
556 bgp_peer_sort_t new_sort;
557 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
558 uint32_t new_pref;
559 uint32_t exist_pref;
560 uint32_t new_med;
561 uint32_t exist_med;
562 uint32_t new_weight;
563 uint32_t exist_weight;
d62a17ae 564 uint32_t newm, existm;
565 struct in_addr new_id;
566 struct in_addr exist_id;
567 int new_cluster;
568 int exist_cluster;
569 int internal_as_route;
570 int confed_as_route;
04d14c8b 571 int ret = 0;
ee88563a
JM
572 int igp_metric_ret = 0;
573 int peer_sort_ret = -1;
d62a17ae 574 char new_buf[PATH_ADDPATH_STR_BUFFER];
575 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
576 uint32_t new_mm_seq;
577 uint32_t exist_mm_seq;
6d8c603a 578 int nh_cmp;
d071f237
AK
579 esi_t *exist_esi;
580 esi_t *new_esi;
581 bool same_esi;
582 bool old_proxy;
583 bool new_proxy;
33c6e933 584 bool new_origin, exist_origin;
d62a17ae 585
586 *paths_eq = 0;
587
588 /* 0. Null check. */
589 if (new == NULL) {
fdf81fa0 590 *reason = bgp_path_selection_none;
d62a17ae 591 if (debug)
592 zlog_debug("%s: new is NULL", pfx_buf);
593 return 0;
594 }
2ec1e66f 595
d62a17ae 596 if (debug)
7533cad7
QY
597 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
598 sizeof(new_buf));
718e3744 599
d62a17ae 600 if (exist == NULL) {
fdf81fa0 601 *reason = bgp_path_selection_first;
d62a17ae 602 if (debug)
603 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
604 new_buf);
605 return 1;
606 }
2ec1e66f 607
d62a17ae 608 if (debug) {
7533cad7
QY
609 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
610 sizeof(exist_buf));
d62a17ae 611 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
612 pfx_buf, new_buf, new->flags, exist_buf,
613 exist->flags);
614 }
8ff56318 615
d62a17ae 616 newattr = new->attr;
617 existattr = exist->attr;
618
5df26422
NS
619 new_p = bgp_dest_get_prefix(new->net);
620
d62a17ae 621 /* For EVPN routes, we cannot just go by local vs remote, we have to
622 * look at the MAC mobility sequence number, if present.
623 */
5df26422
NS
624 if ((safi == SAFI_EVPN)
625 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 626 /* This is an error condition described in RFC 7432 Section
627 * 15.2. The RFC
628 * states that in this scenario "the PE MUST alert the operator"
629 * but it
630 * does not state what other action to take. In order to provide
631 * some
632 * consistency in this scenario we are going to prefer the path
633 * with the
634 * sticky flag.
635 */
636 if (newattr->sticky != existattr->sticky) {
637 if (!debug) {
5df26422
NS
638 prefix2str(new_p, pfx_buf,
639 sizeof(*pfx_buf)
640 * PREFIX2STR_BUFFER);
18ee8310 641 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
642 new, new_buf, sizeof(new_buf));
643 bgp_path_info_path_with_addpath_rx_str(
644 exist, exist_buf, sizeof(exist_buf));
d62a17ae 645 }
646
647 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 648 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
649 if (debug)
650 zlog_debug(
651 "%s: %s wins over %s due to sticky MAC flag",
652 pfx_buf, new_buf, exist_buf);
d62a17ae 653 return 1;
654 }
655
656 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 657 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
658 if (debug)
659 zlog_debug(
660 "%s: %s loses to %s due to sticky MAC flag",
661 pfx_buf, new_buf, exist_buf);
d62a17ae 662 return 0;
663 }
664 }
128ea8ab 665
d071f237
AK
666 new_esi = bgp_evpn_attr_get_esi(newattr);
667 exist_esi = bgp_evpn_attr_get_esi(existattr);
668 if (bgp_evpn_is_esi_valid(new_esi) &&
669 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
670 same_esi = true;
671 } else {
672 same_esi = false;
673 }
674
675 /* If both paths have the same non-zero ES and
676 * one path is local it wins.
677 * PS: Note the local path wins even if the remote
678 * has the higher MM seq. The local path's
679 * MM seq will be fixed up to match the highest
680 * rem seq, subsequently.
681 */
682 if (same_esi) {
683 char esi_buf[ESI_STR_LEN];
684
685 if (bgp_evpn_is_path_local(bgp, new)) {
686 *reason = bgp_path_selection_evpn_local_path;
687 if (debug)
688 zlog_debug(
689 "%s: %s wins over %s as ES %s is same and local",
690 pfx_buf, new_buf, exist_buf,
691 esi_to_str(new_esi, esi_buf,
692 sizeof(esi_buf)));
693 return 1;
694 }
695 if (bgp_evpn_is_path_local(bgp, exist)) {
696 *reason = bgp_path_selection_evpn_local_path;
697 if (debug)
698 zlog_debug(
699 "%s: %s loses to %s as ES %s is same and local",
700 pfx_buf, new_buf, exist_buf,
701 esi_to_str(new_esi, esi_buf,
702 sizeof(esi_buf)));
703 return 0;
704 }
705 }
706
d62a17ae 707 new_mm_seq = mac_mobility_seqnum(newattr);
708 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 709
d62a17ae 710 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 711 *reason = bgp_path_selection_evpn_seq;
d62a17ae 712 if (debug)
713 zlog_debug(
714 "%s: %s wins over %s due to MM seq %u > %u",
715 pfx_buf, new_buf, exist_buf, new_mm_seq,
716 exist_mm_seq);
717 return 1;
718 }
8ff56318 719
d62a17ae 720 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 721 *reason = bgp_path_selection_evpn_seq;
d62a17ae 722 if (debug)
723 zlog_debug(
724 "%s: %s loses to %s due to MM seq %u < %u",
725 pfx_buf, new_buf, exist_buf, new_mm_seq,
726 exist_mm_seq);
727 return 0;
728 }
6d8c603a 729
d071f237
AK
730 /* if the sequence numbers and ESI are the same and one path
731 * is non-proxy it wins (over proxy)
732 */
733 new_proxy = bgp_evpn_attr_is_proxy(newattr);
734 old_proxy = bgp_evpn_attr_is_proxy(existattr);
735 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
736 old_proxy != new_proxy) {
737 if (!new_proxy) {
738 *reason = bgp_path_selection_evpn_non_proxy;
739 if (debug)
740 zlog_debug(
741 "%s: %s wins over %s, same seq/es and non-proxy",
742 pfx_buf, new_buf, exist_buf);
743 return 1;
744 }
745
746 *reason = bgp_path_selection_evpn_non_proxy;
747 if (debug)
748 zlog_debug(
749 "%s: %s loses to %s, same seq/es and non-proxy",
750 pfx_buf, new_buf, exist_buf);
751 return 0;
752 }
753
6d8c603a
AK
754 /*
755 * if sequence numbers are the same path with the lowest IP
756 * wins
757 */
758 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
759 if (nh_cmp < 0) {
fdf81fa0 760 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
761 if (debug)
762 zlog_debug(
23d0a753 763 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 764 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 765 &new->attr->nexthop);
6d8c603a
AK
766 return 1;
767 }
768 if (nh_cmp > 0) {
fdf81fa0 769 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
770 if (debug)
771 zlog_debug(
23d0a753 772 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 773 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 774 &new->attr->nexthop);
6d8c603a
AK
775 return 0;
776 }
d62a17ae 777 }
9fbdd100 778
d62a17ae 779 /* 1. Weight check. */
d62a17ae 780 new_weight = newattr->weight;
781 exist_weight = existattr->weight;
8ff56318 782
d62a17ae 783 if (new_weight > exist_weight) {
fdf81fa0 784 *reason = bgp_path_selection_weight;
d62a17ae 785 if (debug)
786 zlog_debug("%s: %s wins over %s due to weight %d > %d",
787 pfx_buf, new_buf, exist_buf, new_weight,
788 exist_weight);
789 return 1;
790 }
718e3744 791
d62a17ae 792 if (new_weight < exist_weight) {
fdf81fa0 793 *reason = bgp_path_selection_weight;
d62a17ae 794 if (debug)
795 zlog_debug("%s: %s loses to %s due to weight %d < %d",
796 pfx_buf, new_buf, exist_buf, new_weight,
797 exist_weight);
798 return 0;
799 }
9fbdd100 800
d62a17ae 801 /* 2. Local preference check. */
802 new_pref = exist_pref = bgp->default_local_pref;
803
804 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
805 new_pref = newattr->local_pref;
806 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
807 exist_pref = existattr->local_pref;
808
809 if (new_pref > exist_pref) {
fdf81fa0 810 *reason = bgp_path_selection_local_pref;
d62a17ae 811 if (debug)
812 zlog_debug(
813 "%s: %s wins over %s due to localpref %d > %d",
814 pfx_buf, new_buf, exist_buf, new_pref,
815 exist_pref);
816 return 1;
817 }
718e3744 818
d62a17ae 819 if (new_pref < exist_pref) {
fdf81fa0 820 *reason = bgp_path_selection_local_pref;
d62a17ae 821 if (debug)
822 zlog_debug(
823 "%s: %s loses to %s due to localpref %d < %d",
824 pfx_buf, new_buf, exist_buf, new_pref,
825 exist_pref);
826 return 0;
827 }
9fbdd100 828
d62a17ae 829 /* 3. Local route check. We prefer:
830 * - BGP_ROUTE_STATIC
831 * - BGP_ROUTE_AGGREGATE
832 * - BGP_ROUTE_REDISTRIBUTE
833 */
33c6e933
DS
834 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
835 new->sub_type == BGP_ROUTE_IMPORTED);
836 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
837 exist->sub_type == BGP_ROUTE_IMPORTED);
838
839 if (new_origin && !exist_origin) {
fdf81fa0 840 *reason = bgp_path_selection_local_route;
d62a17ae 841 if (debug)
842 zlog_debug(
843 "%s: %s wins over %s due to preferred BGP_ROUTE type",
844 pfx_buf, new_buf, exist_buf);
845 return 1;
846 }
718e3744 847
33c6e933 848 if (!new_origin && exist_origin) {
fdf81fa0 849 *reason = bgp_path_selection_local_route;
d62a17ae 850 if (debug)
851 zlog_debug(
852 "%s: %s loses to %s due to preferred BGP_ROUTE type",
853 pfx_buf, new_buf, exist_buf);
854 return 0;
6811845b 855 }
718e3744 856
d62a17ae 857 /* 4. AS path length check. */
892fedb6 858 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 859 int exist_hops = aspath_count_hops(existattr->aspath);
860 int exist_confeds = aspath_count_confeds(existattr->aspath);
861
892fedb6 862 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 863 int aspath_hops;
864
865 aspath_hops = aspath_count_hops(newattr->aspath);
866 aspath_hops += aspath_count_confeds(newattr->aspath);
867
868 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 869 *reason = bgp_path_selection_confed_as_path;
d62a17ae 870 if (debug)
871 zlog_debug(
872 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
873 pfx_buf, new_buf, exist_buf,
874 aspath_hops,
875 (exist_hops + exist_confeds));
876 return 1;
877 }
878
879 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 880 *reason = bgp_path_selection_confed_as_path;
d62a17ae 881 if (debug)
882 zlog_debug(
883 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
884 pfx_buf, new_buf, exist_buf,
885 aspath_hops,
886 (exist_hops + exist_confeds));
887 return 0;
888 }
889 } else {
890 int newhops = aspath_count_hops(newattr->aspath);
891
892 if (newhops < exist_hops) {
fdf81fa0 893 *reason = bgp_path_selection_as_path;
d62a17ae 894 if (debug)
895 zlog_debug(
896 "%s: %s wins over %s due to aspath hopcount %d < %d",
897 pfx_buf, new_buf, exist_buf,
898 newhops, exist_hops);
899 return 1;
900 }
901
902 if (newhops > exist_hops) {
fdf81fa0 903 *reason = bgp_path_selection_as_path;
d62a17ae 904 if (debug)
905 zlog_debug(
906 "%s: %s loses to %s due to aspath hopcount %d > %d",
907 pfx_buf, new_buf, exist_buf,
908 newhops, exist_hops);
909 return 0;
910 }
911 }
912 }
9fbdd100 913
d62a17ae 914 /* 5. Origin check. */
915 if (newattr->origin < existattr->origin) {
fdf81fa0 916 *reason = bgp_path_selection_origin;
d62a17ae 917 if (debug)
918 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
919 pfx_buf, new_buf, exist_buf,
920 bgp_origin_long_str[newattr->origin],
921 bgp_origin_long_str[existattr->origin]);
922 return 1;
923 }
718e3744 924
d62a17ae 925 if (newattr->origin > existattr->origin) {
fdf81fa0 926 *reason = bgp_path_selection_origin;
d62a17ae 927 if (debug)
928 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
929 pfx_buf, new_buf, exist_buf,
930 bgp_origin_long_str[newattr->origin],
931 bgp_origin_long_str[existattr->origin]);
932 return 0;
933 }
718e3744 934
d62a17ae 935 /* 6. MED check. */
936 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
937 && aspath_count_hops(existattr->aspath) == 0);
938 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
939 && aspath_count_confeds(existattr->aspath) > 0
940 && aspath_count_hops(newattr->aspath) == 0
941 && aspath_count_hops(existattr->aspath) == 0);
942
892fedb6
DA
943 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
944 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 945 || aspath_cmp_left(newattr->aspath, existattr->aspath)
946 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
947 || internal_as_route) {
948 new_med = bgp_med_value(new->attr, bgp);
949 exist_med = bgp_med_value(exist->attr, bgp);
950
951 if (new_med < exist_med) {
fdf81fa0 952 *reason = bgp_path_selection_med;
d62a17ae 953 if (debug)
954 zlog_debug(
955 "%s: %s wins over %s due to MED %d < %d",
956 pfx_buf, new_buf, exist_buf, new_med,
957 exist_med);
958 return 1;
959 }
8ff56318 960
d62a17ae 961 if (new_med > exist_med) {
fdf81fa0 962 *reason = bgp_path_selection_med;
d62a17ae 963 if (debug)
964 zlog_debug(
965 "%s: %s loses to %s due to MED %d > %d",
966 pfx_buf, new_buf, exist_buf, new_med,
967 exist_med);
968 return 0;
969 }
970 }
9fbdd100 971
d62a17ae 972 /* 7. Peer type check. */
973 new_sort = new->peer->sort;
974 exist_sort = exist->peer->sort;
975
976 if (new_sort == BGP_PEER_EBGP
977 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 978 *reason = bgp_path_selection_peer;
d62a17ae 979 if (debug)
980 zlog_debug(
981 "%s: %s wins over %s due to eBGP peer > iBGP peer",
982 pfx_buf, new_buf, exist_buf);
ee88563a
JM
983 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
984 return 1;
985 peer_sort_ret = 1;
d62a17ae 986 }
718e3744 987
d62a17ae 988 if (exist_sort == BGP_PEER_EBGP
989 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 990 *reason = bgp_path_selection_peer;
d62a17ae 991 if (debug)
992 zlog_debug(
993 "%s: %s loses to %s due to iBGP peer < eBGP peer",
994 pfx_buf, new_buf, exist_buf);
ee88563a
JM
995 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
996 return 0;
997 peer_sort_ret = 0;
d62a17ae 998 }
8ff56318 999
d62a17ae 1000 /* 8. IGP metric check. */
1001 newm = existm = 0;
8ff56318 1002
d62a17ae 1003 if (new->extra)
1004 newm = new->extra->igpmetric;
1005 if (exist->extra)
1006 existm = exist->extra->igpmetric;
9fbdd100 1007
d62a17ae 1008 if (newm < existm) {
ee88563a 1009 if (debug && peer_sort_ret < 0)
d62a17ae 1010 zlog_debug(
d588b995 1011 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1012 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1013 igp_metric_ret = 1;
d62a17ae 1014 }
718e3744 1015
d62a17ae 1016 if (newm > existm) {
ee88563a 1017 if (debug && peer_sort_ret < 0)
d62a17ae 1018 zlog_debug(
d588b995 1019 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1020 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1021 igp_metric_ret = 0;
5e242b0d 1022 }
5e242b0d 1023
d62a17ae 1024 /* 9. Same IGP metric. Compare the cluster list length as
1025 representative of IGP hops metric. Rewrite the metric value
1026 pair (newm, existm) with the cluster list length. Prefer the
1027 path with smaller cluster list length. */
1028 if (newm == existm) {
bf0d28dc
DS
1029 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1030 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1031 && (mpath_cfg == NULL
1032 || CHECK_FLAG(
1033 mpath_cfg->ibgp_flags,
1034 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1035 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1036 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1037
1038 if (newm < existm) {
ee88563a 1039 if (debug && peer_sort_ret < 0)
d62a17ae 1040 zlog_debug(
d588b995 1041 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1042 pfx_buf, new_buf, exist_buf,
1043 newm, existm);
ee88563a 1044 igp_metric_ret = 1;
d62a17ae 1045 }
1046
1047 if (newm > existm) {
ee88563a 1048 if (debug && peer_sort_ret < 0)
d62a17ae 1049 zlog_debug(
d588b995 1050 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1051 pfx_buf, new_buf, exist_buf,
1052 newm, existm);
ee88563a 1053 igp_metric_ret = 0;
d62a17ae 1054 }
1055 }
1056 }
31a4638f 1057
d62a17ae 1058 /* 10. confed-external vs. confed-internal */
1059 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1060 if (new_sort == BGP_PEER_CONFED
1061 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1062 *reason = bgp_path_selection_confed;
d62a17ae 1063 if (debug)
1064 zlog_debug(
1065 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1066 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1067 if (!CHECK_FLAG(bgp->flags,
1068 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1069 return 1;
1070 peer_sort_ret = 1;
d62a17ae 1071 }
718e3744 1072
d62a17ae 1073 if (exist_sort == BGP_PEER_CONFED
1074 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1075 *reason = bgp_path_selection_confed;
d62a17ae 1076 if (debug)
1077 zlog_debug(
1078 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1079 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1080 if (!CHECK_FLAG(bgp->flags,
1081 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1082 return 0;
1083 peer_sort_ret = 0;
d62a17ae 1084 }
1085 }
718e3744 1086
d62a17ae 1087 /* 11. Maximum path check. */
1088 if (newm == existm) {
1089 /* If one path has a label but the other does not, do not treat
1090 * them as equals for multipath
1091 */
a4d82a8a 1092 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1093 != (exist->extra
b57ba6d2 1094 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1095 if (debug)
1096 zlog_debug(
1097 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1098 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1099 } else if (CHECK_FLAG(bgp->flags,
1100 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1101
1102 /*
1103 * For the two paths, all comparison steps till IGP
1104 * metric
1105 * have succeeded - including AS_PATH hop count. Since
1106 * 'bgp
1107 * bestpath as-path multipath-relax' knob is on, we
1108 * don't need
1109 * an exact match of AS_PATH. Thus, mark the paths are
1110 * equal.
1111 * That will trigger both these paths to get into the
1112 * multipath
1113 * array.
1114 */
1115 *paths_eq = 1;
1116
1117 if (debug)
1118 zlog_debug(
1119 "%s: %s and %s are equal via multipath-relax",
1120 pfx_buf, new_buf, exist_buf);
1121 } else if (new->peer->sort == BGP_PEER_IBGP) {
1122 if (aspath_cmp(new->attr->aspath,
1123 exist->attr->aspath)) {
1124 *paths_eq = 1;
1125
1126 if (debug)
1127 zlog_debug(
1128 "%s: %s and %s are equal via matching aspaths",
1129 pfx_buf, new_buf, exist_buf);
1130 }
1131 } else if (new->peer->as == exist->peer->as) {
1132 *paths_eq = 1;
1133
1134 if (debug)
1135 zlog_debug(
1136 "%s: %s and %s are equal via same remote-as",
1137 pfx_buf, new_buf, exist_buf);
1138 }
1139 } else {
1140 /*
1141 * TODO: If unequal cost ibgp multipath is enabled we can
1142 * mark the paths as equal here instead of returning
1143 */
ee88563a
JM
1144
1145 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1146 * if either step 7 or 10 (peer type checks) yielded a winner,
1147 * that result was returned immediately. Returning from step 10
1148 * ignored the return value computed in steps 8 and 9 (IGP
1149 * metric checks). In order to preserve that behavior, if
1150 * peer_sort_ret is set, return that rather than igp_metric_ret.
1151 */
1152 ret = peer_sort_ret;
1153 if (peer_sort_ret < 0) {
1154 ret = igp_metric_ret;
1155 if (debug) {
1156 if (ret == 1)
1157 zlog_debug(
1158 "%s: %s wins over %s after IGP metric comparison",
1159 pfx_buf, new_buf, exist_buf);
1160 else
1161 zlog_debug(
1162 "%s: %s loses to %s after IGP metric comparison",
1163 pfx_buf, new_buf, exist_buf);
1164 }
1165 *reason = bgp_path_selection_igp_metric;
d62a17ae 1166 }
1167 return ret;
1168 }
718e3744 1169
ee88563a
JM
1170 /*
1171 * At this point, the decision whether to set *paths_eq = 1 has been
1172 * completed. If we deferred returning because of bestpath peer-type
1173 * relax configuration, return now.
1174 */
1175 if (peer_sort_ret >= 0)
1176 return peer_sort_ret;
1177
d62a17ae 1178 /* 12. If both paths are external, prefer the path that was received
1179 first (the oldest one). This step minimizes route-flap, since a
1180 newer path won't displace an older one, even if it was the
1181 preferred route based on the additional decision criteria below. */
892fedb6 1182 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1183 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1184 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1185 *reason = bgp_path_selection_older;
d62a17ae 1186 if (debug)
1187 zlog_debug(
1188 "%s: %s wins over %s due to oldest external",
1189 pfx_buf, new_buf, exist_buf);
1190 return 1;
1191 }
9fbdd100 1192
1defdda8 1193 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1194 *reason = bgp_path_selection_older;
d62a17ae 1195 if (debug)
1196 zlog_debug(
1197 "%s: %s loses to %s due to oldest external",
1198 pfx_buf, new_buf, exist_buf);
1199 return 0;
1200 }
1201 }
718e3744 1202
d62a17ae 1203 /* 13. Router-ID comparision. */
1204 /* If one of the paths is "stale", the corresponding peer router-id will
1205 * be 0 and would always win over the other path. If originator id is
1206 * used for the comparision, it will decide which path is better.
1207 */
1208 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1209 new_id.s_addr = newattr->originator_id.s_addr;
1210 else
1211 new_id.s_addr = new->peer->remote_id.s_addr;
1212 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1213 exist_id.s_addr = existattr->originator_id.s_addr;
1214 else
1215 exist_id.s_addr = exist->peer->remote_id.s_addr;
1216
1217 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1218 *reason = bgp_path_selection_router_id;
d62a17ae 1219 if (debug)
1220 zlog_debug(
1221 "%s: %s wins over %s due to Router-ID comparison",
1222 pfx_buf, new_buf, exist_buf);
1223 return 1;
1224 }
718e3744 1225
d62a17ae 1226 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1227 *reason = bgp_path_selection_router_id;
d62a17ae 1228 if (debug)
1229 zlog_debug(
1230 "%s: %s loses to %s due to Router-ID comparison",
1231 pfx_buf, new_buf, exist_buf);
1232 return 0;
1233 }
9fbdd100 1234
d62a17ae 1235 /* 14. Cluster length comparision. */
1236 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1237 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1238
1239 if (new_cluster < exist_cluster) {
fdf81fa0 1240 *reason = bgp_path_selection_cluster_length;
d62a17ae 1241 if (debug)
1242 zlog_debug(
1243 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1244 pfx_buf, new_buf, exist_buf, new_cluster,
1245 exist_cluster);
1246 return 1;
1247 }
718e3744 1248
d62a17ae 1249 if (new_cluster > exist_cluster) {
fdf81fa0 1250 *reason = bgp_path_selection_cluster_length;
d62a17ae 1251 if (debug)
1252 zlog_debug(
1253 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1254 pfx_buf, new_buf, exist_buf, new_cluster,
1255 exist_cluster);
1256 return 0;
1257 }
9fbdd100 1258
d62a17ae 1259 /* 15. Neighbor address comparision. */
1260 /* Do this only if neither path is "stale" as stale paths do not have
1261 * valid peer information (as the connection may or may not be up).
1262 */
1defdda8 1263 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1264 *reason = bgp_path_selection_stale;
d62a17ae 1265 if (debug)
1266 zlog_debug(
1267 "%s: %s wins over %s due to latter path being STALE",
1268 pfx_buf, new_buf, exist_buf);
1269 return 1;
1270 }
0de5153c 1271
1defdda8 1272 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1273 *reason = bgp_path_selection_stale;
d62a17ae 1274 if (debug)
1275 zlog_debug(
1276 "%s: %s loses to %s due to former path being STALE",
1277 pfx_buf, new_buf, exist_buf);
1278 return 0;
1279 }
718e3744 1280
d62a17ae 1281 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1282 if (new->peer->su_remote == NULL) {
1283 *reason = bgp_path_selection_local_configured;
d62a17ae 1284 return 0;
fdf81fa0
DS
1285 }
1286 if (exist->peer->su_remote == NULL) {
1287 *reason = bgp_path_selection_local_configured;
d62a17ae 1288 return 1;
fdf81fa0 1289 }
9fbdd100 1290
d62a17ae 1291 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1292
1293 if (ret == 1) {
fdf81fa0 1294 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1295 if (debug)
1296 zlog_debug(
1297 "%s: %s loses to %s due to Neighor IP comparison",
1298 pfx_buf, new_buf, exist_buf);
1299 return 0;
1300 }
1301
1302 if (ret == -1) {
fdf81fa0 1303 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1304 if (debug)
1305 zlog_debug(
1306 "%s: %s wins over %s due to Neighor IP comparison",
1307 pfx_buf, new_buf, exist_buf);
1308 return 1;
1309 }
9fbdd100 1310
fdf81fa0 1311 *reason = bgp_path_selection_default;
d62a17ae 1312 if (debug)
1313 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1314 pfx_buf, new_buf, exist_buf);
718e3744 1315
d62a17ae 1316 return 1;
718e3744 1317}
1318
d071f237
AK
1319
1320int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1321 struct bgp_path_info *exist, int *paths_eq)
1322{
1323 enum bgp_path_selection_reason reason;
1324 char pfx_buf[PREFIX2STR_BUFFER];
1325
1326 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1327 AFI_L2VPN, SAFI_EVPN, &reason);
1328}
1329
65efcfce
LB
1330/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1331 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1332 * multipath is enabled
65efcfce 1333 * This version is compatible with */
18ee8310
DS
1334int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1335 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1336 afi_t afi, safi_t safi,
1337 enum bgp_path_selection_reason *reason)
d62a17ae 1338{
1339 int paths_eq;
1340 int ret;
18ee8310 1341 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1342 afi, safi, reason);
d62a17ae 1343
1344 if (paths_eq)
1345 ret = 0;
1346 else {
1347 if (ret == 1)
1348 ret = -1;
1349 else
1350 ret = 1;
1351 }
1352 return ret;
65efcfce
LB
1353}
1354
5a1ae2c2
DS
1355static enum filter_type bgp_input_filter(struct peer *peer,
1356 const struct prefix *p,
d62a17ae 1357 struct attr *attr, afi_t afi,
1358 safi_t safi)
718e3744 1359{
d62a17ae 1360 struct bgp_filter *filter;
6401252f 1361 enum filter_type ret = FILTER_PERMIT;
718e3744 1362
d62a17ae 1363 filter = &peer->filter[afi][safi];
718e3744 1364
d62a17ae 1365#define FILTER_EXIST_WARN(F, f, filter) \
1366 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1367 zlog_debug("%s: Could not find configured input %s-list %s!", \
1368 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1369
1370 if (DISTRIBUTE_IN_NAME(filter)) {
1371 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1372
6401252f
QY
1373 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1374 == FILTER_DENY) {
1375 ret = FILTER_DENY;
1376 goto done;
1377 }
d62a17ae 1378 }
1379
1380 if (PREFIX_LIST_IN_NAME(filter)) {
1381 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1382
6401252f
QY
1383 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1384 == PREFIX_DENY) {
1385 ret = FILTER_DENY;
1386 goto done;
1387 }
d62a17ae 1388 }
1389
1390 if (FILTER_LIST_IN_NAME(filter)) {
1391 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1392
1393 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1394 == AS_FILTER_DENY) {
1395 ret = FILTER_DENY;
1396 goto done;
1397 }
d62a17ae 1398 }
1399
6401252f 1400done:
c7bb4f00 1401 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1402 char pfxprint[PREFIX2STR_BUFFER];
1403
1404 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1405 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1406 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1407 }
1408
1409 return ret;
650f76c2 1410#undef FILTER_EXIST_WARN
718e3744 1411}
1412
b8685f9b
DS
1413static enum filter_type bgp_output_filter(struct peer *peer,
1414 const struct prefix *p,
d62a17ae 1415 struct attr *attr, afi_t afi,
1416 safi_t safi)
718e3744 1417{
d62a17ae 1418 struct bgp_filter *filter;
6401252f 1419 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1420
1421 filter = &peer->filter[afi][safi];
1422
1423#define FILTER_EXIST_WARN(F, f, filter) \
1424 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1425 zlog_debug("%s: Could not find configured output %s-list %s!", \
1426 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1427
d62a17ae 1428 if (DISTRIBUTE_OUT_NAME(filter)) {
1429 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1430
6401252f
QY
1431 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1432 == FILTER_DENY) {
1433 ret = FILTER_DENY;
1434 goto done;
1435 }
d62a17ae 1436 }
1437
1438 if (PREFIX_LIST_OUT_NAME(filter)) {
1439 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1440
d62a17ae 1441 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1442 == PREFIX_DENY) {
1443 ret = FILTER_DENY;
1444 goto done;
1445 }
d62a17ae 1446 }
718e3744 1447
d62a17ae 1448 if (FILTER_LIST_OUT_NAME(filter)) {
1449 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1450
d62a17ae 1451 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1452 == AS_FILTER_DENY) {
1453 ret = FILTER_DENY;
1454 goto done;
1455 }
1456 }
1457
c7bb4f00 1458 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1459 char pfxprint[PREFIX2STR_BUFFER];
1460
1461 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1462 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1463 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1464 }
718e3744 1465
6401252f
QY
1466done:
1467 return ret;
650f76c2 1468#undef FILTER_EXIST_WARN
718e3744 1469}
1470
1471/* If community attribute includes no_export then return 1. */
3dc339cd 1472static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1473{
1474 if (attr->community) {
1475 /* NO_ADVERTISE check. */
1476 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1477 return true;
d62a17ae 1478
1479 /* NO_EXPORT check. */
1480 if (peer->sort == BGP_PEER_EBGP
1481 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1482 return true;
d62a17ae 1483
1484 /* NO_EXPORT_SUBCONFED check. */
1485 if (peer->sort == BGP_PEER_EBGP
1486 || peer->sort == BGP_PEER_CONFED)
1487 if (community_include(attr->community,
1488 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1489 return true;
d62a17ae 1490 }
3dc339cd 1491 return false;
718e3744 1492}
1493
1494/* Route reflection loop check. */
3dc339cd 1495static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1496{
d62a17ae 1497 struct in_addr cluster_id;
779fee93 1498 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1499
779fee93 1500 if (cluster) {
d62a17ae 1501 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1502 cluster_id = peer->bgp->cluster_id;
1503 else
1504 cluster_id = peer->bgp->router_id;
1505
779fee93 1506 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1507 return true;
d62a17ae 1508 }
3dc339cd 1509 return false;
718e3744 1510}
6b0655a2 1511
5a1ae2c2 1512static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1513 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1514 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1515 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1516{
d62a17ae 1517 struct bgp_filter *filter;
82b692c0
LK
1518 struct bgp_path_info rmap_path = { 0 };
1519 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1520 route_map_result_t ret;
1521 struct route_map *rmap = NULL;
718e3744 1522
d62a17ae 1523 filter = &peer->filter[afi][safi];
718e3744 1524
d62a17ae 1525 /* Apply default weight value. */
1526 if (peer->weight[afi][safi])
1527 attr->weight = peer->weight[afi][safi];
718e3744 1528
d62a17ae 1529 if (rmap_name) {
1530 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1531
d62a17ae 1532 if (rmap == NULL)
1533 return RMAP_DENY;
1534 } else {
1535 if (ROUTE_MAP_IN_NAME(filter)) {
1536 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1537
d62a17ae 1538 if (rmap == NULL)
1539 return RMAP_DENY;
1540 }
1541 }
0b16f239 1542
d62a17ae 1543 /* Route map apply. */
1544 if (rmap) {
40381db7 1545 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1546 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1547 rmap_path.peer = peer;
1548 rmap_path.attr = attr;
82b692c0 1549 rmap_path.extra = &extra;
9bcb3eef 1550 rmap_path.net = dest;
196c6b09 1551
82b692c0
LK
1552 extra.num_labels = num_labels;
1553 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1554 memcpy(extra.label, label,
1555 num_labels * sizeof(mpls_label_t));
718e3744 1556
d62a17ae 1557 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1558
d62a17ae 1559 /* Apply BGP route map to the attribute. */
1782514f 1560 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1561
d62a17ae 1562 peer->rmap_type = 0;
0b16f239 1563
1f2263be 1564 if (ret == RMAP_DENYMATCH)
d62a17ae 1565 return RMAP_DENY;
0b16f239 1566 }
d62a17ae 1567 return RMAP_PERMIT;
0b16f239
DS
1568}
1569
5f040085 1570static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1571 struct attr *attr, afi_t afi, safi_t safi,
1572 const char *rmap_name)
0b16f239 1573{
40381db7 1574 struct bgp_path_info rmap_path;
d62a17ae 1575 route_map_result_t ret;
1576 struct route_map *rmap = NULL;
d7c0a89a 1577 uint8_t rmap_type;
0b16f239 1578
b787157a
DS
1579 /*
1580 * So if we get to this point and have no rmap_name
1581 * we want to just show the output as it currently
1582 * exists.
1583 */
1584 if (!rmap_name)
1585 return RMAP_PERMIT;
0b16f239 1586
d62a17ae 1587 /* Apply default weight value. */
1588 if (peer->weight[afi][safi])
1589 attr->weight = peer->weight[afi][safi];
0b16f239 1590
b787157a 1591 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1592
b787157a
DS
1593 /*
1594 * If we have a route map name and we do not find
1595 * the routemap that means we have an implicit
1596 * deny.
1597 */
1598 if (rmap == NULL)
1599 return RMAP_DENY;
0b16f239 1600
40381db7 1601 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1602 /* Route map apply. */
b787157a 1603 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1604 rmap_path.peer = peer;
1605 rmap_path.attr = attr;
0b16f239 1606
0f672529 1607 rmap_type = peer->rmap_type;
b787157a 1608 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1609
b787157a 1610 /* Apply BGP route map to the attribute. */
1782514f 1611 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1612
0f672529 1613 peer->rmap_type = rmap_type;
b787157a
DS
1614
1615 if (ret == RMAP_DENYMATCH)
1616 /*
1617 * caller has multiple error paths with bgp_attr_flush()
1618 */
1619 return RMAP_DENY;
ac41b2a2 1620
d62a17ae 1621 return RMAP_PERMIT;
718e3744 1622}
6b0655a2 1623
5000f21c 1624/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1625static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1626 struct peer *peer, struct attr *attr)
1627{
1628 if (peer->sort == BGP_PEER_EBGP
1629 && (peer_af_flag_check(peer, afi, safi,
1630 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1631 || peer_af_flag_check(peer, afi, safi,
1632 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1633 || peer_af_flag_check(peer, afi, safi,
1634 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1635 || peer_af_flag_check(peer, afi, safi,
1636 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1637 // Take action on the entire aspath
1638 if (peer_af_flag_check(peer, afi, safi,
1639 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1640 || peer_af_flag_check(peer, afi, safi,
1641 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1642 if (peer_af_flag_check(
1643 peer, afi, safi,
1644 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1645 attr->aspath = aspath_replace_private_asns(
bf26b80e 1646 attr->aspath, bgp->as, peer->as);
d62a17ae 1647
1648 // The entire aspath consists of private ASNs so create
1649 // an empty aspath
1650 else if (aspath_private_as_check(attr->aspath))
1651 attr->aspath = aspath_empty_get();
1652
1653 // There are some public and some private ASNs, remove
1654 // the private ASNs
1655 else
1656 attr->aspath = aspath_remove_private_asns(
bf26b80e 1657 attr->aspath, peer->as);
d62a17ae 1658 }
1659
1660 // 'all' was not specified so the entire aspath must be private
1661 // ASNs
1662 // for us to do anything
1663 else if (aspath_private_as_check(attr->aspath)) {
1664 if (peer_af_flag_check(
1665 peer, afi, safi,
1666 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1667 attr->aspath = aspath_replace_private_asns(
bf26b80e 1668 attr->aspath, bgp->as, peer->as);
d62a17ae 1669 else
1670 attr->aspath = aspath_empty_get();
1671 }
1672 }
5000f21c
DS
1673}
1674
c7122e14 1675/* If this is an EBGP peer with as-override */
d62a17ae 1676static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1677 struct peer *peer, struct attr *attr)
1678{
1679 if (peer->sort == BGP_PEER_EBGP
1680 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1681 if (aspath_single_asn_check(attr->aspath, peer->as))
1682 attr->aspath = aspath_replace_specific_asn(
1683 attr->aspath, peer->as, bgp->as);
1684 }
1685}
1686
7f323236
DW
1687void bgp_attr_add_gshut_community(struct attr *attr)
1688{
1689 struct community *old;
1690 struct community *new;
1691 struct community *merge;
1692 struct community *gshut;
1693
1694 old = attr->community;
1695 gshut = community_str2com("graceful-shutdown");
1696
990f4f91 1697 assert(gshut);
1698
7f323236
DW
1699 if (old) {
1700 merge = community_merge(community_dup(old), gshut);
1701
a4d82a8a 1702 if (old->refcnt == 0)
3c1f53de 1703 community_free(&old);
7f323236
DW
1704
1705 new = community_uniq_sort(merge);
3c1f53de 1706 community_free(&merge);
7f323236
DW
1707 } else {
1708 new = community_dup(gshut);
1709 }
1710
3c1f53de 1711 community_free(&gshut);
7f323236
DW
1712 attr->community = new;
1713 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1714
1715 /* When we add the graceful-shutdown community we must also
1716 * lower the local-preference */
1717 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1718 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1719}
1720
1721
e73c112e
MK
1722/* Notify BGP Conditional advertisement scanner process. */
1723void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1724{
1725 struct peer *temp_peer;
1726 struct peer *peer = SUBGRP_PEER(subgrp);
1727 struct listnode *temp_node, *temp_nnode = NULL;
1728 afi_t afi = SUBGRP_AFI(subgrp);
1729 safi_t safi = SUBGRP_SAFI(subgrp);
1730 struct bgp *bgp = SUBGRP_INST(subgrp);
1731 struct bgp_filter *filter = &peer->filter[afi][safi];
1732
1733 if (!ADVERTISE_MAP_NAME(filter))
1734 return;
1735
1736 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1737 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1738 continue;
1739
1740 if (peer != temp_peer)
1741 continue;
1742
1743 temp_peer->advmap_table_change = true;
1744 break;
1745 }
1746}
1747
1748
f2ee6d5c 1749void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1750{
960035b2 1751 if (family == AF_INET) {
975a328e
DA
1752 attr->nexthop.s_addr = INADDR_ANY;
1753 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1754 }
d62a17ae 1755 if (family == AF_INET6)
1756 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1757 if (family == AF_EVPN)
1758 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1759}
1760
9bcb3eef 1761bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1762 struct update_subgroup *subgrp,
7f7940e6
MK
1763 const struct prefix *p, struct attr *attr,
1764 bool skip_rmap_check)
d62a17ae 1765{
1766 struct bgp_filter *filter;
1767 struct peer *from;
1768 struct peer *peer;
1769 struct peer *onlypeer;
1770 struct bgp *bgp;
40381db7 1771 struct attr *piattr;
b68885f9 1772 route_map_result_t ret;
d62a17ae 1773 int transparent;
1774 int reflect;
1775 afi_t afi;
1776 safi_t safi;
1777 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1778 bool nh_reset = false;
1779 uint64_t cum_bw;
d62a17ae 1780
1781 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1782 return false;
d62a17ae 1783
1784 afi = SUBGRP_AFI(subgrp);
1785 safi = SUBGRP_SAFI(subgrp);
1786 peer = SUBGRP_PEER(subgrp);
1787 onlypeer = NULL;
1788 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1789 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1790
40381db7 1791 from = pi->peer;
d62a17ae 1792 filter = &peer->filter[afi][safi];
1793 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1794 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1795 : pi->attr;
3f9c7369 1796
49e5a4a0 1797#ifdef ENABLE_BGP_VNC
d62a17ae 1798 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1799 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1800 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1801
1802 /*
1803 * direct and direct_ext type routes originate internally even
1804 * though they can have peer pointers that reference other
1805 * systems
1806 */
8228a9a7
DS
1807 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1808 __func__, p);
d62a17ae 1809 samepeer_safe = 1;
1810 }
65efcfce
LB
1811#endif
1812
ddb5b488
PZ
1813 if (((afi == AFI_IP) || (afi == AFI_IP6))
1814 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1815 && (pi->type == ZEBRA_ROUTE_BGP)
1816 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1817
1818 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1819
1820 samepeer_safe = 1;
1821 }
1822
d62a17ae 1823 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1824 * pi is valid */
1825 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1826 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1827 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1828 return false;
d62a17ae 1829 }
adbac85e 1830
d62a17ae 1831 /* If this is not the bestpath then check to see if there is an enabled
1832 * addpath
1833 * feature that requires us to advertise it */
40381db7 1834 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1835 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1836 return false;
d62a17ae 1837 }
1838 }
06370dac 1839
d62a17ae 1840 /* Aggregate-address suppress check. */
4056a5f6
RZ
1841 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1842 return false;
3f9c7369 1843
13b7e7f0
DS
1844 /*
1845 * If we are doing VRF 2 VRF leaking via the import
1846 * statement, we want to prevent the route going
1847 * off box as that the RT and RD created are localy
1848 * significant and globaly useless.
1849 */
40381db7
DS
1850 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1851 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1852 return false;
13b7e7f0 1853
d62a17ae 1854 /* If it's labeled safi, make sure the route has a valid label. */
1855 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1856 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1857 if (!bgp_is_valid_label(&label)) {
1858 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1859 zlog_debug("u%" PRIu64 ":s%" PRIu64
1860 " %pFX is filtered - no label (%p)",
d62a17ae 1861 subgrp->update_group->id, subgrp->id,
8228a9a7 1862 p, &label);
3dc339cd 1863 return false;
d62a17ae 1864 }
1865 }
cd1964ff 1866
d62a17ae 1867 /* Do not send back route to sender. */
1868 if (onlypeer && from == onlypeer) {
3dc339cd 1869 return false;
d62a17ae 1870 }
3f9c7369 1871
d62a17ae 1872 /* Do not send the default route in the BGP table if the neighbor is
1873 * configured for default-originate */
1874 if (CHECK_FLAG(peer->af_flags[afi][safi],
1875 PEER_FLAG_DEFAULT_ORIGINATE)) {
1876 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1877 return false;
d62a17ae 1878 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1879 return false;
d62a17ae 1880 }
4125bb67 1881
d62a17ae 1882 /* Transparency check. */
1883 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1884 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1885 transparent = 1;
1886 else
1887 transparent = 0;
1888
1889 /* If community is not disabled check the no-export and local. */
40381db7 1890 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1891 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1892 zlog_debug("%s: community filter check fail for %pFX",
1893 __func__, p);
3dc339cd 1894 return false;
d62a17ae 1895 }
3f9c7369 1896
d62a17ae 1897 /* If the attribute has originator-id and it is same as remote
1898 peer's id. */
40381db7
DS
1899 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1900 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1901 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1902 zlog_debug(
8228a9a7
DS
1903 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1904 onlypeer->host, p);
3dc339cd 1905 return false;
d62a17ae 1906 }
3f9c7369 1907
d62a17ae 1908 /* ORF prefix-list filter check */
1909 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1910 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1911 || CHECK_FLAG(peer->af_cap[afi][safi],
1912 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1913 if (peer->orf_plist[afi][safi]) {
1914 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1915 == PREFIX_DENY) {
1916 if (bgp_debug_update(NULL, p,
1917 subgrp->update_group, 0))
1918 zlog_debug(
8228a9a7
DS
1919 "%s [Update:SEND] %pFX is filtered via ORF",
1920 peer->host, p);
3dc339cd 1921 return false;
d62a17ae 1922 }
1923 }
1924
1925 /* Output filter check. */
40381db7 1926 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1927 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1928 zlog_debug("%s [Update:SEND] %pFX is filtered",
1929 peer->host, p);
3dc339cd 1930 return false;
d62a17ae 1931 }
3f9c7369 1932
d62a17ae 1933 /* AS path loop check. */
2b31007c
RZ
1934 if (onlypeer && onlypeer->as_path_loop_detection
1935 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1936 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1937 zlog_debug(
3efd0893 1938 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1939 onlypeer->host, onlypeer->as);
3dc339cd 1940 return false;
d62a17ae 1941 }
3f9c7369 1942
d62a17ae 1943 /* If we're a CONFED we need to loop check the CONFED ID too */
1944 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1945 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1946 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1947 zlog_debug(
3efd0893 1948 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1949 peer->host, bgp->confed_id);
3dc339cd 1950 return false;
d62a17ae 1951 }
3f9c7369 1952 }
3f9c7369 1953
d62a17ae 1954 /* Route-Reflect check. */
1955 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1956 reflect = 1;
1957 else
1958 reflect = 0;
1959
1960 /* IBGP reflection check. */
1961 if (reflect && !samepeer_safe) {
1962 /* A route from a Client peer. */
1963 if (CHECK_FLAG(from->af_flags[afi][safi],
1964 PEER_FLAG_REFLECTOR_CLIENT)) {
1965 /* Reflect to all the Non-Client peers and also to the
1966 Client peers other than the originator. Originator
1967 check
1968 is already done. So there is noting to do. */
1969 /* no bgp client-to-client reflection check. */
892fedb6
DA
1970 if (CHECK_FLAG(bgp->flags,
1971 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1972 if (CHECK_FLAG(peer->af_flags[afi][safi],
1973 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1974 return false;
d62a17ae 1975 } else {
1976 /* A route from a Non-client peer. Reflect to all other
1977 clients. */
1978 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1979 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1980 return false;
d62a17ae 1981 }
1982 }
3f9c7369 1983
d62a17ae 1984 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1985 *attr = *piattr;
d62a17ae 1986
1987 /* If local-preference is not set. */
1988 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1989 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1990 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1991 attr->local_pref = bgp->default_local_pref;
3f9c7369 1992 }
3f9c7369 1993
d62a17ae 1994 /* If originator-id is not set and the route is to be reflected,
1995 set the originator id */
1996 if (reflect
1997 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1998 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1999 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2000 }
3f9c7369 2001
d62a17ae 2002 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2003 */
2004 if (peer->sort == BGP_PEER_EBGP
2005 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2006 if (from != bgp->peer_self && !transparent
2007 && !CHECK_FLAG(peer->af_flags[afi][safi],
2008 PEER_FLAG_MED_UNCHANGED))
2009 attr->flag &=
2010 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2011 }
3f9c7369 2012
d62a17ae 2013 /* Since the nexthop attribute can vary per peer, it is not explicitly
2014 * set
2015 * in announce check, only certain flags and length (or number of
2016 * nexthops
2017 * -- for IPv6/MP_REACH) are set here in order to guide the update
2018 * formation
2019 * code in setting the nexthop(s) on a per peer basis in
2020 * reformat_peer().
2021 * Typically, the source nexthop in the attribute is preserved but in
2022 * the
2023 * scenarios where we know it will always be overwritten, we reset the
2024 * nexthop to "0" in an attempt to achieve better Update packing. An
2025 * example of this is when a prefix from each of 2 IBGP peers needs to
2026 * be
2027 * announced to an EBGP peer (and they have the same attributes barring
2028 * their nexthop).
2029 */
2030 if (reflect)
2031 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2032
2033#define NEXTHOP_IS_V6 \
2034 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2035 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2036 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2037 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2038
2039 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2040 * if
2041 * the peer (group) is configured to receive link-local nexthop
2042 * unchanged
c728d027
DA
2043 * and it is available in the prefix OR we're not reflecting the route,
2044 * link-local nexthop address is valid and
d62a17ae 2045 * the peer (group) to whom we're going to announce is on a shared
2046 * network
2047 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2048 * By checking if nexthop LL address is valid we are sure that
2049 * we do not announce LL address as `::`.
d62a17ae 2050 */
2051 if (NEXTHOP_IS_V6) {
2052 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2053 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2054 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2055 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2056 || (!reflect
2057 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2058 && peer->shared_network
d62a17ae 2059 && (from == bgp->peer_self
2060 || peer->sort == BGP_PEER_EBGP))) {
2061 attr->mp_nexthop_len =
2062 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2063 }
3f9c7369 2064
d62a17ae 2065 /* Clear off link-local nexthop in source, whenever it is not
2066 * needed to
2067 * ensure more prefixes share the same attribute for
2068 * announcement.
2069 */
2070 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2071 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2072 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2073 }
3f9c7369 2074
d62a17ae 2075 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2076 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2077
2078 /* Route map & unsuppress-map apply. */
7f7940e6 2079 if (!skip_rmap_check
e73c112e 2080 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2081 struct bgp_path_info rmap_path = {0};
2082 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2083 struct attr dummy_attr = {0};
d62a17ae 2084
e34291b8 2085 /* Fill temp path_info */
9bcb3eef
DS
2086 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2087 pi, peer, attr);
16f7ce2b 2088
d62a17ae 2089 /* don't confuse inbound and outbound setting */
2090 RESET_FLAG(attr->rmap_change_flags);
2091
2092 /*
2093 * The route reflector is not allowed to modify the attributes
2094 * of the reflected IBGP routes unless explicitly allowed.
2095 */
2096 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2097 && !CHECK_FLAG(bgp->flags,
2098 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2099 dummy_attr = *attr;
40381db7 2100 rmap_path.attr = &dummy_attr;
d62a17ae 2101 }
3f9c7369 2102
d62a17ae 2103 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2104
4056a5f6 2105 if (bgp_path_suppressed(pi))
d62a17ae 2106 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2107 &rmap_path);
d62a17ae 2108 else
2109 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2110 &rmap_path);
d62a17ae 2111
2112 peer->rmap_type = 0;
2113
2114 if (ret == RMAP_DENYMATCH) {
778048bf 2115 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2116 zlog_debug(
2117 "%s [Update:SEND] %pFX is filtered by route-map",
2118 peer->host, p);
778048bf 2119
d62a17ae 2120 bgp_attr_flush(attr);
3dc339cd 2121 return false;
d62a17ae 2122 }
3f9c7369 2123 }
3f9c7369 2124
9dac9fc8
DA
2125 /* RFC 8212 to prevent route leaks.
2126 * This specification intends to improve this situation by requiring the
2127 * explicit configuration of both BGP Import and Export Policies for any
2128 * External BGP (EBGP) session such as customers, peers, or
2129 * confederation boundaries for all enabled address families. Through
2130 * codification of the aforementioned requirement, operators will
2131 * benefit from consistent behavior across different BGP
2132 * implementations.
2133 */
1d3fdccf 2134 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2135 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2136 return false;
9dac9fc8 2137
fb29348a
DA
2138 /* draft-ietf-idr-deprecate-as-set-confed-set
2139 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2140 * Eventually, This document (if approved) updates RFC 4271
2141 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2142 * and obsoletes RFC 6472.
2143 */
7f972cd8 2144 if (peer->bgp->reject_as_sets)
fb29348a 2145 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2146 return false;
fb29348a 2147
33d022bc
DA
2148 /* Codification of AS 0 Processing */
2149 if (aspath_check_as_zero(attr->aspath))
e2369003 2150 return false;
33d022bc 2151
637e5ba4 2152 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2153 if (peer->sort == BGP_PEER_IBGP
2154 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2155 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2156 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2157 } else {
2158 bgp_attr_add_gshut_community(attr);
2159 }
2160 }
2161
d62a17ae 2162 /* After route-map has been applied, we check to see if the nexthop to
2163 * be carried in the attribute (that is used for the announcement) can
2164 * be cleared off or not. We do this in all cases where we would be
2165 * setting the nexthop to "ourselves". For IPv6, we only need to
2166 * consider
2167 * the global nexthop here; the link-local nexthop would have been
2168 * cleared
2169 * already, and if not, it is required by the update formation code.
2170 * Also see earlier comments in this function.
2171 */
2172 /*
2173 * If route-map has performed some operation on the nexthop or the peer
2174 * configuration says to pass it unchanged, we cannot reset the nexthop
2175 * here, so only attempt to do it if these aren't true. Note that the
2176 * route-map handler itself might have cleared the nexthop, if for
2177 * example,
2178 * it is configured as 'peer-address'.
2179 */
2180 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2181 piattr->rmap_change_flags)
d62a17ae 2182 && !transparent
2183 && !CHECK_FLAG(peer->af_flags[afi][safi],
2184 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2185 /* We can reset the nexthop, if setting (or forcing) it to
2186 * 'self' */
2187 if (CHECK_FLAG(peer->af_flags[afi][safi],
2188 PEER_FLAG_NEXTHOP_SELF)
2189 || CHECK_FLAG(peer->af_flags[afi][safi],
2190 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2191 if (!reflect
2192 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2193 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2194 subgroup_announce_reset_nhop(
2195 (peer_cap_enhe(peer, afi, safi)
2196 ? AF_INET6
2197 : p->family),
2198 attr);
7b651a32 2199 nh_reset = true;
2200 }
d62a17ae 2201 } else if (peer->sort == BGP_PEER_EBGP) {
2202 /* Can also reset the nexthop if announcing to EBGP, but
2203 * only if
2204 * no peer in the subgroup is on a shared subnet.
2205 * Note: 3rd party nexthop currently implemented for
2206 * IPv4 only.
2207 */
737af885
BS
2208 if ((p->family == AF_INET) &&
2209 (!bgp_subgrp_multiaccess_check_v4(
2210 piattr->nexthop,
7b651a32 2211 subgrp, from))) {
d62a17ae 2212 subgroup_announce_reset_nhop(
2213 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2214 ? AF_INET6
2215 : p->family),
737af885 2216 attr);
7b651a32 2217 nh_reset = true;
2218 }
737af885
BS
2219
2220 if ((p->family == AF_INET6) &&
2221 (!bgp_subgrp_multiaccess_check_v6(
2222 piattr->mp_nexthop_global,
7b651a32 2223 subgrp, from))) {
737af885
BS
2224 subgroup_announce_reset_nhop(
2225 (peer_cap_enhe(peer, afi, safi)
2226 ? AF_INET6
2227 : p->family),
2228 attr);
7b651a32 2229 nh_reset = true;
2230 }
737af885
BS
2231
2232
2233
40381db7 2234 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2235 /*
2236 * This flag is used for leaked vpn-vrf routes
2237 */
2238 int family = p->family;
2239
2240 if (peer_cap_enhe(peer, afi, safi))
2241 family = AF_INET6;
2242
2243 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2244 zlog_debug(
1defdda8 2245 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2246 __func__, family2str(family));
2247 subgroup_announce_reset_nhop(family, attr);
7b651a32 2248 nh_reset = true;
d62a17ae 2249 }
63696f1d 2250 }
960035b2 2251
63696f1d 2252 /* If IPv6/MP and nexthop does not have any override and happens
2253 * to
2254 * be a link-local address, reset it so that we don't pass along
2255 * the
2256 * source's link-local IPv6 address to recipients who may not be
2257 * on
2258 * the same interface.
2259 */
2260 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2261 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2262 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2263 nh_reset = true;
2264 }
d62a17ae 2265 }
3f9c7369 2266
7b651a32 2267 /*
2268 * When the next hop is set to ourselves, if all multipaths have
2269 * link-bandwidth announce the cumulative bandwidth as that makes
2270 * the most sense. However, don't modify if the link-bandwidth has
2271 * been explicitly set by user policy.
2272 */
2273 if (nh_reset &&
f7e1c681 2274 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2275 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2276 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2277 attr->ecommunity = ecommunity_replace_linkbw(
2278 bgp->as, attr->ecommunity, cum_bw);
2279
3dc339cd 2280 return true;
3f9c7369
DS
2281}
2282
f009ff26 2283static int bgp_route_select_timer_expire(struct thread *thread)
2284{
2285 struct afi_safi_info *info;
2286 afi_t afi;
2287 safi_t safi;
2288 struct bgp *bgp;
2289
2290 info = THREAD_ARG(thread);
2291 afi = info->afi;
2292 safi = info->safi;
2293 bgp = info->bgp;
2294
2295 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2296 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2297 safi);
f009ff26 2298
2299 bgp->gr_info[afi][safi].t_route_select = NULL;
2300
2301 XFREE(MTYPE_TMP, info);
2302
2303 /* Best path selection */
2304 return bgp_best_path_select_defer(bgp, afi, safi);
2305}
2306
9bcb3eef 2307void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2308 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2309 struct bgp_path_info_pair *result, afi_t afi,
2310 safi_t safi)
2311{
2312 struct bgp_path_info *new_select;
2313 struct bgp_path_info *old_select;
40381db7
DS
2314 struct bgp_path_info *pi;
2315 struct bgp_path_info *pi1;
2316 struct bgp_path_info *pi2;
2317 struct bgp_path_info *nextpi = NULL;
d62a17ae 2318 int paths_eq, do_mpath, debug;
2319 struct list mp_list;
2320 char pfx_buf[PREFIX2STR_BUFFER];
2321 char path_buf[PATH_ADDPATH_STR_BUFFER];
2322
2323 bgp_mp_list_init(&mp_list);
2324 do_mpath =
2325 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2326
9bcb3eef 2327 debug = bgp_debug_bestpath(dest);
d62a17ae 2328
2329 if (debug)
9bcb3eef 2330 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2331
9bcb3eef 2332 dest->reason = bgp_path_selection_none;
d62a17ae 2333 /* bgp deterministic-med */
2334 new_select = NULL;
892fedb6 2335 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2336
1defdda8 2337 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2338 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2339 pi1 = pi1->next)
9bcb3eef 2340 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2341 BGP_PATH_DMED_SELECTED);
d62a17ae 2342
9bcb3eef 2343 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2344 pi1 = pi1->next) {
40381db7 2345 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2346 continue;
40381db7 2347 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2348 continue;
ea8b2282 2349 if (pi1->peer != bgp->peer_self)
40381db7 2350 if (pi1->peer->status != Established)
d62a17ae 2351 continue;
2352
40381db7
DS
2353 new_select = pi1;
2354 if (pi1->next) {
2355 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2356 if (CHECK_FLAG(pi2->flags,
1defdda8 2357 BGP_PATH_DMED_CHECK))
d62a17ae 2358 continue;
40381db7 2359 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2360 continue;
ea8b2282 2361 if (pi2->peer != bgp->peer_self
d62a17ae 2362 && !CHECK_FLAG(
ea8b2282
DS
2363 pi2->peer->sflags,
2364 PEER_STATUS_NSF_WAIT))
40381db7 2365 if (pi2->peer->status
d62a17ae 2366 != Established)
2367 continue;
2368
121e245d
DS
2369 if (!aspath_cmp_left(pi1->attr->aspath,
2370 pi2->attr->aspath)
2371 && !aspath_cmp_left_confed(
40381db7 2372 pi1->attr->aspath,
121e245d
DS
2373 pi2->attr->aspath))
2374 continue;
d62a17ae 2375
121e245d
DS
2376 if (bgp_path_info_cmp(
2377 bgp, pi2, new_select,
2378 &paths_eq, mpath_cfg, debug,
fdf81fa0 2379 pfx_buf, afi, safi,
9bcb3eef 2380 &dest->reason)) {
121e245d 2381 bgp_path_info_unset_flag(
9bcb3eef 2382 dest, new_select,
121e245d
DS
2383 BGP_PATH_DMED_SELECTED);
2384 new_select = pi2;
d62a17ae 2385 }
121e245d
DS
2386
2387 bgp_path_info_set_flag(
9bcb3eef 2388 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2389 }
2390 }
9bcb3eef 2391 bgp_path_info_set_flag(dest, new_select,
18ee8310 2392 BGP_PATH_DMED_CHECK);
9bcb3eef 2393 bgp_path_info_set_flag(dest, new_select,
18ee8310 2394 BGP_PATH_DMED_SELECTED);
d62a17ae 2395
2396 if (debug) {
18ee8310 2397 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2398 new_select, path_buf, sizeof(path_buf));
8228a9a7
DS
2399 zlog_debug(
2400 "%pBD: %s is the bestpath from AS %u",
2401 dest, path_buf,
2402 aspath_get_first_as(
2403 new_select->attr->aspath));
d62a17ae 2404 }
2405 }
2406 }
96450faf 2407
d62a17ae 2408 /* Check old selected route and new selected route. */
2409 old_select = NULL;
2410 new_select = NULL;
9bcb3eef 2411 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2412 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2413 enum bgp_path_selection_reason reason;
2414
40381db7
DS
2415 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2416 old_select = pi;
d62a17ae 2417
40381db7 2418 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2419 /* reap REMOVED routes, if needs be
2420 * selected route must stay for a while longer though
2421 */
40381db7
DS
2422 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2423 && (pi != old_select))
9bcb3eef 2424 bgp_path_info_reap(dest, pi);
d62a17ae 2425
ddb5b488 2426 if (debug)
40381db7
DS
2427 zlog_debug("%s: pi %p in holddown", __func__,
2428 pi);
ddb5b488 2429
d62a17ae 2430 continue;
2431 }
96450faf 2432
40381db7
DS
2433 if (pi->peer && pi->peer != bgp->peer_self
2434 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2435 if (pi->peer->status != Established) {
ddb5b488
PZ
2436
2437 if (debug)
2438 zlog_debug(
40381db7
DS
2439 "%s: pi %p non self peer %s not estab state",
2440 __func__, pi, pi->peer->host);
ddb5b488 2441
d62a17ae 2442 continue;
ddb5b488 2443 }
9fbdd100 2444
892fedb6 2445 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2446 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2447 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2448 if (debug)
40381db7 2449 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2450 continue;
2451 }
9fbdd100 2452
9bcb3eef 2453 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2454
9bcb3eef 2455 reason = dest->reason;
40381db7 2456 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2457 debug, pfx_buf, afi, safi,
2458 &dest->reason)) {
19ea4cec
DS
2459 if (new_select == NULL &&
2460 reason != bgp_path_selection_none)
9bcb3eef 2461 dest->reason = reason;
40381db7 2462 new_select = pi;
d62a17ae 2463 }
2464 }
718e3744 2465
d62a17ae 2466 /* Now that we know which path is the bestpath see if any of the other
2467 * paths
2468 * qualify as multipaths
2469 */
2470 if (debug) {
2471 if (new_select)
7533cad7
QY
2472 bgp_path_info_path_with_addpath_rx_str(
2473 new_select, path_buf, sizeof(path_buf));
d62a17ae 2474 else
772270f3 2475 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2476 zlog_debug(
8228a9a7
DS
2477 "%pBD: After path selection, newbest is %s oldbest was %s",
2478 dest, path_buf,
d62a17ae 2479 old_select ? old_select->peer->host : "NONE");
96450faf 2480 }
9fbdd100 2481
d62a17ae 2482 if (do_mpath && new_select) {
9bcb3eef 2483 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2484 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2485
2486 if (debug)
18ee8310 2487 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2488 pi, path_buf, sizeof(path_buf));
d62a17ae 2489
40381db7 2490 if (pi == new_select) {
d62a17ae 2491 if (debug)
2492 zlog_debug(
8228a9a7
DS
2493 "%pBD: %s is the bestpath, add to the multipath list",
2494 dest, path_buf);
40381db7 2495 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2496 continue;
2497 }
2498
40381db7 2499 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2500 continue;
2501
40381db7
DS
2502 if (pi->peer && pi->peer != bgp->peer_self
2503 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2504 PEER_STATUS_NSF_WAIT))
40381db7 2505 if (pi->peer->status != Established)
d62a17ae 2506 continue;
2507
40381db7 2508 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2509 if (debug)
2510 zlog_debug(
8228a9a7
DS
2511 "%pBD: %s has the same nexthop as the bestpath, skip it",
2512 dest, path_buf);
d62a17ae 2513 continue;
2514 }
2515
40381db7 2516 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2517 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2518 &dest->reason);
d62a17ae 2519
2520 if (paths_eq) {
2521 if (debug)
2522 zlog_debug(
8228a9a7
DS
2523 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2524 dest, path_buf);
40381db7 2525 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2526 }
2527 }
2528 }
fee0f4c6 2529
9bcb3eef 2530 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2531 mpath_cfg);
2532 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2533 bgp_mp_list_clear(&mp_list);
96450faf 2534
9bcb3eef 2535 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2536
d62a17ae 2537 result->old = old_select;
2538 result->new = new_select;
96450faf 2539
d62a17ae 2540 return;
fee0f4c6 2541}
2542
3f9c7369
DS
2543/*
2544 * A new route/change in bestpath of an existing route. Evaluate the path
2545 * for advertisement to the subgroup.
2546 */
3dc339cd
DA
2547void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2548 struct bgp_path_info *selected,
9bcb3eef 2549 struct bgp_dest *dest,
3dc339cd 2550 uint32_t addpath_tx_id)
d62a17ae 2551{
b54892e0 2552 const struct prefix *p;
d62a17ae 2553 struct peer *onlypeer;
2554 struct attr attr;
2555 afi_t afi;
2556 safi_t safi;
a77e2f4b
S
2557 struct bgp *bgp;
2558 bool advertise;
adbac85e 2559
9bcb3eef 2560 p = bgp_dest_get_prefix(dest);
d62a17ae 2561 afi = SUBGRP_AFI(subgrp);
2562 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2563 bgp = SUBGRP_INST(subgrp);
d62a17ae 2564 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2565 : NULL);
2566
2dbe669b
DA
2567 if (BGP_DEBUG(update, UPDATE_OUT))
2568 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2569
d62a17ae 2570 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2571 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2572 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2573 return;
d62a17ae 2574
2575 memset(&attr, 0, sizeof(struct attr));
2576 /* It's initialized in bgp_announce_check() */
2577
a77e2f4b
S
2578 /* Announcement to the subgroup. If the route is filtered withdraw it.
2579 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2580 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2581 * route
d62a17ae 2582 */
a77e2f4b
S
2583 advertise = bgp_check_advertise(bgp, dest);
2584
d62a17ae 2585 if (selected) {
7f7940e6 2586 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2587 false)) {
2588 /* Route is selected, if the route is already installed
2589 * in FIB, then it is advertised
2590 */
2591 if (advertise)
2592 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2593 selected);
2594 } else
9bcb3eef 2595 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2596 addpath_tx_id);
d62a17ae 2597 }
2598
2599 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2600 else {
9bcb3eef 2601 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2602 }
200df115 2603}
fee0f4c6 2604
3064bf43 2605/*
e1072051 2606 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2607 * This is called at the end of route processing.
3064bf43 2608 */
9bcb3eef 2609void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2610{
40381db7 2611 struct bgp_path_info *pi;
3064bf43 2612
9bcb3eef 2613 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2614 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2615 continue;
40381db7
DS
2616 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2617 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2618 }
3064bf43 2619}
2620
2621/*
2622 * Has the route changed from the RIB's perspective? This is invoked only
2623 * if the route selection returns the same best route as earlier - to
2624 * determine if we need to update zebra or not.
2625 */
9bcb3eef 2626bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2627{
4b7e6066 2628 struct bgp_path_info *mpinfo;
d62a17ae 2629
2bb9eff4
DS
2630 /* If this is multipath, check all selected paths for any nexthop
2631 * change or attribute change. Some attribute changes (e.g., community)
2632 * aren't of relevance to the RIB, but we'll update zebra to ensure
2633 * we handle the case of BGP nexthop change. This is the behavior
2634 * when the best path has an attribute change anyway.
d62a17ae 2635 */
1defdda8 2636 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2637 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2638 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2639 return true;
d62a17ae 2640
2bb9eff4
DS
2641 /*
2642 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2643 */
18ee8310
DS
2644 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2645 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2646 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2647 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2648 return true;
d62a17ae 2649 }
3064bf43 2650
d62a17ae 2651 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2652 return false;
3064bf43 2653}
2654
d62a17ae 2655struct bgp_process_queue {
2656 struct bgp *bgp;
9bcb3eef 2657 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2658#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2659 unsigned int flags;
2660 unsigned int queued;
200df115 2661};
2662
3b0c17e1 2663static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2664 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2665 struct bgp_path_info *new_select,
2666 struct bgp_path_info *old_select)
2667{
9bcb3eef 2668 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2669
2670 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2671 return;
2672
2673 if (advertise_type5_routes(bgp, afi) && new_select
2674 && is_route_injectable_into_evpn(new_select)) {
2675
2676 /* apply the route-map */
2677 if (bgp->adv_cmd_rmap[afi][safi].map) {
2678 route_map_result_t ret;
2679 struct bgp_path_info rmap_path;
2680 struct bgp_path_info_extra rmap_path_extra;
2681 struct attr dummy_attr;
2682
2683 dummy_attr = *new_select->attr;
2684
2685 /* Fill temp path_info */
9bcb3eef 2686 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2687 new_select, new_select->peer,
2688 &dummy_attr);
2689
2690 RESET_FLAG(dummy_attr.rmap_change_flags);
2691
2692 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2693 p, &rmap_path);
3b0c17e1 2694
2695 if (ret == RMAP_DENYMATCH) {
2696 bgp_attr_flush(&dummy_attr);
2697 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2698 safi);
2699 } else
2700 bgp_evpn_advertise_type5_route(
2701 bgp, p, &dummy_attr, afi, safi);
2702 } else {
2703 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2704 afi, safi);
2705 }
2706 } else if (advertise_type5_routes(bgp, afi) && old_select
2707 && is_route_injectable_into_evpn(old_select))
2708 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2709}
2710
3103e8d2
DS
2711/*
2712 * old_select = The old best path
2713 * new_select = the new best path
2714 *
2715 * if (!old_select && new_select)
2716 * We are sending new information on.
2717 *
2718 * if (old_select && new_select) {
2719 * if (new_select != old_select)
2720 * We have a new best path send a change
2721 * else
2722 * We've received a update with new attributes that needs
2723 * to be passed on.
2724 * }
2725 *
2726 * if (old_select && !new_select)
2727 * We have no eligible route that we can announce or the rn
2728 * is being removed.
2729 */
9bcb3eef 2730static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2731 afi_t afi, safi_t safi)
d62a17ae 2732{
4b7e6066
DS
2733 struct bgp_path_info *new_select;
2734 struct bgp_path_info *old_select;
2735 struct bgp_path_info_pair old_and_new;
ddb5b488 2736 int debug = 0;
d62a17ae 2737
892fedb6 2738 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2739 if (dest)
2740 debug = bgp_debug_bestpath(dest);
b54892e0 2741 if (debug)
f4c713ae 2742 zlog_debug(
56ca3b5b 2743 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2744 __func__, dest);
f4c713ae
LB
2745 return;
2746 }
d62a17ae 2747 /* Is it end of initial update? (after startup) */
9bcb3eef 2748 if (!dest) {
d62a17ae 2749 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2750 sizeof(bgp->update_delay_zebra_resume_time));
2751
2752 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2753 FOREACH_AFI_SAFI (afi, safi) {
2754 if (bgp_fibupd_safi(safi))
2755 bgp_zebra_announce_table(bgp, afi, safi);
2756 }
d62a17ae 2757 bgp->main_peers_update_hold = 0;
2758
2759 bgp_start_routeadv(bgp);
aac24838 2760 return;
d62a17ae 2761 }
cb1faec9 2762
9bcb3eef 2763 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2764
9bcb3eef 2765 debug = bgp_debug_bestpath(dest);
b54892e0 2766 if (debug)
56ca3b5b 2767 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2768 afi2str(afi), safi2str(safi));
ddb5b488 2769
f009ff26 2770 /* The best path calculation for the route is deferred if
2771 * BGP_NODE_SELECT_DEFER is set
2772 */
9bcb3eef 2773 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2774 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2775 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2776 return;
2777 }
2778
d62a17ae 2779 /* Best path selection. */
9bcb3eef 2780 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2781 afi, safi);
2782 old_select = old_and_new.old;
2783 new_select = old_and_new.new;
2784
2785 /* Do we need to allocate or free labels?
2786 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2787 * necessary to do this upon changes to best path. Exceptions:
2788 * - label index has changed -> recalculate resulting label
2789 * - path_info sub_type changed -> switch to/from implicit-null
2790 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2791 */
318cac96 2792 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2793 if (new_select) {
2794 if (!old_select
2795 || bgp_label_index_differs(new_select, old_select)
57592a53 2796 || new_select->sub_type != old_select->sub_type
9bcb3eef 2797 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2798 /* Enforced penultimate hop popping:
2799 * implicit-null for local routes, aggregate
2800 * and redistributed routes
2801 */
d62a17ae 2802 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2803 || new_select->sub_type
2804 == BGP_ROUTE_AGGREGATE
2805 || new_select->sub_type
2806 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2807 if (CHECK_FLAG(
9bcb3eef 2808 dest->flags,
992dd67e
PR
2809 BGP_NODE_REGISTERED_FOR_LABEL)
2810 || CHECK_FLAG(
2811 dest->flags,
2812 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2813 bgp_unregister_for_label(dest);
70e98a7f 2814 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2815 &dest->local_label);
2816 bgp_set_valid_label(&dest->local_label);
d62a17ae 2817 } else
9bcb3eef
DS
2818 bgp_register_for_label(dest,
2819 new_select);
d62a17ae 2820 }
9bcb3eef 2821 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2822 BGP_NODE_REGISTERED_FOR_LABEL)
2823 || CHECK_FLAG(dest->flags,
2824 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2825 bgp_unregister_for_label(dest);
318cac96 2826 }
992dd67e
PR
2827 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2828 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2829 bgp_unregister_for_label(dest);
d62a17ae 2830 }
cd1964ff 2831
b54892e0 2832 if (debug)
ddb5b488 2833 zlog_debug(
56ca3b5b 2834 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2835 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2836 old_select, new_select);
ddb5b488 2837
d62a17ae 2838 /* If best route remains the same and this is not due to user-initiated
2839 * clear, see exactly what needs to be done.
2840 */
d62a17ae 2841 if (old_select && old_select == new_select
9bcb3eef 2842 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2843 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2844 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2845 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2846#ifdef ENABLE_BGP_VNC
d62a17ae 2847 vnc_import_bgp_add_route(bgp, p, old_select);
2848 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2849#endif
bb744275 2850 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2851 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2852
2853 if (new_select->type == ZEBRA_ROUTE_BGP
2854 && (new_select->sub_type == BGP_ROUTE_NORMAL
2855 || new_select->sub_type
2856 == BGP_ROUTE_IMPORTED))
2857
9bcb3eef 2858 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2859 bgp, afi, safi);
2860 }
d62a17ae 2861 }
d62a17ae 2862
2863 /* If there is a change of interest to peers, reannounce the
2864 * route. */
1defdda8 2865 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2866 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2867 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2868 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2869
2870 /* unicast routes must also be annouced to
2871 * labeled-unicast update-groups */
2872 if (safi == SAFI_UNICAST)
2873 group_announce_route(bgp, afi,
9bcb3eef 2874 SAFI_LABELED_UNICAST, dest,
d62a17ae 2875 new_select);
2876
1defdda8 2877 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2878 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2879 }
fee0f4c6 2880
3b0c17e1 2881 /* advertise/withdraw type-5 routes */
2882 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2883 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2884 bgp_process_evpn_route_injection(
9bcb3eef 2885 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2886
b1875e65 2887 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2888 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2889 bgp_zebra_clear_route_change_flags(dest);
2890 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2891 return;
d62a17ae 2892 }
8ad7271d 2893
d62a17ae 2894 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2895 */
9bcb3eef 2896 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2897
2898 /* bestpath has changed; bump version */
2899 if (old_select || new_select) {
9bcb3eef 2900 bgp_bump_version(dest);
d62a17ae 2901
2902 if (!bgp->t_rmap_def_originate_eval) {
2903 bgp_lock(bgp);
2904 thread_add_timer(
2905 bm->master,
2906 update_group_refresh_default_originate_route_map,
2907 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2908 &bgp->t_rmap_def_originate_eval);
2909 }
2910 }
3f9c7369 2911
d62a17ae 2912 if (old_select)
9bcb3eef 2913 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2914 if (new_select) {
ddb5b488
PZ
2915 if (debug)
2916 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2917 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2918 bgp_path_info_unset_flag(dest, new_select,
2919 BGP_PATH_ATTR_CHANGED);
1defdda8 2920 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2921 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2922 }
338b3424 2923
49e5a4a0 2924#ifdef ENABLE_BGP_VNC
d62a17ae 2925 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2926 if (old_select != new_select) {
2927 if (old_select) {
2928 vnc_import_bgp_exterior_del_route(bgp, p,
2929 old_select);
2930 vnc_import_bgp_del_route(bgp, p, old_select);
2931 }
2932 if (new_select) {
2933 vnc_import_bgp_exterior_add_route(bgp, p,
2934 new_select);
2935 vnc_import_bgp_add_route(bgp, p, new_select);
2936 }
2937 }
2938 }
65efcfce
LB
2939#endif
2940
9bcb3eef 2941 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2942
2943 /* unicast routes must also be annouced to labeled-unicast update-groups
2944 */
2945 if (safi == SAFI_UNICAST)
9bcb3eef 2946 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2947 new_select);
2948
2949 /* FIB update. */
2950 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2951 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2952 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2953 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2954 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2955 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2956
2957 /* if this is an evpn imported type-5 prefix,
2958 * we need to withdraw the route first to clear
2959 * the nh neigh and the RMAC entry.
2960 */
2961 if (old_select &&
2962 is_route_parent_evpn(old_select))
2963 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2964
9bcb3eef 2965 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2966 } else {
d62a17ae 2967 /* Withdraw the route from the kernel. */
2968 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2969 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2970 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2971 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2972
568e10ca 2973 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2974 }
718e3744 2975 }
3064bf43 2976
9bcb3eef 2977 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2978 old_select);
5424b7ba 2979
d62a17ae 2980 /* Clear any route change flags. */
9bcb3eef 2981 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2982
18ee8310 2983 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2984 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2985 bgp_path_info_reap(dest, old_select);
d62a17ae 2986
9bcb3eef 2987 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2988 return;
718e3744 2989}
2990
f009ff26 2991/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2992int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2993{
9bcb3eef 2994 struct bgp_dest *dest;
f009ff26 2995 int cnt = 0;
2996 struct afi_safi_info *thread_info;
f009ff26 2997
56c226e7
DS
2998 if (bgp->gr_info[afi][safi].t_route_select) {
2999 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3000
3001 thread_info = THREAD_ARG(t);
3002 XFREE(MTYPE_TMP, thread_info);
f009ff26 3003 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3004 }
f009ff26 3005
3006 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3007 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3008 get_afi_safi_str(afi, safi, false),
26742171 3009 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3010 }
3011
3012 /* Process the route list */
6338d242
DS
3013 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3014 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3015 dest = bgp_route_next(dest)) {
3016 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3017 continue;
3018
3019 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3020 bgp->gr_info[afi][safi].gr_deferred--;
3021 bgp_process_main_one(bgp, dest, afi, safi);
3022 cnt++;
3023 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3024 bgp_dest_unlock_node(dest);
3025 break;
f009ff26 3026 }
f009ff26 3027 }
3028
9e3b51a7 3029 /* Send EOR message when all routes are processed */
6338d242 3030 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3031 bgp_send_delayed_eor(bgp);
8c48b3b6 3032 /* Send route processing complete message to RIB */
3033 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3034 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3035 return 0;
9e3b51a7 3036 }
f009ff26 3037
3038 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3039
3040 thread_info->afi = afi;
3041 thread_info->safi = safi;
3042 thread_info->bgp = bgp;
3043
3044 /* If there are more routes to be processed, start the
3045 * selection timer
3046 */
3047 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3048 BGP_ROUTE_SELECT_DELAY,
3049 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3050 return 0;
3051}
3052
aac24838 3053static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3054{
aac24838
JB
3055 struct bgp_process_queue *pqnode = data;
3056 struct bgp *bgp = pqnode->bgp;
d62a17ae 3057 struct bgp_table *table;
9bcb3eef 3058 struct bgp_dest *dest;
aac24838
JB
3059
3060 /* eoiu marker */
3061 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3062 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3063 /* should always have dedicated wq call */
3064 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3065 return WQ_SUCCESS;
3066 }
3067
ac021f40 3068 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3069 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3070 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3071 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3072 table = bgp_dest_table(dest);
3073 /* note, new DESTs may be added as part of processing */
3074 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3075
9bcb3eef 3076 bgp_dest_unlock_node(dest);
d62a17ae 3077 bgp_table_unlock(table);
3078 }
aac24838
JB
3079
3080 return WQ_SUCCESS;
3081}
3082
3083static void bgp_processq_del(struct work_queue *wq, void *data)
3084{
3085 struct bgp_process_queue *pqnode = data;
3086
3087 bgp_unlock(pqnode->bgp);
3088
3089 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3090}
3091
b6c386bb 3092void bgp_process_queue_init(struct bgp *bgp)
200df115 3093{
b6c386bb
DS
3094 if (!bgp->process_queue) {
3095 char name[BUFSIZ];
3096
3097 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3098 bgp->process_queue = work_queue_new(bm->master, name);
3099 }
3100
3101 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3102 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3103 bgp->process_queue->spec.max_retries = 0;
3104 bgp->process_queue->spec.hold = 50;
d62a17ae 3105 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3106 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3107}
3108
cfe8d15a 3109static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3110{
3111 struct bgp_process_queue *pqnode;
3112
a4d82a8a
PZ
3113 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3114 sizeof(struct bgp_process_queue));
aac24838
JB
3115
3116 /* unlocked in bgp_processq_del */
3117 pqnode->bgp = bgp_lock(bgp);
3118 STAILQ_INIT(&pqnode->pqueue);
3119
aac24838
JB
3120 return pqnode;
3121}
3122
9bcb3eef 3123void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3124{
aac24838 3125#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3126 struct work_queue *wq = bgp->process_queue;
d62a17ae 3127 struct bgp_process_queue *pqnode;
cfe8d15a 3128 int pqnode_reuse = 0;
495f0b13 3129
d62a17ae 3130 /* already scheduled for processing? */
9bcb3eef 3131 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3132 return;
2e02b9b2 3133
f009ff26 3134 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3135 * the workqueue
3136 */
9bcb3eef 3137 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3138 if (BGP_DEBUG(update, UPDATE_OUT))
3139 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3140 dest);
f009ff26 3141 return;
3142 }
3143
aac24838 3144 if (wq == NULL)
d62a17ae 3145 return;
3146
aac24838 3147 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3148 limit only if is from the same BGP view and it's not an EOIU marker
3149 */
aac24838
JB
3150 if (work_queue_item_count(wq)) {
3151 struct work_queue_item *item = work_queue_last_item(wq);
3152 pqnode = item->data;
228da428 3153
a4d82a8a
PZ
3154 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3155 || pqnode->bgp != bgp
3156 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3157 pqnode = bgp_processq_alloc(bgp);
3158 else
3159 pqnode_reuse = 1;
aac24838 3160 } else
cfe8d15a 3161 pqnode = bgp_processq_alloc(bgp);
aac24838 3162 /* all unlocked in bgp_process_wq */
9bcb3eef 3163 bgp_table_lock(bgp_dest_table(dest));
aac24838 3164
9bcb3eef
DS
3165 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3166 bgp_dest_lock_node(dest);
aac24838 3167
60466a63 3168 /* can't be enqueued twice */
9bcb3eef
DS
3169 assert(STAILQ_NEXT(dest, pq) == NULL);
3170 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3171 pqnode->queued++;
3172
cfe8d15a
LB
3173 if (!pqnode_reuse)
3174 work_queue_add(wq, pqnode);
3175
d62a17ae 3176 return;
fee0f4c6 3177}
0a486e5f 3178
d62a17ae 3179void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3180{
d62a17ae 3181 struct bgp_process_queue *pqnode;
cb1faec9 3182
b6c386bb 3183 if (bgp->process_queue == NULL)
d62a17ae 3184 return;
2e02b9b2 3185
cfe8d15a 3186 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3187
aac24838 3188 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3189 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3190}
3191
d62a17ae 3192static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3193{
d62a17ae 3194 struct peer *peer;
0a486e5f 3195
d62a17ae 3196 peer = THREAD_ARG(thread);
3197 peer->t_pmax_restart = NULL;
0a486e5f 3198
d62a17ae 3199 if (bgp_debug_neighbor_events(peer))
3200 zlog_debug(
3201 "%s Maximum-prefix restart timer expired, restore peering",
3202 peer->host);
0a486e5f 3203
a9bafa95 3204 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3205 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3206
d62a17ae 3207 return 0;
0a486e5f 3208}
3209
9cbd06e0
DA
3210static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3211 safi_t safi)
3212{
3213 uint32_t count = 0;
f41b0459 3214 bool filtered = false;
9cbd06e0
DA
3215 struct bgp_dest *dest;
3216 struct bgp_adj_in *ain;
40bb2ccf 3217 struct attr attr = {};
9cbd06e0
DA
3218 struct bgp_table *table = peer->bgp->rib[afi][safi];
3219
3220 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3221 for (ain = dest->adj_in; ain; ain = ain->next) {
3222 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3223
3224 attr = *ain->attr;
9cbd06e0
DA
3225
3226 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3227 == FILTER_DENY)
f41b0459
DA
3228 filtered = true;
3229
3230 if (bgp_input_modifier(
3231 peer, rn_p, &attr, afi, safi,
3232 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3233 NULL, 0, NULL)
3234 == RMAP_DENY)
3235 filtered = true;
3236
3237 if (filtered)
9cbd06e0 3238 count++;
f41b0459
DA
3239
3240 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3241 }
3242 }
3243
3244 return count;
3245}
3246
3dc339cd
DA
3247bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3248 int always)
718e3744 3249{
d62a17ae 3250 iana_afi_t pkt_afi;
5c525538 3251 iana_safi_t pkt_safi;
9cbd06e0
DA
3252 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3253 PEER_FLAG_MAX_PREFIX_FORCE))
3254 ? bgp_filtered_routes_count(peer, afi, safi)
3255 + peer->pcount[afi][safi]
3256 : peer->pcount[afi][safi];
9cabb64b 3257
d62a17ae 3258 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3259 return false;
e0701b79 3260
9cbd06e0 3261 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3262 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3263 PEER_STATUS_PREFIX_LIMIT)
3264 && !always)
3dc339cd 3265 return false;
e0701b79 3266
d62a17ae 3267 zlog_info(
6cde4b45 3268 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3269 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3270 peer->pmax[afi][safi]);
d62a17ae 3271 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3272
3273 if (CHECK_FLAG(peer->af_flags[afi][safi],
3274 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3275 return false;
d62a17ae 3276
3277 /* Convert AFI, SAFI to values for packet. */
3278 pkt_afi = afi_int2iana(afi);
3279 pkt_safi = safi_int2iana(safi);
3280 {
d7c0a89a 3281 uint8_t ndata[7];
d62a17ae 3282
3283 ndata[0] = (pkt_afi >> 8);
3284 ndata[1] = pkt_afi;
3285 ndata[2] = pkt_safi;
3286 ndata[3] = (peer->pmax[afi][safi] >> 24);
3287 ndata[4] = (peer->pmax[afi][safi] >> 16);
3288 ndata[5] = (peer->pmax[afi][safi] >> 8);
3289 ndata[6] = (peer->pmax[afi][safi]);
3290
3291 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3292 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3293 BGP_NOTIFY_CEASE_MAX_PREFIX,
3294 ndata, 7);
3295 }
3296
3297 /* Dynamic peers will just close their connection. */
3298 if (peer_dynamic_neighbor(peer))
3dc339cd 3299 return true;
d62a17ae 3300
3301 /* restart timer start */
3302 if (peer->pmax_restart[afi][safi]) {
3303 peer->v_pmax_restart =
3304 peer->pmax_restart[afi][safi] * 60;
3305
3306 if (bgp_debug_neighbor_events(peer))
3307 zlog_debug(
3308 "%s Maximum-prefix restart timer started for %d secs",
3309 peer->host, peer->v_pmax_restart);
3310
3311 BGP_TIMER_ON(peer->t_pmax_restart,
3312 bgp_maximum_prefix_restart_timer,
3313 peer->v_pmax_restart);
3314 }
3315
3dc339cd 3316 return true;
d62a17ae 3317 } else
3318 UNSET_FLAG(peer->af_sflags[afi][safi],
3319 PEER_STATUS_PREFIX_LIMIT);
3320
b1823b69
DS
3321 if (pcount
3322 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3323 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3324 PEER_STATUS_PREFIX_THRESHOLD)
3325 && !always)
3dc339cd 3326 return false;
d62a17ae 3327
3328 zlog_info(
6cde4b45 3329 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3330 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3331 peer->pmax[afi][safi]);
d62a17ae 3332 SET_FLAG(peer->af_sflags[afi][safi],
3333 PEER_STATUS_PREFIX_THRESHOLD);
3334 } else
3335 UNSET_FLAG(peer->af_sflags[afi][safi],
3336 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3337 return false;
718e3744 3338}
3339
b40d939b 3340/* Unconditionally remove the route from the RIB, without taking
3341 * damping into consideration (eg, because the session went down)
3342 */
9bcb3eef 3343void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3344 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3345{
f009ff26 3346
3347 struct bgp *bgp = NULL;
3348 bool delete_route = false;
3349
9bcb3eef
DS
3350 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3351 safi);
d62a17ae 3352
f009ff26 3353 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3354 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3355
f009ff26 3356 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3357 * flag
3358 */
3359 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3360 delete_route = true;
9bcb3eef 3361 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3362 delete_route = true;
f009ff26 3363 if (delete_route) {
9bcb3eef
DS
3364 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3365 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3366 bgp = pi->peer->bgp;
26742171 3367 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3368 }
3369 }
3370 }
4a11bf2c 3371
9bcb3eef
DS
3372 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3373 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3374}
3375
9bcb3eef 3376static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3377 struct peer *peer, afi_t afi, safi_t safi,
3378 struct prefix_rd *prd)
3379{
9bcb3eef 3380 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3381
d62a17ae 3382 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3383 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3384 */
40ec3340
DS
3385 if (peer->sort == BGP_PEER_EBGP) {
3386 if (get_active_bdc_from_pi(pi, afi, safi)) {
3387 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3388 == BGP_DAMP_SUPPRESSED) {
3389 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3390 safi);
3391 return;
3392 }
d62a17ae 3393 }
40ec3340 3394 }
d62a17ae 3395
49e5a4a0 3396#ifdef ENABLE_BGP_VNC
d62a17ae 3397 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3398 struct bgp_dest *pdest = NULL;
d62a17ae 3399 struct bgp_table *table = NULL;
3400
9bcb3eef
DS
3401 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3402 (struct prefix *)prd);
3403 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3404 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3405
3406 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3407 peer->bgp, prd, table, p, pi);
d62a17ae 3408 }
9bcb3eef 3409 bgp_dest_unlock_node(pdest);
d62a17ae 3410 }
3411 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3412 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3413
b54892e0
DS
3414 vnc_import_bgp_del_route(peer->bgp, p, pi);
3415 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3416 }
65efcfce 3417 }
d62a17ae 3418#endif
128ea8ab 3419
d62a17ae 3420 /* If this is an EVPN route, process for un-import. */
3421 if (safi == SAFI_EVPN)
b54892e0 3422 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3423
9bcb3eef 3424 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3425}
3426
4b7e6066
DS
3427struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3428 struct peer *peer, struct attr *attr,
9bcb3eef 3429 struct bgp_dest *dest)
fb018d25 3430{
4b7e6066 3431 struct bgp_path_info *new;
fb018d25 3432
d62a17ae 3433 /* Make new BGP info. */
4b7e6066 3434 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3435 new->type = type;
3436 new->instance = instance;
3437 new->sub_type = sub_type;
3438 new->peer = peer;
3439 new->attr = attr;
3440 new->uptime = bgp_clock();
9bcb3eef 3441 new->net = dest;
d62a17ae 3442 return new;
fb018d25
DS
3443}
3444
d62a17ae 3445static void overlay_index_update(struct attr *attr,
d62a17ae 3446 union gw_addr *gw_ip)
684a7227 3447{
d62a17ae 3448 if (!attr)
3449 return;
d62a17ae 3450 if (gw_ip == NULL) {
6c924775
DS
3451 struct bgp_route_evpn eo;
3452
3453 memset(&eo, 0, sizeof(eo));
3454 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3455 } else {
6c924775
DS
3456 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3457
3458 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3459 }
684a7227
PG
3460}
3461
40381db7 3462static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3463 union gw_addr *gw_ip)
3464{
6c924775
DS
3465 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3466 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3467 union {
0a50c248 3468 esi_t esi;
11ebf4ed
DS
3469 union gw_addr ip;
3470 } temp;
d62a17ae 3471
3472 if (afi != AFI_L2VPN)
3473 return true;
11ebf4ed 3474
6c924775 3475 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3476
3477 if (gw_ip == NULL) {
3478 memset(&temp, 0, sizeof(temp));
40381db7 3479 path_gw_ip_remote = &temp.ip;
11ebf4ed 3480 } else
40381db7 3481 path_gw_ip_remote = gw_ip;
11ebf4ed 3482
6c924775 3483 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3484}
3485
c265ee22 3486/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3487bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3488 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3489 struct bgp_dest *dest)
d62a17ae 3490{
2dbe3fa9 3491 bool ret = false;
b099a5c8
DA
3492 bool is_bgp_static_route =
3493 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3494 : false;
d62a17ae 3495
e8442016
DS
3496 /*
3497 * Only validated for unicast and multicast currently.
3498 * Also valid for EVPN where the nexthop is an IP address.
3499 * If we are a bgp static route being checked then there is
3500 * no need to check to see if the nexthop is martian as
3501 * that it should be ok.
3502 */
3503 if (is_bgp_static_route ||
3504 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3505 return false;
d62a17ae 3506
3507 /* If NEXT_HOP is present, validate it. */
3508 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3509 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3510 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3511 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3512 return true;
d62a17ae 3513 }
c265ee22 3514
d62a17ae 3515 /* If MP_NEXTHOP is present, validate it. */
3516 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3517 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3518 * it is not an IPv6 link-local address.
0355b41d
DA
3519 *
3520 * If we receive an UPDATE with nexthop length set to 32 bytes
3521 * we shouldn't discard an UPDATE if it's set to (::).
3522 * The link-local (2st) is validated along the code path later.
d62a17ae 3523 */
3524 if (attr->mp_nexthop_len) {
3525 switch (attr->mp_nexthop_len) {
3526 case BGP_ATTR_NHLEN_IPV4:
3527 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3528 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3529 || IPV4_CLASS_DE(
3530 ntohl(attr->mp_nexthop_global_in.s_addr))
3531 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3532 dest));
d62a17ae 3533 break;
3534
3535 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3536 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3537 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3538 &attr->mp_nexthop_global)
d62a17ae 3539 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3540 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3541 &attr->mp_nexthop_global)
3542 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3543 dest));
d62a17ae 3544 break;
0355b41d
DA
3545 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3546 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3547 || IN6_IS_ADDR_MULTICAST(
3548 &attr->mp_nexthop_global)
3549 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3550 dest));
0355b41d 3551 break;
d62a17ae 3552
3553 default:
3dc339cd 3554 ret = true;
d62a17ae 3555 break;
3556 }
3557 }
c265ee22 3558
d62a17ae 3559 return ret;
3560}
3561
aade37d7 3562static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3563{
3564 struct community *old;
3565 struct community *new;
3566 struct community *merge;
aade37d7 3567 struct community *no_export;
2721dd61
DA
3568
3569 old = attr->community;
aade37d7 3570 no_export = community_str2com("no-export");
2721dd61 3571
b4efa101
DA
3572 assert(no_export);
3573
2721dd61 3574 if (old) {
aade37d7 3575 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3576
3577 if (!old->refcnt)
3578 community_free(&old);
3579
3580 new = community_uniq_sort(merge);
3581 community_free(&merge);
3582 } else {
aade37d7 3583 new = community_dup(no_export);
2721dd61
DA
3584 }
3585
aade37d7 3586 community_free(&no_export);
2721dd61
DA
3587
3588 attr->community = new;
3589 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3590}
3591
5a1ae2c2 3592int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3593 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3594 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3595 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3596 struct bgp_route_evpn *evpn)
d62a17ae 3597{
3598 int ret;
3599 int aspath_loop_count = 0;
9bcb3eef 3600 struct bgp_dest *dest;
d62a17ae 3601 struct bgp *bgp;
3602 struct attr new_attr;
3603 struct attr *attr_new;
40381db7 3604 struct bgp_path_info *pi;
4b7e6066
DS
3605 struct bgp_path_info *new;
3606 struct bgp_path_info_extra *extra;
d62a17ae 3607 const char *reason;
3608 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3609 int connected = 0;
3610 int do_loop_check = 1;
3611 int has_valid_label = 0;
7c312383 3612 afi_t nh_afi;
949b0f24 3613 uint8_t pi_type = 0;
3614 uint8_t pi_sub_type = 0;
3615
c7bb4f00 3616 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3617 char pfxprint[PREFIX2STR_BUFFER];
3618
3619 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3620 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3621 afi, safi, attr);
6401252f
QY
3622 }
3623
49e5a4a0 3624#ifdef ENABLE_BGP_VNC
d62a17ae 3625 int vnc_implicit_withdraw = 0;
65efcfce 3626#endif
d62a17ae 3627 int same_attr = 0;
718e3744 3628
d62a17ae 3629 memset(&new_attr, 0, sizeof(struct attr));
3630 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3631 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3632
d62a17ae 3633 bgp = peer->bgp;
9bcb3eef 3634 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3635 /* TODO: Check to see if we can get rid of "is_valid_label" */
3636 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3637 has_valid_label = (num_labels > 0) ? 1 : 0;
3638 else
3639 has_valid_label = bgp_is_valid_label(label);
718e3744 3640
28f66de2
MS
3641 if (has_valid_label)
3642 assert(label != NULL);
3643
d62a17ae 3644 /* When peer's soft reconfiguration enabled. Record input packet in
3645 Adj-RIBs-In. */
3646 if (!soft_reconfig
3647 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3648 && peer != bgp->peer_self)
9bcb3eef 3649 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3650
3651 /* Check previously received route. */
9bcb3eef 3652 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3653 if (pi->peer == peer && pi->type == type
3654 && pi->sub_type == sub_type
3655 && pi->addpath_rx_id == addpath_id)
d62a17ae 3656 break;
3657
3658 /* AS path local-as loop check. */
3659 if (peer->change_local_as) {
c4368918
DW
3660 if (peer->allowas_in[afi][safi])
3661 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3662 else if (!CHECK_FLAG(peer->flags,
3663 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3664 aspath_loop_count = 1;
3665
3666 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3667 > aspath_loop_count) {
b4d46cc9 3668 peer->stat_pfx_aspath_loop++;
9bcb3eef 3669 reason = "as-path contains our own AS A;";
d62a17ae 3670 goto filtered;
3671 }
718e3744 3672 }
718e3744 3673
d62a17ae 3674 /* If the peer is configured for "allowas-in origin" and the last ASN in
3675 * the
3676 * as-path is our ASN then we do not need to call aspath_loop_check
3677 */
3678 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3679 if (aspath_get_last_as(attr->aspath) == bgp->as)
3680 do_loop_check = 0;
3681
3682 /* AS path loop check. */
3683 if (do_loop_check) {
3684 if (aspath_loop_check(attr->aspath, bgp->as)
3685 > peer->allowas_in[afi][safi]
3686 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3687 && aspath_loop_check(attr->aspath, bgp->confed_id)
3688 > peer->allowas_in[afi][safi])) {
b4d46cc9 3689 peer->stat_pfx_aspath_loop++;
d62a17ae 3690 reason = "as-path contains our own AS;";
3691 goto filtered;
3692 }
3693 }
aac9ef6c 3694
d62a17ae 3695 /* Route reflector originator ID check. */
3696 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3697 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3698 peer->stat_pfx_originator_loop++;
d62a17ae 3699 reason = "originator is us;";
3700 goto filtered;
3701 }
718e3744 3702
d62a17ae 3703 /* Route reflector cluster ID check. */
3704 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3705 peer->stat_pfx_cluster_loop++;
d62a17ae 3706 reason = "reflected from the same cluster;";
3707 goto filtered;
3708 }
718e3744 3709
d62a17ae 3710 /* Apply incoming filter. */
3711 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3712 peer->stat_pfx_filter++;
d62a17ae 3713 reason = "filter;";
3714 goto filtered;
3715 }
718e3744 3716
a8b72dc6
DA
3717 /* RFC 8212 to prevent route leaks.
3718 * This specification intends to improve this situation by requiring the
3719 * explicit configuration of both BGP Import and Export Policies for any
3720 * External BGP (EBGP) session such as customers, peers, or
3721 * confederation boundaries for all enabled address families. Through
3722 * codification of the aforementioned requirement, operators will
3723 * benefit from consistent behavior across different BGP
3724 * implementations.
3725 */
1d3fdccf 3726 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3727 if (!bgp_inbound_policy_exists(peer,
3728 &peer->filter[afi][safi])) {
3729 reason = "inbound policy missing";
3730 goto filtered;
3731 }
3732
fb29348a
DA
3733 /* draft-ietf-idr-deprecate-as-set-confed-set
3734 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3735 * Eventually, This document (if approved) updates RFC 4271
3736 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3737 * and obsoletes RFC 6472.
3738 */
7f972cd8 3739 if (peer->bgp->reject_as_sets)
fb29348a
DA
3740 if (aspath_check_as_sets(attr->aspath)) {
3741 reason =
3742 "as-path contains AS_SET or AS_CONFED_SET type;";
3743 goto filtered;
3744 }
3745
6f4f49b2 3746 new_attr = *attr;
d62a17ae 3747
3748 /* Apply incoming route-map.
3749 * NB: new_attr may now contain newly allocated values from route-map
3750 * "set"
3751 * commands, so we need bgp_attr_flush in the error paths, until we
3752 * intern
3753 * the attr (which takes over the memory references) */
9bcb3eef
DS
3754 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3755 num_labels, dest)
3756 == RMAP_DENY) {
b4d46cc9 3757 peer->stat_pfx_filter++;
d62a17ae 3758 reason = "route-map;";
3759 bgp_attr_flush(&new_attr);
3760 goto filtered;
3761 }
718e3744 3762
05864da7 3763 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3764 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3765 /* remove from RIB previous entry */
3766 bgp_zebra_withdraw(p, pi, bgp, safi);
3767 }
3768
7f323236
DW
3769 if (peer->sort == BGP_PEER_EBGP) {
3770
2721dd61
DA
3771 /* rfc7999:
3772 * A BGP speaker receiving an announcement tagged with the
3773 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3774 * NO_EXPORT community as defined in RFC1997, or a
3775 * similar community, to prevent propagation of the
3776 * prefix outside the local AS. The community to prevent
3777 * propagation SHOULD be chosen according to the operator's
3778 * routing policy.
3779 */
3780 if (new_attr.community
3781 && community_include(new_attr.community,
3782 COMMUNITY_BLACKHOLE))
aade37d7 3783 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3784
a4d82a8a
PZ
3785 /* If we receive the graceful-shutdown community from an eBGP
3786 * peer we must lower local-preference */
3787 if (new_attr.community
3788 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3789 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3790 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3791
a4d82a8a
PZ
3792 /* If graceful-shutdown is configured then add the GSHUT
3793 * community to all paths received from eBGP peers */
637e5ba4 3794 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3795 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3796 }
3797
949b0f24 3798 if (pi) {
3799 pi_type = pi->type;
3800 pi_sub_type = pi->sub_type;
3801 }
3802
d62a17ae 3803 /* next hop check. */
a4d82a8a 3804 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3805 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3806 &new_attr, dest)) {
b4d46cc9 3807 peer->stat_pfx_nh_invalid++;
d62a17ae 3808 reason = "martian or self next-hop;";
3809 bgp_attr_flush(&new_attr);
3810 goto filtered;
3811 }
718e3744 3812
5c14a191 3813 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3814 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3815 reason = "self mac;";
3816 goto filtered;
3817 }
3818
1e9be514
QY
3819 /* Update Overlay Index */
3820 if (afi == AFI_L2VPN) {
3821 overlay_index_update(&new_attr,
3822 evpn == NULL ? NULL : &evpn->gw_ip);
3823 }
3824
a1b773e2
DS
3825 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3826 * condition :
3827 * Suppress fib is enabled
3828 * BGP_OPT_NO_FIB is not enabled
3829 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3830 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3831 */
3832 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3833 && (sub_type == BGP_ROUTE_NORMAL)
3834 && (!bgp_option_check(BGP_OPT_NO_FIB))
3835 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3836 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3837
d62a17ae 3838 attr_new = bgp_attr_intern(&new_attr);
3839
9cbd06e0
DA
3840 /* If maximum prefix count is configured and current prefix
3841 * count exeed it.
3842 */
3843 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3844 return -1;
3845
d62a17ae 3846 /* If the update is implicit withdraw. */
40381db7
DS
3847 if (pi) {
3848 pi->uptime = bgp_clock();
3849 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3850
9bcb3eef 3851 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3852
d62a17ae 3853 /* Same attribute comes in. */
40381db7 3854 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3855 && same_attr
d62a17ae 3856 && (!has_valid_label
40381db7 3857 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3858 num_labels * sizeof(mpls_label_t))
d62a17ae 3859 == 0)
3860 && (overlay_index_equal(
0a50c248 3861 afi, pi,
d62a17ae 3862 evpn == NULL ? NULL : &evpn->gw_ip))) {
40ec3340 3863 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3864 && peer->sort == BGP_PEER_EBGP
40381db7 3865 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3866 if (bgp_debug_update(peer, p, NULL, 1)) {
3867 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3868 afi, safi, prd, p, label,
3869 num_labels, addpath_id ? 1 : 0,
3870 addpath_id, pfx_buf,
3871 sizeof(pfx_buf));
d62a17ae 3872 zlog_debug("%s rcvd %s", peer->host,
3873 pfx_buf);
3874 }
3875
9bcb3eef 3876 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3877 != BGP_DAMP_SUPPRESSED) {
40381db7 3878 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3879 safi);
9bcb3eef 3880 bgp_process(bgp, dest, afi, safi);
d62a17ae 3881 }
3882 } else /* Duplicate - odd */
3883 {
3884 if (bgp_debug_update(peer, p, NULL, 1)) {
3885 if (!peer->rcvd_attr_printed) {
3886 zlog_debug(
3887 "%s rcvd UPDATE w/ attr: %s",
3888 peer->host,
3889 peer->rcvd_attr_str);
3890 peer->rcvd_attr_printed = 1;
3891 }
3892
3893 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3894 afi, safi, prd, p, label,
3895 num_labels, addpath_id ? 1 : 0,
3896 addpath_id, pfx_buf,
3897 sizeof(pfx_buf));
d62a17ae 3898 zlog_debug(
3899 "%s rcvd %s...duplicate ignored",
3900 peer->host, pfx_buf);
3901 }
3902
3903 /* graceful restart STALE flag unset. */
40381db7 3904 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3905 bgp_path_info_unset_flag(
9bcb3eef
DS
3906 dest, pi, BGP_PATH_STALE);
3907 bgp_dest_set_defer_flag(dest, false);
3908 bgp_process(bgp, dest, afi, safi);
d62a17ae 3909 }
3910 }
3911
9bcb3eef 3912 bgp_dest_unlock_node(dest);
d62a17ae 3913 bgp_attr_unintern(&attr_new);
3914
3915 return 0;
3916 }
718e3744 3917
d62a17ae 3918 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3919 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3920 if (bgp_debug_update(peer, p, NULL, 1)) {
3921 bgp_debug_rdpfxpath2str(
a4d82a8a 3922 afi, safi, prd, p, label, num_labels,
d62a17ae 3923 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3924 sizeof(pfx_buf));
3925 zlog_debug(
3926 "%s rcvd %s, flapped quicker than processing",
3927 peer->host, pfx_buf);
3928 }
3929
9bcb3eef 3930 bgp_path_info_restore(dest, pi);
d62a17ae 3931 }
718e3744 3932
d62a17ae 3933 /* Received Logging. */
3934 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3935 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3936 num_labels, addpath_id ? 1 : 0,
3937 addpath_id, pfx_buf,
3938 sizeof(pfx_buf));
d62a17ae 3939 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3940 }
718e3744 3941
d62a17ae 3942 /* graceful restart STALE flag unset. */
f009ff26 3943 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3944 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3945 bgp_dest_set_defer_flag(dest, false);
f009ff26 3946 }
d62a17ae 3947
3948 /* The attribute is changed. */
9bcb3eef 3949 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3950
3951 /* implicit withdraw, decrement aggregate and pcount here.
3952 * only if update is accepted, they'll increment below.
3953 */
40381db7 3954 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3955
3956 /* Update bgp route dampening information. */
40ec3340 3957 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3958 && peer->sort == BGP_PEER_EBGP) {
3959 /* This is implicit withdraw so we should update
40ec3340
DS
3960 * dampening information.
3961 */
40381db7 3962 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3963 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3964 }
49e5a4a0 3965#ifdef ENABLE_BGP_VNC
d62a17ae 3966 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3967 struct bgp_dest *pdest = NULL;
d62a17ae 3968 struct bgp_table *table = NULL;
3969
9bcb3eef
DS
3970 pdest = bgp_node_get(bgp->rib[afi][safi],
3971 (struct prefix *)prd);
3972 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3973 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3974
3975 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3976 bgp, prd, table, p, pi);
d62a17ae 3977 }
9bcb3eef 3978 bgp_dest_unlock_node(pdest);
d62a17ae 3979 }
3980 if ((afi == AFI_IP || afi == AFI_IP6)
3981 && (safi == SAFI_UNICAST)) {
40381db7 3982 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3983 /*
3984 * Implicit withdraw case.
3985 */
3986 ++vnc_implicit_withdraw;
40381db7
DS
3987 vnc_import_bgp_del_route(bgp, p, pi);
3988 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3989 }
3990 }
65efcfce 3991#endif
128ea8ab 3992
d62a17ae 3993 /* Special handling for EVPN update of an existing route. If the
3994 * extended community attribute has changed, we need to
3995 * un-import
3996 * the route using its existing extended community. It will be
3997 * subsequently processed for import with the new extended
3998 * community.
3999 */
6f8c9c11
PR
4000 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4001 && !same_attr) {
40381db7 4002 if ((pi->attr->flag
d62a17ae 4003 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4004 && (attr_new->flag
4005 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4006 int cmp;
4007
40381db7 4008 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 4009 attr_new->ecommunity);
4010 if (!cmp) {
4011 if (bgp_debug_update(peer, p, NULL, 1))
4012 zlog_debug(
4013 "Change in EXT-COMM, existing %s new %s",
4014 ecommunity_str(
40381db7 4015 pi->attr->ecommunity),
d62a17ae 4016 ecommunity_str(
4017 attr_new->ecommunity));
6f8c9c11
PR
4018 if (safi == SAFI_EVPN)
4019 bgp_evpn_unimport_route(
4020 bgp, afi, safi, p, pi);
4021 else /* SAFI_MPLS_VPN */
4022 vpn_leak_to_vrf_withdraw(bgp,
4023 pi);
d62a17ae 4024 }
4025 }
4026 }
718e3744 4027
d62a17ae 4028 /* Update to new attribute. */
40381db7
DS
4029 bgp_attr_unintern(&pi->attr);
4030 pi->attr = attr_new;
d62a17ae 4031
4032 /* Update MPLS label */
4033 if (has_valid_label) {
40381db7 4034 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4035 if (extra->label != label) {
4036 memcpy(&extra->label, label,
dbd587da 4037 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4038 extra->num_labels = num_labels;
4039 }
b57ba6d2
MK
4040 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4041 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4042 }
718e3744 4043
e496b420
HS
4044 /* Update SRv6 SID */
4045 if (attr->srv6_l3vpn) {
4046 extra = bgp_path_info_extra_get(pi);
4047 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4048 sid_copy(&extra->sid[0],
4049 &attr->srv6_l3vpn->sid);
4050 extra->num_sids = 1;
4051 }
4052 } else if (attr->srv6_vpn) {
4053 extra = bgp_path_info_extra_get(pi);
4054 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4055 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4056 extra->num_sids = 1;
4057 }
4058 }
4059
49e5a4a0 4060#ifdef ENABLE_BGP_VNC
d62a17ae 4061 if ((afi == AFI_IP || afi == AFI_IP6)
4062 && (safi == SAFI_UNICAST)) {
4063 if (vnc_implicit_withdraw) {
4064 /*
4065 * Add back the route with its new attributes
4066 * (e.g., nexthop).
4067 * The route is still selected, until the route
4068 * selection
4069 * queued by bgp_process actually runs. We have
4070 * to make this
4071 * update to the VNC side immediately to avoid
4072 * racing against
4073 * configuration changes (e.g., route-map
4074 * changes) which
4075 * trigger re-importation of the entire RIB.
4076 */
40381db7
DS
4077 vnc_import_bgp_add_route(bgp, p, pi);
4078 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4079 }
4080 }
65efcfce
LB
4081#endif
4082
d62a17ae 4083 /* Update bgp route dampening information. */
40ec3340 4084 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 4085 && peer->sort == BGP_PEER_EBGP) {
4086 /* Now we do normal update dampening. */
9bcb3eef 4087 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4088 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4089 bgp_dest_unlock_node(dest);
d62a17ae 4090 return 0;
4091 }
4092 }
128ea8ab 4093
d62a17ae 4094 /* Nexthop reachability check - for unicast and
4095 * labeled-unicast.. */
7c312383
AD
4096 if (((afi == AFI_IP || afi == AFI_IP6)
4097 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4098 || (safi == SAFI_EVPN &&
4099 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4100 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4101 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4102 && !CHECK_FLAG(peer->flags,
4103 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4104 && !CHECK_FLAG(bgp->flags,
4105 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4106 connected = 1;
4107 else
4108 connected = 0;
4109
960035b2
PZ
4110 struct bgp *bgp_nexthop = bgp;
4111
40381db7
DS
4112 if (pi->extra && pi->extra->bgp_orig)
4113 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4114
7c312383
AD
4115 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4116
4117 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4053e952 4118 safi, pi, NULL, connected)
a4d82a8a 4119 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4120 bgp_path_info_set_flag(dest, pi,
4121 BGP_PATH_VALID);
d62a17ae 4122 else {
4123 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4124 zlog_debug("%s(%pI4): NH unresolved",
4125 __func__,
4126 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4127 }
9bcb3eef 4128 bgp_path_info_unset_flag(dest, pi,
18ee8310 4129 BGP_PATH_VALID);
d62a17ae 4130 }
4131 } else
9bcb3eef 4132 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4133
49e5a4a0 4134#ifdef ENABLE_BGP_VNC
d62a17ae 4135 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4136 struct bgp_dest *pdest = NULL;
d62a17ae 4137 struct bgp_table *table = NULL;
4138
9bcb3eef
DS
4139 pdest = bgp_node_get(bgp->rib[afi][safi],
4140 (struct prefix *)prd);
4141 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4142 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4143
4144 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4145 bgp, prd, table, p, pi);
d62a17ae 4146 }
9bcb3eef 4147 bgp_dest_unlock_node(pdest);
d62a17ae 4148 }
4149#endif
718e3744 4150
d62a17ae 4151 /* If this is an EVPN route and some attribute has changed,
4152 * process
4153 * route for import. If the extended community has changed, we
4154 * would
4155 * have done the un-import earlier and the import would result
4156 * in the
4157 * route getting injected into appropriate L2 VNIs. If it is
4158 * just
4159 * some other attribute change, the import will result in
4160 * updating
4161 * the attributes for the route in the VNI(s).
4162 */
7c312383
AD
4163 if (safi == SAFI_EVPN && !same_attr &&
4164 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4165 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4166
4167 /* Process change. */
40381db7 4168 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4169
9bcb3eef
DS
4170 bgp_process(bgp, dest, afi, safi);
4171 bgp_dest_unlock_node(dest);
558d1fec 4172
ddb5b488
PZ
4173 if (SAFI_UNICAST == safi
4174 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4175 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4176
40381db7 4177 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4178 }
4179 if ((SAFI_MPLS_VPN == safi)
4180 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4181
40381db7 4182 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4183 }
4184
49e5a4a0 4185#ifdef ENABLE_BGP_VNC
d62a17ae 4186 if (SAFI_MPLS_VPN == safi) {
4187 mpls_label_t label_decoded = decode_label(label);
28070ee3 4188
d62a17ae 4189 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4190 type, sub_type, &label_decoded);
4191 }
4192 if (SAFI_ENCAP == safi) {
4193 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4194 type, sub_type, NULL);
4195 }
28070ee3
PZ
4196#endif
4197
d62a17ae 4198 return 0;
4199 } // End of implicit withdraw
718e3744 4200
d62a17ae 4201 /* Received Logging. */
4202 if (bgp_debug_update(peer, p, NULL, 1)) {
4203 if (!peer->rcvd_attr_printed) {
4204 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4205 peer->rcvd_attr_str);
4206 peer->rcvd_attr_printed = 1;
4207 }
718e3744 4208
a4d82a8a 4209 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4210 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4211 sizeof(pfx_buf));
4212 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4213 }
718e3744 4214
d62a17ae 4215 /* Make new BGP info. */
9bcb3eef 4216 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4217
d62a17ae 4218 /* Update MPLS label */
4219 if (has_valid_label) {
18ee8310 4220 extra = bgp_path_info_extra_get(new);
8ba71050 4221 if (extra->label != label) {
dbd587da
QY
4222 memcpy(&extra->label, label,
4223 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4224 extra->num_labels = num_labels;
4225 }
b57ba6d2
MK
4226 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4227 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4228 }
718e3744 4229
e496b420
HS
4230 /* Update SRv6 SID */
4231 if (safi == SAFI_MPLS_VPN) {
4232 extra = bgp_path_info_extra_get(new);
4233 if (attr->srv6_l3vpn) {
4234 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4235 extra->num_sids = 1;
4236 } else if (attr->srv6_vpn) {
4237 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4238 extra->num_sids = 1;
4239 }
4240 }
4241
d62a17ae 4242 /* Update Overlay Index */
4243 if (afi == AFI_L2VPN) {
4244 overlay_index_update(new->attr,
d62a17ae 4245 evpn == NULL ? NULL : &evpn->gw_ip);
4246 }
4247 /* Nexthop reachability check. */
7c312383
AD
4248 if (((afi == AFI_IP || afi == AFI_IP6)
4249 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4250 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4251 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4252 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4253 && !CHECK_FLAG(peer->flags,
4254 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4255 && !CHECK_FLAG(bgp->flags,
4256 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4257 connected = 1;
4258 else
4259 connected = 0;
4260
7c312383
AD
4261 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4262
4053e952 4263 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
7c312383 4264 connected)
a4d82a8a 4265 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4266 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4267 else {
4268 if (BGP_DEBUG(nht, NHT)) {
4269 char buf1[INET6_ADDRSTRLEN];
4270 inet_ntop(AF_INET,
4271 (const void *)&attr_new->nexthop,
4272 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4273 zlog_debug("%s(%s): NH unresolved", __func__,
4274 buf1);
d62a17ae 4275 }
9bcb3eef 4276 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4277 }
4278 } else
9bcb3eef 4279 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4280
d62a17ae 4281 /* Addpath ID */
4282 new->addpath_rx_id = addpath_id;
4283
4284 /* Increment prefix */
4285 bgp_aggregate_increment(bgp, p, new, afi, safi);
4286
4287 /* Register new BGP information. */
9bcb3eef 4288 bgp_path_info_add(dest, new);
d62a17ae 4289
4290 /* route_node_get lock */
9bcb3eef 4291 bgp_dest_unlock_node(dest);
558d1fec 4292
49e5a4a0 4293#ifdef ENABLE_BGP_VNC
d62a17ae 4294 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4295 struct bgp_dest *pdest = NULL;
d62a17ae 4296 struct bgp_table *table = NULL;
4297
9bcb3eef
DS
4298 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4299 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4300 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4301
4302 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4303 bgp, prd, table, p, new);
4304 }
9bcb3eef 4305 bgp_dest_unlock_node(pdest);
d62a17ae 4306 }
65efcfce
LB
4307#endif
4308
d62a17ae 4309 /* If this is an EVPN route, process for import. */
7c312383 4310 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4311 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4312
9bcb3eef 4313 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4314
d62a17ae 4315 /* Process change. */
9bcb3eef 4316 bgp_process(bgp, dest, afi, safi);
718e3744 4317
ddb5b488
PZ
4318 if (SAFI_UNICAST == safi
4319 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4320 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4321 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4322 }
4323 if ((SAFI_MPLS_VPN == safi)
4324 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4325
4326 vpn_leak_to_vrf_update(bgp, new);
4327 }
49e5a4a0 4328#ifdef ENABLE_BGP_VNC
d62a17ae 4329 if (SAFI_MPLS_VPN == safi) {
4330 mpls_label_t label_decoded = decode_label(label);
28070ee3 4331
d62a17ae 4332 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4333 sub_type, &label_decoded);
4334 }
4335 if (SAFI_ENCAP == safi) {
4336 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4337 sub_type, NULL);
4338 }
28070ee3
PZ
4339#endif
4340
d62a17ae 4341 return 0;
718e3744 4342
d62a17ae 4343/* This BGP update is filtered. Log the reason then update BGP
4344 entry. */
4345filtered:
9bcb3eef 4346 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4347
d62a17ae 4348 if (bgp_debug_update(peer, p, NULL, 1)) {
4349 if (!peer->rcvd_attr_printed) {
4350 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4351 peer->rcvd_attr_str);
4352 peer->rcvd_attr_printed = 1;
4353 }
718e3744 4354
a4d82a8a 4355 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4356 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4357 sizeof(pfx_buf));
4358 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4359 peer->host, pfx_buf, reason);
4360 }
128ea8ab 4361
40381db7 4362 if (pi) {
d62a17ae 4363 /* If this is an EVPN route, un-import it as it is now filtered.
4364 */
4365 if (safi == SAFI_EVPN)
40381db7 4366 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4367
ddb5b488
PZ
4368 if (SAFI_UNICAST == safi
4369 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4370 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4371
40381db7 4372 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4373 }
4374 if ((SAFI_MPLS_VPN == safi)
4375 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4376
40381db7 4377 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4378 }
4379
9bcb3eef 4380 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4381 }
4382
9bcb3eef 4383 bgp_dest_unlock_node(dest);
558d1fec 4384
49e5a4a0 4385#ifdef ENABLE_BGP_VNC
d62a17ae 4386 /*
4387 * Filtered update is treated as an implicit withdrawal (see
4388 * bgp_rib_remove()
4389 * a few lines above)
4390 */
4391 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4392 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4393 0);
4394 }
97736e32
PZ
4395#endif
4396
d62a17ae 4397 return 0;
718e3744 4398}
4399
26a3ffd6 4400int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4401 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4402 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4403 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4404{
d62a17ae 4405 struct bgp *bgp;
4406 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4407 struct bgp_dest *dest;
40381db7 4408 struct bgp_path_info *pi;
718e3744 4409
49e5a4a0 4410#ifdef ENABLE_BGP_VNC
d62a17ae 4411 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4412 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4413 0);
4414 }
28070ee3
PZ
4415#endif
4416
d62a17ae 4417 bgp = peer->bgp;
4418
4419 /* Lookup node. */
9bcb3eef 4420 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4421
4422 /* If peer is soft reconfiguration enabled. Record input packet for
4423 * further calculation.
4424 *
4425 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4426 * routes that are filtered. This tanks out Quagga RS pretty badly due
4427 * to
4428 * the iteration over all RS clients.
4429 * Since we need to remove the entry from adj_in anyway, do that first
4430 * and
4431 * if there was no entry, we don't need to do anything more.
4432 */
4433 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4434 && peer != bgp->peer_self)
9bcb3eef 4435 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4436 peer->stat_pfx_dup_withdraw++;
4437
d62a17ae 4438 if (bgp_debug_update(peer, p, NULL, 1)) {
4439 bgp_debug_rdpfxpath2str(
a4d82a8a 4440 afi, safi, prd, p, label, num_labels,
d62a17ae 4441 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4442 sizeof(pfx_buf));
4443 zlog_debug(
4444 "%s withdrawing route %s not in adj-in",
4445 peer->host, pfx_buf);
4446 }
9bcb3eef 4447 bgp_dest_unlock_node(dest);
d62a17ae 4448 return 0;
4449 }
cd808e74 4450
d62a17ae 4451 /* Lookup withdrawn route. */
9bcb3eef 4452 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4453 if (pi->peer == peer && pi->type == type
4454 && pi->sub_type == sub_type
4455 && pi->addpath_rx_id == addpath_id)
d62a17ae 4456 break;
4457
4458 /* Logging. */
4459 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4460 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4461 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4462 sizeof(pfx_buf));
4463 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4464 pfx_buf);
4465 }
718e3744 4466
d62a17ae 4467 /* Withdraw specified route from routing table. */
40381db7 4468 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4469 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4470 if (SAFI_UNICAST == safi
4471 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4472 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4473 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4474 }
4475 if ((SAFI_MPLS_VPN == safi)
4476 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4477
40381db7 4478 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4479 }
4480 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4481 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4482 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4483 sizeof(pfx_buf));
4484 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4485 }
718e3744 4486
d62a17ae 4487 /* Unlock bgp_node_get() lock. */
9bcb3eef 4488 bgp_dest_unlock_node(dest);
d62a17ae 4489
4490 return 0;
718e3744 4491}
6b0655a2 4492
d62a17ae 4493void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4494 int withdraw)
718e3744 4495{
d62a17ae 4496 struct update_subgroup *subgrp;
4497 subgrp = peer_subgroup(peer, afi, safi);
4498 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4499}
6182d65b 4500
718e3744 4501
3f9c7369
DS
4502/*
4503 * bgp_stop_announce_route_timer
4504 */
d62a17ae 4505void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4506{
d62a17ae 4507 if (!paf->t_announce_route)
4508 return;
4509
50478845 4510 thread_cancel(&paf->t_announce_route);
718e3744 4511}
6b0655a2 4512
3f9c7369
DS
4513/*
4514 * bgp_announce_route_timer_expired
4515 *
4516 * Callback that is invoked when the route announcement timer for a
4517 * peer_af expires.
4518 */
d62a17ae 4519static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4520{
d62a17ae 4521 struct peer_af *paf;
4522 struct peer *peer;
558d1fec 4523
d62a17ae 4524 paf = THREAD_ARG(t);
4525 peer = paf->peer;
718e3744 4526
d62a17ae 4527 if (peer->status != Established)
4528 return 0;
3f9c7369 4529
d62a17ae 4530 if (!peer->afc_nego[paf->afi][paf->safi])
4531 return 0;
3f9c7369 4532
d62a17ae 4533 peer_af_announce_route(paf, 1);
c5aec50b
MK
4534
4535 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4536 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4537
d62a17ae 4538 return 0;
718e3744 4539}
4540
3f9c7369
DS
4541/*
4542 * bgp_announce_route
4543 *
4544 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4545 */
d62a17ae 4546void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4547{
4548 struct peer_af *paf;
4549 struct update_subgroup *subgrp;
4550
4551 paf = peer_af_find(peer, afi, safi);
4552 if (!paf)
4553 return;
4554 subgrp = PAF_SUBGRP(paf);
4555
4556 /*
4557 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4558 * or a refresh has already been triggered.
4559 */
4560 if (!subgrp || paf->t_announce_route)
4561 return;
4562
4563 /*
4564 * Start a timer to stagger/delay the announce. This serves
4565 * two purposes - announcement can potentially be combined for
4566 * multiple peers and the announcement doesn't happen in the
4567 * vty context.
4568 */
4569 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4570 (subgrp->peer_count == 1)
4571 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4572 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4573 &paf->t_announce_route);
3f9c7369
DS
4574}
4575
4576/*
4577 * Announce routes from all AF tables to a peer.
4578 *
4579 * This should ONLY be called when there is a need to refresh the
4580 * routes to the peer based on a policy change for this peer alone
4581 * or a route refresh request received from the peer.
4582 * The operation will result in splitting the peer from its existing
4583 * subgroups and putting it in new subgroups.
4584 */
d62a17ae 4585void bgp_announce_route_all(struct peer *peer)
718e3744 4586{
d62a17ae 4587 afi_t afi;
4588 safi_t safi;
4589
05c7a1cc
QY
4590 FOREACH_AFI_SAFI (afi, safi)
4591 bgp_announce_route(peer, afi, safi);
718e3744 4592}
6b0655a2 4593
d62a17ae 4594static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4595 struct bgp_table *table,
4596 struct prefix_rd *prd)
718e3744 4597{
d62a17ae 4598 int ret;
9bcb3eef 4599 struct bgp_dest *dest;
d62a17ae 4600 struct bgp_adj_in *ain;
718e3744 4601
d62a17ae 4602 if (!table)
4603 table = peer->bgp->rib[afi][safi];
718e3744 4604
9bcb3eef
DS
4605 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4606 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4607 if (ain->peer != peer)
4608 continue;
8692c506 4609
d7d15889 4610 struct bgp_path_info *pi;
d7c0a89a 4611 uint32_t num_labels = 0;
b57ba6d2 4612 mpls_label_t *label_pnt = NULL;
8cb687c2 4613 struct bgp_route_evpn evpn;
b57ba6d2 4614
9bcb3eef 4615 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4616 pi = pi->next)
4617 if (pi->peer == peer)
4618 break;
4619
40381db7
DS
4620 if (pi && pi->extra)
4621 num_labels = pi->extra->num_labels;
b57ba6d2 4622 if (num_labels)
40381db7 4623 label_pnt = &pi->extra->label[0];
8cb687c2 4624 if (pi)
6c924775
DS
4625 memcpy(&evpn,
4626 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4627 sizeof(evpn));
4628 else
4629 memset(&evpn, 0, sizeof(evpn));
8692c506 4630
9bcb3eef
DS
4631 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4632 ain->addpath_rx_id, ain->attr, afi,
4633 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4634 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4635 num_labels, 1, &evpn);
ea47320b
DL
4636
4637 if (ret < 0) {
9bcb3eef 4638 bgp_dest_unlock_node(dest);
ea47320b 4639 return;
d62a17ae 4640 }
4641 }
718e3744 4642}
4643
d62a17ae 4644void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4645{
9bcb3eef 4646 struct bgp_dest *dest;
d62a17ae 4647 struct bgp_table *table;
718e3744 4648
d62a17ae 4649 if (peer->status != Established)
4650 return;
718e3744 4651
d62a17ae 4652 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4653 && (safi != SAFI_EVPN))
4654 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4655 else
9bcb3eef
DS
4656 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4657 dest = bgp_route_next(dest)) {
4658 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4659
b54892e0
DS
4660 if (table == NULL)
4661 continue;
8692c506 4662
9bcb3eef 4663 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4664 struct prefix_rd prd;
4665
4666 prd.family = AF_UNSPEC;
4667 prd.prefixlen = 64;
4668 memcpy(&prd.val, p->u.val, 8);
4669
4670 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4671 }
718e3744 4672}
6b0655a2 4673
228da428 4674
d62a17ae 4675struct bgp_clear_node_queue {
9bcb3eef 4676 struct bgp_dest *dest;
228da428
CC
4677};
4678
d62a17ae 4679static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4680{
d62a17ae 4681 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4682 struct bgp_dest *dest = cnq->dest;
d62a17ae 4683 struct peer *peer = wq->spec.data;
40381db7 4684 struct bgp_path_info *pi;
3103e8d2 4685 struct bgp *bgp;
9bcb3eef
DS
4686 afi_t afi = bgp_dest_table(dest)->afi;
4687 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4688
9bcb3eef 4689 assert(dest && peer);
3103e8d2 4690 bgp = peer->bgp;
d62a17ae 4691
4692 /* It is possible that we have multiple paths for a prefix from a peer
4693 * if that peer is using AddPath.
4694 */
9bcb3eef 4695 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4696 if (pi->peer != peer)
ea47320b
DL
4697 continue;
4698
4699 /* graceful restart STALE flag set. */
9af52ccf
DA
4700 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4701 && peer->nsf[afi][safi])
4702 || CHECK_FLAG(peer->af_sflags[afi][safi],
4703 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4704 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4705 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4706 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4707 else {
4708 /* If this is an EVPN route, process for
4709 * un-import. */
4710 if (safi == SAFI_EVPN)
9bcb3eef
DS
4711 bgp_evpn_unimport_route(
4712 bgp, afi, safi,
4713 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4714 /* Handle withdraw for VRF route-leaking and L3VPN */
4715 if (SAFI_UNICAST == safi
4716 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4717 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4718 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4719 bgp, pi);
960035b2 4720 }
3103e8d2 4721 if (SAFI_MPLS_VPN == safi &&
960035b2 4722 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4723 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4724 }
3103e8d2 4725
9bcb3eef 4726 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4727 }
ea47320b 4728 }
d62a17ae 4729 return WQ_SUCCESS;
200df115 4730}
4731
d62a17ae 4732static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4733{
d62a17ae 4734 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4735 struct bgp_dest *dest = cnq->dest;
4736 struct bgp_table *table = bgp_dest_table(dest);
228da428 4737
9bcb3eef 4738 bgp_dest_unlock_node(dest);
d62a17ae 4739 bgp_table_unlock(table);
4740 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4741}
4742
d62a17ae 4743static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4744{
d62a17ae 4745 struct peer *peer = wq->spec.data;
64e580a7 4746
d62a17ae 4747 /* Tickle FSM to start moving again */
4748 BGP_EVENT_ADD(peer, Clearing_Completed);
4749
4750 peer_unlock(peer); /* bgp_clear_route */
200df115 4751}
718e3744 4752
d62a17ae 4753static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4754{
d62a17ae 4755 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4756
4757 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4758#undef CLEAR_QUEUE_NAME_LEN
4759
0ce1ca80 4760 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4761 peer->clear_node_queue->spec.hold = 10;
4762 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4763 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4764 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4765 peer->clear_node_queue->spec.max_retries = 0;
4766
4767 /* we only 'lock' this peer reference when the queue is actually active
4768 */
4769 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4770}
4771
d62a17ae 4772static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4773 struct bgp_table *table)
65ca75e0 4774{
9bcb3eef 4775 struct bgp_dest *dest;
b6c386bb 4776 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4777
d62a17ae 4778 if (!table)
4779 table = peer->bgp->rib[afi][safi];
dc83d712 4780
d62a17ae 4781 /* If still no table => afi/safi isn't configured at all or smth. */
4782 if (!table)
4783 return;
dc83d712 4784
9bcb3eef 4785 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4786 struct bgp_path_info *pi, *next;
d62a17ae 4787 struct bgp_adj_in *ain;
4788 struct bgp_adj_in *ain_next;
4789
4790 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4791 * queued for every clearing peer, regardless of whether it is
4792 * relevant to the peer at hand.
4793 *
4794 * Overview: There are 3 different indices which need to be
4795 * scrubbed, potentially, when a peer is removed:
4796 *
4797 * 1 peer's routes visible via the RIB (ie accepted routes)
4798 * 2 peer's routes visible by the (optional) peer's adj-in index
4799 * 3 other routes visible by the peer's adj-out index
4800 *
4801 * 3 there is no hurry in scrubbing, once the struct peer is
4802 * removed from bgp->peer, we could just GC such deleted peer's
4803 * adj-outs at our leisure.
4804 *
4805 * 1 and 2 must be 'scrubbed' in some way, at least made
4806 * invisible via RIB index before peer session is allowed to be
4807 * brought back up. So one needs to know when such a 'search' is
4808 * complete.
4809 *
4810 * Ideally:
4811 *
4812 * - there'd be a single global queue or a single RIB walker
4813 * - rather than tracking which route_nodes still need to be
4814 * examined on a peer basis, we'd track which peers still
4815 * aren't cleared
4816 *
4817 * Given that our per-peer prefix-counts now should be reliable,
4818 * this may actually be achievable. It doesn't seem to be a huge
4819 * problem at this time,
4820 *
4821 * It is possible that we have multiple paths for a prefix from
4822 * a peer
4823 * if that peer is using AddPath.
4824 */
9bcb3eef 4825 ain = dest->adj_in;
d62a17ae 4826 while (ain) {
4827 ain_next = ain->next;
4828
4829 if (ain->peer == peer) {
9bcb3eef
DS
4830 bgp_adj_in_remove(dest, ain);
4831 bgp_dest_unlock_node(dest);
d62a17ae 4832 }
4833
4834 ain = ain_next;
4835 }
4836
9bcb3eef 4837 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4838 next = pi->next;
4839 if (pi->peer != peer)
d62a17ae 4840 continue;
4841
4842 if (force)
9bcb3eef 4843 bgp_path_info_reap(dest, pi);
d62a17ae 4844 else {
4845 struct bgp_clear_node_queue *cnq;
4846
4847 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4848 bgp_table_lock(bgp_dest_table(dest));
4849 bgp_dest_lock_node(dest);
d62a17ae 4850 cnq = XCALLOC(
4851 MTYPE_BGP_CLEAR_NODE_QUEUE,
4852 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4853 cnq->dest = dest;
d62a17ae 4854 work_queue_add(peer->clear_node_queue, cnq);
4855 break;
4856 }
4857 }
4858 }
4859 return;
4860}
4861
4862void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4863{
9bcb3eef 4864 struct bgp_dest *dest;
d62a17ae 4865 struct bgp_table *table;
4866
4867 if (peer->clear_node_queue == NULL)
4868 bgp_clear_node_queue_init(peer);
4869
4870 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4871 * Idle until it receives a Clearing_Completed event. This protects
4872 * against peers which flap faster than we can we clear, which could
4873 * lead to:
4874 *
4875 * a) race with routes from the new session being installed before
4876 * clear_route_node visits the node (to delete the route of that
4877 * peer)
4878 * b) resource exhaustion, clear_route_node likely leads to an entry
4879 * on the process_main queue. Fast-flapping could cause that queue
4880 * to grow and grow.
4881 */
4882
4883 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4884 * the unlock will happen upon work-queue completion; other wise, the
4885 * unlock happens at the end of this function.
4886 */
4887 if (!peer->clear_node_queue->thread)
4888 peer_lock(peer);
4889
4890 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4891 bgp_clear_route_table(peer, afi, safi, NULL);
4892 else
9bcb3eef
DS
4893 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4894 dest = bgp_route_next(dest)) {
4895 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4896 if (!table)
4897 continue;
4898
4899 bgp_clear_route_table(peer, afi, safi, table);
4900 }
d62a17ae 4901
4902 /* unlock if no nodes got added to the clear-node-queue. */
4903 if (!peer->clear_node_queue->thread)
4904 peer_unlock(peer);
718e3744 4905}
d62a17ae 4906
4907void bgp_clear_route_all(struct peer *peer)
718e3744 4908{
d62a17ae 4909 afi_t afi;
4910 safi_t safi;
718e3744 4911
05c7a1cc
QY
4912 FOREACH_AFI_SAFI (afi, safi)
4913 bgp_clear_route(peer, afi, safi);
65efcfce 4914
49e5a4a0 4915#ifdef ENABLE_BGP_VNC
d62a17ae 4916 rfapiProcessPeerDown(peer);
65efcfce 4917#endif
718e3744 4918}
4919
d62a17ae 4920void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4921{
d62a17ae 4922 struct bgp_table *table;
9bcb3eef 4923 struct bgp_dest *dest;
d62a17ae 4924 struct bgp_adj_in *ain;
4925 struct bgp_adj_in *ain_next;
718e3744 4926
d62a17ae 4927 table = peer->bgp->rib[afi][safi];
718e3744 4928
d62a17ae 4929 /* It is possible that we have multiple paths for a prefix from a peer
4930 * if that peer is using AddPath.
4931 */
9bcb3eef
DS
4932 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4933 ain = dest->adj_in;
43143c8f 4934
d62a17ae 4935 while (ain) {
4936 ain_next = ain->next;
43143c8f 4937
d62a17ae 4938 if (ain->peer == peer) {
9bcb3eef
DS
4939 bgp_adj_in_remove(dest, ain);
4940 bgp_dest_unlock_node(dest);
d62a17ae 4941 }
43143c8f 4942
d62a17ae 4943 ain = ain_next;
4944 }
4945 }
718e3744 4946}
93406d87 4947
d62a17ae 4948void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4949{
9bcb3eef 4950 struct bgp_dest *dest;
40381db7 4951 struct bgp_path_info *pi;
d62a17ae 4952 struct bgp_table *table;
4953
9af52ccf 4954 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
4955 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4956 dest = bgp_route_next(dest)) {
4957 struct bgp_dest *rm;
d62a17ae 4958
4959 /* look for neighbor in tables */
9bcb3eef 4960 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4961 if (!table)
ea47320b
DL
4962 continue;
4963
4964 for (rm = bgp_table_top(table); rm;
4965 rm = bgp_route_next(rm))
9bcb3eef 4966 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4967 pi = pi->next) {
40381db7 4968 if (pi->peer != peer)
ea47320b 4969 continue;
40381db7 4970 if (!CHECK_FLAG(pi->flags,
1defdda8 4971 BGP_PATH_STALE))
ea47320b
DL
4972 break;
4973
40381db7 4974 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4975 break;
4976 }
d62a17ae 4977 }
4978 } else {
9bcb3eef
DS
4979 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4980 dest = bgp_route_next(dest))
4981 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4982 pi = pi->next) {
40381db7 4983 if (pi->peer != peer)
ea47320b 4984 continue;
40381db7 4985 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4986 break;
9bcb3eef 4987 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4988 break;
4989 }
d62a17ae 4990 }
93406d87 4991}
6b0655a2 4992
9af52ccf
DA
4993void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4994{
4995 struct bgp_dest *dest, *ndest;
4996 struct bgp_path_info *pi;
4997 struct bgp_table *table;
4998
4999 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5000 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5001 dest = bgp_route_next(dest)) {
5002 table = bgp_dest_get_bgp_table_info(dest);
5003 if (!table)
5004 continue;
5005
5006 for (ndest = bgp_table_top(table); ndest;
5007 ndest = bgp_route_next(ndest)) {
5008 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5009 pi = pi->next) {
5010 if (pi->peer != peer)
5011 continue;
5012
5013 if ((CHECK_FLAG(
5014 peer->af_sflags[afi][safi],
5015 PEER_STATUS_ENHANCED_REFRESH))
5016 && !CHECK_FLAG(pi->flags,
5017 BGP_PATH_STALE)
5018 && !CHECK_FLAG(
5019 pi->flags,
5020 BGP_PATH_UNUSEABLE)) {
5021 if (bgp_debug_neighbor_events(
5022 peer))
5023 zlog_debug(
5024 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5025 peer->host,
5026 afi2str(afi),
5027 safi2str(safi),
5028 bgp_dest_get_prefix(
5029 ndest));
5030
5031 bgp_path_info_set_flag(
5032 ndest, pi,
5033 BGP_PATH_STALE);
5034 }
5035 }
5036 }
5037 }
5038 } else {
5039 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5040 dest = bgp_route_next(dest)) {
5041 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5042 pi = pi->next) {
5043 if (pi->peer != peer)
5044 continue;
5045
5046 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5047 PEER_STATUS_ENHANCED_REFRESH))
5048 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5049 && !CHECK_FLAG(pi->flags,
5050 BGP_PATH_UNUSEABLE)) {
5051 if (bgp_debug_neighbor_events(peer))
5052 zlog_debug(
5053 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5054 peer->host,
5055 afi2str(afi),
5056 safi2str(safi),
5057 bgp_dest_get_prefix(
5058 dest));
5059
5060 bgp_path_info_set_flag(dest, pi,
5061 BGP_PATH_STALE);
5062 }
5063 }
5064 }
5065 }
5066}
5067
3dc339cd 5068bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5069{
e0df4c04 5070 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5071 return true;
e0df4c04 5072
9dac9fc8
DA
5073 if (peer->sort == BGP_PEER_EBGP
5074 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5075 || FILTER_LIST_OUT_NAME(filter)
5076 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5077 return true;
5078 return false;
9dac9fc8
DA
5079}
5080
3dc339cd 5081bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5082{
e0df4c04 5083 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5084 return true;
e0df4c04 5085
9dac9fc8
DA
5086 if (peer->sort == BGP_PEER_EBGP
5087 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5088 || FILTER_LIST_IN_NAME(filter)
5089 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5090 return true;
5091 return false;
9dac9fc8
DA
5092}
5093
568e10ca 5094static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5095 safi_t safi)
bb86c601 5096{
9bcb3eef 5097 struct bgp_dest *dest;
40381db7 5098 struct bgp_path_info *pi;
4b7e6066 5099 struct bgp_path_info *next;
bb86c601 5100
9bcb3eef
DS
5101 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5102 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5103 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5104
40381db7 5105 next = pi->next;
1b7bb747
CS
5106
5107 /* Unimport EVPN routes from VRFs */
5108 if (safi == SAFI_EVPN)
5109 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5110 SAFI_EVPN, p, pi);
1b7bb747 5111
40381db7
DS
5112 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5113 && pi->type == ZEBRA_ROUTE_BGP
5114 && (pi->sub_type == BGP_ROUTE_NORMAL
5115 || pi->sub_type == BGP_ROUTE_AGGREGATE
5116 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5117
d62a17ae 5118 if (bgp_fibupd_safi(safi))
b54892e0 5119 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5120 }
9514b37d 5121
9bcb3eef 5122 bgp_path_info_reap(dest, pi);
d62a17ae 5123 }
bb86c601
LB
5124}
5125
718e3744 5126/* Delete all kernel routes. */
d62a17ae 5127void bgp_cleanup_routes(struct bgp *bgp)
5128{
5129 afi_t afi;
9bcb3eef 5130 struct bgp_dest *dest;
67009e22 5131 struct bgp_table *table;
d62a17ae 5132
5133 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5134 if (afi == AFI_L2VPN)
5135 continue;
568e10ca 5136 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5137 SAFI_UNICAST);
d62a17ae 5138 /*
5139 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5140 */
5141 if (afi != AFI_L2VPN) {
5142 safi_t safi;
5143 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5144 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5145 dest = bgp_route_next(dest)) {
5146 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5147 if (table != NULL) {
5148 bgp_cleanup_table(bgp, table, safi);
5149 bgp_table_finish(&table);
9bcb3eef
DS
5150 bgp_dest_set_bgp_table_info(dest, NULL);
5151 bgp_dest_unlock_node(dest);
d62a17ae 5152 }
5153 }
5154 safi = SAFI_ENCAP;
9bcb3eef
DS
5155 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5156 dest = bgp_route_next(dest)) {
5157 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5158 if (table != NULL) {
5159 bgp_cleanup_table(bgp, table, safi);
5160 bgp_table_finish(&table);
9bcb3eef
DS
5161 bgp_dest_set_bgp_table_info(dest, NULL);
5162 bgp_dest_unlock_node(dest);
d62a17ae 5163 }
5164 }
5165 }
5166 }
9bcb3eef
DS
5167 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5168 dest = bgp_route_next(dest)) {
5169 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5170 if (table != NULL) {
5171 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5172 bgp_table_finish(&table);
9bcb3eef
DS
5173 bgp_dest_set_bgp_table_info(dest, NULL);
5174 bgp_dest_unlock_node(dest);
d62a17ae 5175 }
bb86c601 5176 }
718e3744 5177}
5178
d62a17ae 5179void bgp_reset(void)
718e3744 5180{
d62a17ae 5181 vty_reset();
5182 bgp_zclient_reset();
5183 access_list_reset();
5184 prefix_list_reset();
718e3744 5185}
6b0655a2 5186
d62a17ae 5187static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5188{
d62a17ae 5189 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5190 && CHECK_FLAG(peer->af_cap[afi][safi],
5191 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5192}
5193
718e3744 5194/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5195 value. */
d62a17ae 5196int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5197 struct bgp_nlri *packet)
5198{
d7c0a89a
QY
5199 uint8_t *pnt;
5200 uint8_t *lim;
d62a17ae 5201 struct prefix p;
5202 int psize;
5203 int ret;
5204 afi_t afi;
5205 safi_t safi;
5206 int addpath_encoded;
d7c0a89a 5207 uint32_t addpath_id;
d62a17ae 5208
d62a17ae 5209 pnt = packet->nlri;
5210 lim = pnt + packet->length;
5211 afi = packet->afi;
5212 safi = packet->safi;
5213 addpath_id = 0;
5214 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5215
5216 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5217 syntactic validity. If the field is syntactically incorrect,
5218 then the Error Subcode is set to Invalid Network Field. */
5219 for (; pnt < lim; pnt += psize) {
5220 /* Clear prefix structure. */
5221 memset(&p, 0, sizeof(struct prefix));
5222
5223 if (addpath_encoded) {
5224
5225 /* When packet overflow occurs return immediately. */
761ed665 5226 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5227 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5228
a3a850a1 5229 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5230 addpath_id = ntohl(addpath_id);
d62a17ae 5231 pnt += BGP_ADDPATH_ID_LEN;
5232 }
718e3744 5233
d62a17ae 5234 /* Fetch prefix length. */
5235 p.prefixlen = *pnt++;
5236 /* afi/safi validity already verified by caller,
5237 * bgp_update_receive */
5238 p.family = afi2family(afi);
5239
5240 /* Prefix length check. */
5241 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5242 flog_err(
e50f7cfd 5243 EC_BGP_UPDATE_RCV,
14454c9f 5244 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5245 peer->host, p.prefixlen, packet->afi);
513386b5 5246 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5247 }
6b0655a2 5248
d62a17ae 5249 /* Packet size overflow check. */
5250 psize = PSIZE(p.prefixlen);
5251
5252 /* When packet overflow occur return immediately. */
5253 if (pnt + psize > lim) {
af4c2728 5254 flog_err(
e50f7cfd 5255 EC_BGP_UPDATE_RCV,
d62a17ae 5256 "%s [Error] Update packet error (prefix length %d overflows packet)",
5257 peer->host, p.prefixlen);
513386b5 5258 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5259 }
5260
5261 /* Defensive coding, double-check the psize fits in a struct
5262 * prefix */
5263 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5264 flog_err(
e50f7cfd 5265 EC_BGP_UPDATE_RCV,
d62a17ae 5266 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5267 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5268 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5269 }
5270
5271 /* Fetch prefix from NLRI packet. */
a85297a7 5272 memcpy(p.u.val, pnt, psize);
d62a17ae 5273
5274 /* Check address. */
5275 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5276 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5277 /* From RFC4271 Section 6.3:
5278 *
5279 * If a prefix in the NLRI field is semantically
5280 * incorrect
5281 * (e.g., an unexpected multicast IP address),
5282 * an error SHOULD
5283 * be logged locally, and the prefix SHOULD be
5284 * ignored.
a4d82a8a 5285 */
af4c2728 5286 flog_err(
e50f7cfd 5287 EC_BGP_UPDATE_RCV,
23d0a753
DA
5288 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5289 peer->host, &p.u.prefix4);
d62a17ae 5290 continue;
5291 }
5292 }
5293
5294 /* Check address. */
5295 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5296 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5297 flog_err(
e50f7cfd 5298 EC_BGP_UPDATE_RCV,
c0d72166
DS
5299 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5300 peer->host, &p.u.prefix6);
d62a17ae 5301
5302 continue;
5303 }
5304 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5305 flog_err(
e50f7cfd 5306 EC_BGP_UPDATE_RCV,
c0d72166
DS
5307 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5308 peer->host, &p.u.prefix6);
d62a17ae 5309
5310 continue;
5311 }
5312 }
5313
5314 /* Normal process. */
5315 if (attr)
5316 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5317 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5318 NULL, NULL, 0, 0, NULL);
d62a17ae 5319 else
5320 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5321 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5322 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5323 NULL);
d62a17ae 5324
513386b5
DA
5325 /* Do not send BGP notification twice when maximum-prefix count
5326 * overflow. */
5327 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5328 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5329
5330 /* Address family configuration mismatch. */
d62a17ae 5331 if (ret < 0)
513386b5 5332 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5333 }
5334
5335 /* Packet length consistency check. */
5336 if (pnt != lim) {
af4c2728 5337 flog_err(
e50f7cfd 5338 EC_BGP_UPDATE_RCV,
d62a17ae 5339 "%s [Error] Update packet error (prefix length mismatch with total length)",
5340 peer->host);
513386b5 5341 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5342 }
6b0655a2 5343
513386b5 5344 return BGP_NLRI_PARSE_OK;
718e3744 5345}
5346
d62a17ae 5347static struct bgp_static *bgp_static_new(void)
718e3744 5348{
d62a17ae 5349 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5350}
5351
d62a17ae 5352static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5353{
0a22ddfb 5354 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5355 route_map_counter_decrement(bgp_static->rmap.map);
5356
0a22ddfb 5357 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5358 XFREE(MTYPE_BGP_STATIC, bgp_static);
5359}
5360
5f040085 5361void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5362 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5363{
9bcb3eef 5364 struct bgp_dest *dest;
40381db7 5365 struct bgp_path_info *pi;
4b7e6066 5366 struct bgp_path_info *new;
40381db7 5367 struct bgp_path_info rmap_path;
d62a17ae 5368 struct attr attr;
5369 struct attr *attr_new;
b68885f9 5370 route_map_result_t ret;
49e5a4a0 5371#ifdef ENABLE_BGP_VNC
d62a17ae 5372 int vnc_implicit_withdraw = 0;
65efcfce 5373#endif
fee0f4c6 5374
d62a17ae 5375 assert(bgp_static);
dd8103a9 5376
9bcb3eef 5377 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5378
d62a17ae 5379 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5380
d62a17ae 5381 attr.nexthop = bgp_static->igpnexthop;
5382 attr.med = bgp_static->igpmetric;
5383 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5384
d62a17ae 5385 if (bgp_static->atomic)
5386 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5387
d62a17ae 5388 /* Store label index, if required. */
5389 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5390 attr.label_index = bgp_static->label_index;
5391 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5392 }
718e3744 5393
d62a17ae 5394 /* Apply route-map. */
5395 if (bgp_static->rmap.name) {
5396 struct attr attr_tmp = attr;
80ced710 5397
40381db7
DS
5398 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5399 rmap_path.peer = bgp->peer_self;
5400 rmap_path.attr = &attr_tmp;
fee0f4c6 5401
d62a17ae 5402 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5403
1782514f 5404 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5405
d62a17ae 5406 bgp->peer_self->rmap_type = 0;
718e3744 5407
d62a17ae 5408 if (ret == RMAP_DENYMATCH) {
5409 /* Free uninterned attribute. */
5410 bgp_attr_flush(&attr_tmp);
718e3744 5411
d62a17ae 5412 /* Unintern original. */
5413 aspath_unintern(&attr.aspath);
5414 bgp_static_withdraw(bgp, p, afi, safi);
5415 return;
5416 }
7f323236 5417
637e5ba4 5418 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5419 bgp_attr_add_gshut_community(&attr_tmp);
5420
d62a17ae 5421 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5422 } else {
5423
637e5ba4 5424 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5425 bgp_attr_add_gshut_community(&attr);
5426
d62a17ae 5427 attr_new = bgp_attr_intern(&attr);
7f323236 5428 }
718e3744 5429
9bcb3eef 5430 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5431 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5432 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5433 break;
5434
40381db7
DS
5435 if (pi) {
5436 if (attrhash_cmp(pi->attr, attr_new)
5437 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5438 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5439 bgp_dest_unlock_node(dest);
d62a17ae 5440 bgp_attr_unintern(&attr_new);
5441 aspath_unintern(&attr.aspath);
5442 return;
5443 } else {
5444 /* The attribute is changed. */
9bcb3eef 5445 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5446
5447 /* Rewrite BGP route information. */
40381db7 5448 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5449 bgp_path_info_restore(dest, pi);
d62a17ae 5450 else
40381db7 5451 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5452#ifdef ENABLE_BGP_VNC
d62a17ae 5453 if ((afi == AFI_IP || afi == AFI_IP6)
5454 && (safi == SAFI_UNICAST)) {
40381db7 5455 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5456 /*
5457 * Implicit withdraw case.
40381db7 5458 * We have to do this before pi is
d62a17ae 5459 * changed
5460 */
5461 ++vnc_implicit_withdraw;
40381db7 5462 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5463 vnc_import_bgp_exterior_del_route(
40381db7 5464 bgp, p, pi);
d62a17ae 5465 }
5466 }
65efcfce 5467#endif
40381db7
DS
5468 bgp_attr_unintern(&pi->attr);
5469 pi->attr = attr_new;
5470 pi->uptime = bgp_clock();
49e5a4a0 5471#ifdef ENABLE_BGP_VNC
d62a17ae 5472 if ((afi == AFI_IP || afi == AFI_IP6)
5473 && (safi == SAFI_UNICAST)) {
5474 if (vnc_implicit_withdraw) {
40381db7 5475 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5476 vnc_import_bgp_exterior_add_route(
40381db7 5477 bgp, p, pi);
d62a17ae 5478 }
5479 }
65efcfce 5480#endif
718e3744 5481
d62a17ae 5482 /* Nexthop reachability check. */
892fedb6 5483 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5484 && (safi == SAFI_UNICAST
5485 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5486
5487 struct bgp *bgp_nexthop = bgp;
5488
40381db7
DS
5489 if (pi->extra && pi->extra->bgp_orig)
5490 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5491
5492 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952
PR
5493 afi, safi, pi, NULL,
5494 0))
9bcb3eef 5495 bgp_path_info_set_flag(dest, pi,
18ee8310 5496 BGP_PATH_VALID);
d62a17ae 5497 else {
5498 if (BGP_DEBUG(nht, NHT)) {
5499 char buf1[INET6_ADDRSTRLEN];
5500 inet_ntop(p->family,
5501 &p->u.prefix, buf1,
5502 INET6_ADDRSTRLEN);
5503 zlog_debug(
5504 "%s(%s): Route not in table, not advertising",
15569c58 5505 __func__, buf1);
d62a17ae 5506 }
18ee8310 5507 bgp_path_info_unset_flag(
9bcb3eef 5508 dest, pi, BGP_PATH_VALID);
d62a17ae 5509 }
5510 } else {
5511 /* Delete the NHT structure if any, if we're
5512 * toggling between
5513 * enabling/disabling import check. We
5514 * deregister the route
5515 * from NHT to avoid overloading NHT and the
5516 * process interaction
5517 */
40381db7 5518 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5519 bgp_path_info_set_flag(dest, pi,
5520 BGP_PATH_VALID);
d62a17ae 5521 }
5522 /* Process change. */
40381db7 5523 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5524 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5525
5526 if (SAFI_UNICAST == safi
5527 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5528 || bgp->inst_type
5529 == BGP_INSTANCE_TYPE_DEFAULT)) {
5530 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5531 pi);
ddb5b488
PZ
5532 }
5533
9bcb3eef 5534 bgp_dest_unlock_node(dest);
d62a17ae 5535 aspath_unintern(&attr.aspath);
5536 return;
5537 }
718e3744 5538 }
718e3744 5539
d62a17ae 5540 /* Make new BGP info. */
5541 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5542 attr_new, dest);
d62a17ae 5543 /* Nexthop reachability check. */
892fedb6 5544 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5545 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
4053e952 5546 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
9bcb3eef 5547 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5548 else {
5549 if (BGP_DEBUG(nht, NHT)) {
5550 char buf1[INET6_ADDRSTRLEN];
5551 inet_ntop(p->family, &p->u.prefix, buf1,
5552 INET6_ADDRSTRLEN);
5553 zlog_debug(
5554 "%s(%s): Route not in table, not advertising",
15569c58 5555 __func__, buf1);
d62a17ae 5556 }
9bcb3eef 5557 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5558 }
5559 } else {
5560 /* Delete the NHT structure if any, if we're toggling between
5561 * enabling/disabling import check. We deregister the route
5562 * from NHT to avoid overloading NHT and the process interaction
5563 */
5564 bgp_unlink_nexthop(new);
5565
9bcb3eef 5566 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5567 }
078430f6 5568
d62a17ae 5569 /* Aggregate address increment. */
5570 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5571
d62a17ae 5572 /* Register new BGP information. */
9bcb3eef 5573 bgp_path_info_add(dest, new);
718e3744 5574
d62a17ae 5575 /* route_node_get lock */
9bcb3eef 5576 bgp_dest_unlock_node(dest);
d62a17ae 5577
5578 /* Process change. */
9bcb3eef 5579 bgp_process(bgp, dest, afi, safi);
d62a17ae 5580
ddb5b488
PZ
5581 if (SAFI_UNICAST == safi
5582 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5583 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5584 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5585 }
5586
d62a17ae 5587 /* Unintern original. */
5588 aspath_unintern(&attr.aspath);
718e3744 5589}
5590
5f040085 5591void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5592 safi_t safi)
718e3744 5593{
9bcb3eef 5594 struct bgp_dest *dest;
40381db7 5595 struct bgp_path_info *pi;
718e3744 5596
9bcb3eef 5597 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5598
d62a17ae 5599 /* Check selected route and self inserted route. */
9bcb3eef 5600 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5601 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5602 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5603 break;
5604
5605 /* Withdraw static BGP route from routing table. */
40381db7 5606 if (pi) {
ddb5b488
PZ
5607 if (SAFI_UNICAST == safi
5608 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5609 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5610 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5611 }
40381db7
DS
5612 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5613 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5614 bgp_path_info_delete(dest, pi);
5615 bgp_process(bgp, dest, afi, safi);
d62a17ae 5616 }
718e3744 5617
d62a17ae 5618 /* Unlock bgp_node_lookup. */
9bcb3eef 5619 bgp_dest_unlock_node(dest);
718e3744 5620}
5621
137446f9
LB
5622/*
5623 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5624 */
5f040085 5625static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5626 afi_t afi, safi_t safi,
5627 struct prefix_rd *prd)
718e3744 5628{
9bcb3eef 5629 struct bgp_dest *dest;
40381db7 5630 struct bgp_path_info *pi;
718e3744 5631
9bcb3eef 5632 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5633
d62a17ae 5634 /* Check selected route and self inserted route. */
9bcb3eef 5635 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5636 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5637 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5638 break;
718e3744 5639
d62a17ae 5640 /* Withdraw static BGP route from routing table. */
40381db7 5641 if (pi) {
49e5a4a0 5642#ifdef ENABLE_BGP_VNC
d62a17ae 5643 rfapiProcessWithdraw(
40381db7 5644 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5645 1); /* Kill, since it is an administrative change */
65efcfce 5646#endif
ddb5b488
PZ
5647 if (SAFI_MPLS_VPN == safi
5648 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5649 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5650 }
40381db7 5651 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5652 bgp_path_info_delete(dest, pi);
5653 bgp_process(bgp, dest, afi, safi);
d62a17ae 5654 }
718e3744 5655
d62a17ae 5656 /* Unlock bgp_node_lookup. */
9bcb3eef 5657 bgp_dest_unlock_node(dest);
718e3744 5658}
5659
5f040085 5660static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5661 struct bgp_static *bgp_static, afi_t afi,
5662 safi_t safi)
137446f9 5663{
9bcb3eef 5664 struct bgp_dest *dest;
4b7e6066 5665 struct bgp_path_info *new;
d62a17ae 5666 struct attr *attr_new;
5667 struct attr attr = {0};
40381db7 5668 struct bgp_path_info *pi;
49e5a4a0 5669#ifdef ENABLE_BGP_VNC
d62a17ae 5670 mpls_label_t label = 0;
65efcfce 5671#endif
d7c0a89a 5672 uint32_t num_labels = 0;
d62a17ae 5673 union gw_addr add;
137446f9 5674
d62a17ae 5675 assert(bgp_static);
137446f9 5676
b57ba6d2
MK
5677 if (bgp_static->label != MPLS_INVALID_LABEL)
5678 num_labels = 1;
9bcb3eef
DS
5679 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5680 &bgp_static->prd);
137446f9 5681
d62a17ae 5682 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5683
d62a17ae 5684 attr.nexthop = bgp_static->igpnexthop;
5685 attr.med = bgp_static->igpmetric;
5686 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5687
d62a17ae 5688 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5689 || (safi == SAFI_ENCAP)) {
5690 if (afi == AFI_IP) {
5691 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5692 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5693 }
5694 }
5695 if (afi == AFI_L2VPN) {
5696 if (bgp_static->gatewayIp.family == AF_INET)
5697 add.ipv4.s_addr =
5698 bgp_static->gatewayIp.u.prefix4.s_addr;
5699 else if (bgp_static->gatewayIp.family == AF_INET6)
5700 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5701 sizeof(struct in6_addr));
0a50c248 5702 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5703 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5704 struct bgp_encap_type_vxlan bet;
5705 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5706 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5707 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5708 }
5709 if (bgp_static->router_mac) {
5710 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5711 }
5712 }
5713 /* Apply route-map. */
5714 if (bgp_static->rmap.name) {
5715 struct attr attr_tmp = attr;
40381db7 5716 struct bgp_path_info rmap_path;
b68885f9 5717 route_map_result_t ret;
137446f9 5718
40381db7
DS
5719 rmap_path.peer = bgp->peer_self;
5720 rmap_path.attr = &attr_tmp;
137446f9 5721
d62a17ae 5722 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5723
1782514f 5724 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5725
d62a17ae 5726 bgp->peer_self->rmap_type = 0;
137446f9 5727
d62a17ae 5728 if (ret == RMAP_DENYMATCH) {
5729 /* Free uninterned attribute. */
5730 bgp_attr_flush(&attr_tmp);
137446f9 5731
d62a17ae 5732 /* Unintern original. */
5733 aspath_unintern(&attr.aspath);
5734 bgp_static_withdraw_safi(bgp, p, afi, safi,
5735 &bgp_static->prd);
5736 return;
5737 }
137446f9 5738
d62a17ae 5739 attr_new = bgp_attr_intern(&attr_tmp);
5740 } else {
5741 attr_new = bgp_attr_intern(&attr);
5742 }
137446f9 5743
9bcb3eef 5744 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5745 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5746 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5747 break;
5748
40381db7 5749 if (pi) {
d62a17ae 5750 memset(&add, 0, sizeof(union gw_addr));
40381db7 5751 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5752 && overlay_index_equal(afi, pi, &add)
40381db7 5753 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5754 bgp_dest_unlock_node(dest);
d62a17ae 5755 bgp_attr_unintern(&attr_new);
5756 aspath_unintern(&attr.aspath);
5757 return;
5758 } else {
5759 /* The attribute is changed. */
9bcb3eef 5760 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5761
5762 /* Rewrite BGP route information. */
40381db7 5763 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5764 bgp_path_info_restore(dest, pi);
d62a17ae 5765 else
40381db7
DS
5766 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5767 bgp_attr_unintern(&pi->attr);
5768 pi->attr = attr_new;
5769 pi->uptime = bgp_clock();
49e5a4a0 5770#ifdef ENABLE_BGP_VNC
40381db7
DS
5771 if (pi->extra)
5772 label = decode_label(&pi->extra->label[0]);
65efcfce 5773#endif
137446f9 5774
d62a17ae 5775 /* Process change. */
40381db7 5776 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5777 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5778
5779 if (SAFI_MPLS_VPN == safi
5780 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5781 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5782 }
49e5a4a0 5783#ifdef ENABLE_BGP_VNC
40381db7
DS
5784 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5785 pi->attr, afi, safi, pi->type,
5786 pi->sub_type, &label);
65efcfce 5787#endif
9bcb3eef 5788 bgp_dest_unlock_node(dest);
d62a17ae 5789 aspath_unintern(&attr.aspath);
5790 return;
5791 }
5792 }
137446f9
LB
5793
5794
d62a17ae 5795 /* Make new BGP info. */
5796 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5797 attr_new, dest);
1defdda8 5798 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5799 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5800 if (num_labels) {
5801 new->extra->label[0] = bgp_static->label;
5802 new->extra->num_labels = num_labels;
5803 }
49e5a4a0 5804#ifdef ENABLE_BGP_VNC
d62a17ae 5805 label = decode_label(&bgp_static->label);
65efcfce 5806#endif
137446f9 5807
d62a17ae 5808 /* Aggregate address increment. */
5809 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5810
d62a17ae 5811 /* Register new BGP information. */
9bcb3eef 5812 bgp_path_info_add(dest, new);
d62a17ae 5813 /* route_node_get lock */
9bcb3eef 5814 bgp_dest_unlock_node(dest);
137446f9 5815
d62a17ae 5816 /* Process change. */
9bcb3eef 5817 bgp_process(bgp, dest, afi, safi);
137446f9 5818
ddb5b488
PZ
5819 if (SAFI_MPLS_VPN == safi
5820 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5821 vpn_leak_to_vrf_update(bgp, new);
5822 }
49e5a4a0 5823#ifdef ENABLE_BGP_VNC
d62a17ae 5824 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5825 safi, new->type, new->sub_type, &label);
65efcfce
LB
5826#endif
5827
d62a17ae 5828 /* Unintern original. */
5829 aspath_unintern(&attr.aspath);
137446f9
LB
5830}
5831
718e3744 5832/* Configure static BGP network. When user don't run zebra, static
5833 route should be installed as valid. */
37a87b8f
CS
5834int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5835 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5836 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5837{
d62a17ae 5838 struct prefix p;
5839 struct bgp_static *bgp_static;
9bcb3eef 5840 struct bgp_dest *dest;
d7c0a89a 5841 uint8_t need_update = 0;
d62a17ae 5842
37a87b8f 5843 prefix_copy(&p, pfx);
d62a17ae 5844 apply_mask(&p);
718e3744 5845
e2a86ad9 5846 if (negate) {
718e3744 5847
e2a86ad9 5848 /* Set BGP static route configuration. */
9bcb3eef 5849 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5850
9bcb3eef 5851 if (!dest) {
37a87b8f
CS
5852 snprintf(errmsg, errmsg_len,
5853 "Can't find static route specified\n");
5854 return -1;
d62a17ae 5855 }
5856
9bcb3eef 5857 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5858
e2a86ad9
DS
5859 if ((label_index != BGP_INVALID_LABEL_INDEX)
5860 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5861 snprintf(errmsg, errmsg_len,
5862 "label-index doesn't match static route\n");
5863 return -1;
d62a17ae 5864 }
d62a17ae 5865
e2a86ad9
DS
5866 if ((rmap && bgp_static->rmap.name)
5867 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5868 snprintf(errmsg, errmsg_len,
5869 "route-map name doesn't match static route\n");
5870 return -1;
d62a17ae 5871 }
718e3744 5872
e2a86ad9
DS
5873 /* Update BGP RIB. */
5874 if (!bgp_static->backdoor)
5875 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5876
e2a86ad9
DS
5877 /* Clear configuration. */
5878 bgp_static_free(bgp_static);
9bcb3eef
DS
5879 bgp_dest_set_bgp_static_info(dest, NULL);
5880 bgp_dest_unlock_node(dest);
5881 bgp_dest_unlock_node(dest);
e2a86ad9 5882 } else {
718e3744 5883
e2a86ad9 5884 /* Set BGP static route configuration. */
9bcb3eef
DS
5885 dest = bgp_node_get(bgp->route[afi][safi], &p);
5886 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5887 if (bgp_static) {
e2a86ad9 5888 /* Configuration change. */
e2a86ad9
DS
5889 /* Label index cannot be changed. */
5890 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5891 snprintf(errmsg, errmsg_len,
5892 "cannot change label-index\n");
5893 return -1;
e2a86ad9 5894 }
d62a17ae 5895
e2a86ad9 5896 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5897 if (bgp_static->valid
5898 && bgp_static->backdoor != backdoor)
e2a86ad9 5899 need_update = 1;
718e3744 5900
e2a86ad9 5901 bgp_static->backdoor = backdoor;
718e3744 5902
e2a86ad9 5903 if (rmap) {
0a22ddfb
QY
5904 XFREE(MTYPE_ROUTE_MAP_NAME,
5905 bgp_static->rmap.name);
b4897fa5 5906 route_map_counter_decrement(
5907 bgp_static->rmap.map);
e2a86ad9
DS
5908 bgp_static->rmap.name =
5909 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5910 bgp_static->rmap.map =
5911 route_map_lookup_by_name(rmap);
b4897fa5 5912 route_map_counter_increment(
5913 bgp_static->rmap.map);
e2a86ad9 5914 } else {
0a22ddfb
QY
5915 XFREE(MTYPE_ROUTE_MAP_NAME,
5916 bgp_static->rmap.name);
b4897fa5 5917 route_map_counter_decrement(
5918 bgp_static->rmap.map);
e2a86ad9
DS
5919 bgp_static->rmap.map = NULL;
5920 bgp_static->valid = 0;
5921 }
9bcb3eef 5922 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5923 } else {
5924 /* New configuration. */
5925 bgp_static = bgp_static_new();
5926 bgp_static->backdoor = backdoor;
5927 bgp_static->valid = 0;
5928 bgp_static->igpmetric = 0;
975a328e 5929 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5930 bgp_static->label_index = label_index;
718e3744 5931
e2a86ad9 5932 if (rmap) {
0a22ddfb
QY
5933 XFREE(MTYPE_ROUTE_MAP_NAME,
5934 bgp_static->rmap.name);
b4897fa5 5935 route_map_counter_decrement(
5936 bgp_static->rmap.map);
e2a86ad9
DS
5937 bgp_static->rmap.name =
5938 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5939 bgp_static->rmap.map =
5940 route_map_lookup_by_name(rmap);
b4897fa5 5941 route_map_counter_increment(
5942 bgp_static->rmap.map);
e2a86ad9 5943 }
9bcb3eef 5944 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5945 }
d62a17ae 5946
e2a86ad9
DS
5947 bgp_static->valid = 1;
5948 if (need_update)
5949 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5950
e2a86ad9
DS
5951 if (!bgp_static->backdoor)
5952 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5953 }
d62a17ae 5954
37a87b8f 5955 return 0;
d62a17ae 5956}
5957
5958void bgp_static_add(struct bgp *bgp)
5959{
5960 afi_t afi;
5961 safi_t safi;
9bcb3eef
DS
5962 struct bgp_dest *dest;
5963 struct bgp_dest *rm;
d62a17ae 5964 struct bgp_table *table;
5965 struct bgp_static *bgp_static;
5966
05c7a1cc 5967 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5968 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5969 dest = bgp_route_next(dest)) {
5970 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5971 continue;
ea47320b 5972
05c7a1cc
QY
5973 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5974 || (safi == SAFI_EVPN)) {
9bcb3eef 5975 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5976
5977 for (rm = bgp_table_top(table); rm;
5978 rm = bgp_route_next(rm)) {
a78beeb5 5979 bgp_static =
9bcb3eef 5980 bgp_dest_get_bgp_static_info(
5a8ba9fc 5981 rm);
9bcb3eef
DS
5982 bgp_static_update_safi(
5983 bgp, bgp_dest_get_prefix(rm),
5984 bgp_static, afi, safi);
d62a17ae 5985 }
05c7a1cc 5986 } else {
5a8ba9fc 5987 bgp_static_update(
9bcb3eef
DS
5988 bgp, bgp_dest_get_prefix(dest),
5989 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5990 safi);
ea47320b 5991 }
05c7a1cc 5992 }
6aeb9e78
DS
5993}
5994
718e3744 5995/* Called from bgp_delete(). Delete all static routes from the BGP
5996 instance. */
d62a17ae 5997void bgp_static_delete(struct bgp *bgp)
5998{
5999 afi_t afi;
6000 safi_t safi;
9bcb3eef
DS
6001 struct bgp_dest *dest;
6002 struct bgp_dest *rm;
d62a17ae 6003 struct bgp_table *table;
6004 struct bgp_static *bgp_static;
6005
05c7a1cc 6006 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6007 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6008 dest = bgp_route_next(dest)) {
6009 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6010 continue;
ea47320b 6011
05c7a1cc
QY
6012 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6013 || (safi == SAFI_EVPN)) {
9bcb3eef 6014 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6015
6016 for (rm = bgp_table_top(table); rm;
6017 rm = bgp_route_next(rm)) {
a78beeb5 6018 bgp_static =
9bcb3eef 6019 bgp_dest_get_bgp_static_info(
5a8ba9fc 6020 rm);
c7d14ba6
PG
6021 if (!bgp_static)
6022 continue;
6023
05c7a1cc 6024 bgp_static_withdraw_safi(
9bcb3eef 6025 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6026 AFI_IP, safi,
6027 (struct prefix_rd *)
9bcb3eef
DS
6028 bgp_dest_get_prefix(
6029 dest));
ea47320b 6030 bgp_static_free(bgp_static);
811c6797 6031 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6032 NULL);
811c6797 6033 bgp_dest_unlock_node(rm);
d62a17ae 6034 }
05c7a1cc 6035 } else {
9bcb3eef 6036 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6037 bgp_static_withdraw(bgp,
9bcb3eef 6038 bgp_dest_get_prefix(dest),
b54892e0 6039 afi, safi);
05c7a1cc 6040 bgp_static_free(bgp_static);
9bcb3eef
DS
6041 bgp_dest_set_bgp_static_info(dest, NULL);
6042 bgp_dest_unlock_node(dest);
ea47320b 6043 }
05c7a1cc 6044 }
d62a17ae 6045}
6046
6047void bgp_static_redo_import_check(struct bgp *bgp)
6048{
6049 afi_t afi;
6050 safi_t safi;
9bcb3eef
DS
6051 struct bgp_dest *dest;
6052 struct bgp_dest *rm;
d62a17ae 6053 struct bgp_table *table;
6054 struct bgp_static *bgp_static;
6055
6056 /* Use this flag to force reprocessing of the route */
892fedb6 6057 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6058 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6059 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6060 dest = bgp_route_next(dest)) {
6061 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6062 continue;
ea47320b 6063
05c7a1cc
QY
6064 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6065 || (safi == SAFI_EVPN)) {
9bcb3eef 6066 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6067
6068 for (rm = bgp_table_top(table); rm;
6069 rm = bgp_route_next(rm)) {
a78beeb5 6070 bgp_static =
9bcb3eef 6071 bgp_dest_get_bgp_static_info(
5a8ba9fc 6072 rm);
9bcb3eef
DS
6073 bgp_static_update_safi(
6074 bgp, bgp_dest_get_prefix(rm),
6075 bgp_static, afi, safi);
d62a17ae 6076 }
05c7a1cc 6077 } else {
9bcb3eef
DS
6078 bgp_static = bgp_dest_get_bgp_static_info(dest);
6079 bgp_static_update(bgp,
6080 bgp_dest_get_prefix(dest),
6081 bgp_static, afi, safi);
ea47320b 6082 }
05c7a1cc
QY
6083 }
6084 }
892fedb6 6085 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6086}
6087
6088static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6089 safi_t safi)
6090{
6091 struct bgp_table *table;
9bcb3eef 6092 struct bgp_dest *dest;
40381db7 6093 struct bgp_path_info *pi;
d62a17ae 6094
dfb6fd1d
NT
6095 /* Do not install the aggregate route if BGP is in the
6096 * process of termination.
6097 */
892fedb6
DA
6098 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6099 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6100 return;
6101
d62a17ae 6102 table = bgp->rib[afi][safi];
9bcb3eef
DS
6103 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6104 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6105 if (pi->peer == bgp->peer_self
6106 && ((pi->type == ZEBRA_ROUTE_BGP
6107 && pi->sub_type == BGP_ROUTE_STATIC)
6108 || (pi->type != ZEBRA_ROUTE_BGP
6109 && pi->sub_type
d62a17ae 6110 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6111 bgp_aggregate_decrement(
6112 bgp, bgp_dest_get_prefix(dest), pi, afi,
6113 safi);
40381db7 6114 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6115 bgp_path_info_delete(dest, pi);
6116 bgp_process(bgp, dest, afi, safi);
d62a17ae 6117 }
6118 }
6119 }
ad4cbda1 6120}
6121
6122/*
6123 * Purge all networks and redistributed routes from routing table.
6124 * Invoked upon the instance going down.
6125 */
d62a17ae 6126void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6127{
d62a17ae 6128 afi_t afi;
6129 safi_t safi;
ad4cbda1 6130
05c7a1cc
QY
6131 FOREACH_AFI_SAFI (afi, safi)
6132 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6133}
6134
137446f9
LB
6135/*
6136 * gpz 110624
6137 * Currently this is used to set static routes for VPN and ENCAP.
6138 * I think it can probably be factored with bgp_static_set.
6139 */
d62a17ae 6140int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6141 const char *ip_str, const char *rd_str,
6142 const char *label_str, const char *rmap_str,
6143 int evpn_type, const char *esi, const char *gwip,
6144 const char *ethtag, const char *routermac)
6145{
6146 VTY_DECLVAR_CONTEXT(bgp, bgp);
6147 int ret;
6148 struct prefix p;
6149 struct prefix_rd prd;
9bcb3eef
DS
6150 struct bgp_dest *pdest;
6151 struct bgp_dest *dest;
d62a17ae 6152 struct bgp_table *table;
6153 struct bgp_static *bgp_static;
6154 mpls_label_t label = MPLS_INVALID_LABEL;
6155 struct prefix gw_ip;
6156
6157 /* validate ip prefix */
6158 ret = str2prefix(ip_str, &p);
6159 if (!ret) {
6160 vty_out(vty, "%% Malformed prefix\n");
6161 return CMD_WARNING_CONFIG_FAILED;
6162 }
6163 apply_mask(&p);
6164 if ((afi == AFI_L2VPN)
6165 && (bgp_build_evpn_prefix(evpn_type,
6166 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6167 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6168 return CMD_WARNING_CONFIG_FAILED;
6169 }
718e3744 6170
d62a17ae 6171 ret = str2prefix_rd(rd_str, &prd);
6172 if (!ret) {
6173 vty_out(vty, "%% Malformed rd\n");
6174 return CMD_WARNING_CONFIG_FAILED;
6175 }
718e3744 6176
d62a17ae 6177 if (label_str) {
6178 unsigned long label_val;
6179 label_val = strtoul(label_str, NULL, 10);
6180 encode_label(label_val, &label);
6181 }
9bedbb1e 6182
d62a17ae 6183 if (safi == SAFI_EVPN) {
6184 if (esi && str2esi(esi, NULL) == 0) {
6185 vty_out(vty, "%% Malformed ESI\n");
6186 return CMD_WARNING_CONFIG_FAILED;
6187 }
6188 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6189 vty_out(vty, "%% Malformed Router MAC\n");
6190 return CMD_WARNING_CONFIG_FAILED;
6191 }
6192 if (gwip) {
6193 memset(&gw_ip, 0, sizeof(struct prefix));
6194 ret = str2prefix(gwip, &gw_ip);
6195 if (!ret) {
6196 vty_out(vty, "%% Malformed GatewayIp\n");
6197 return CMD_WARNING_CONFIG_FAILED;
6198 }
6199 if ((gw_ip.family == AF_INET
3714a385 6200 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6201 (struct prefix_evpn *)&p))
6202 || (gw_ip.family == AF_INET6
3714a385 6203 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6204 (struct prefix_evpn *)&p))) {
6205 vty_out(vty,
6206 "%% GatewayIp family differs with IP prefix\n");
6207 return CMD_WARNING_CONFIG_FAILED;
6208 }
6209 }
6210 }
9bcb3eef
DS
6211 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6212 if (!bgp_dest_has_bgp_path_info_data(pdest))
6213 bgp_dest_set_bgp_table_info(pdest,
67009e22 6214 bgp_table_init(bgp, afi, safi));
9bcb3eef 6215 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6216
9bcb3eef 6217 dest = bgp_node_get(table, &p);
d62a17ae 6218
9bcb3eef 6219 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6220 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6221 bgp_dest_unlock_node(dest);
d62a17ae 6222 } else {
6223 /* New configuration. */
6224 bgp_static = bgp_static_new();
6225 bgp_static->backdoor = 0;
6226 bgp_static->valid = 0;
6227 bgp_static->igpmetric = 0;
975a328e 6228 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6229 bgp_static->label = label;
6230 bgp_static->prd = prd;
6231
6232 if (rmap_str) {
0a22ddfb 6233 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6234 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6235 bgp_static->rmap.name =
6236 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6237 bgp_static->rmap.map =
6238 route_map_lookup_by_name(rmap_str);
b4897fa5 6239 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6240 }
718e3744 6241
d62a17ae 6242 if (safi == SAFI_EVPN) {
6243 if (esi) {
6244 bgp_static->eth_s_id =
6245 XCALLOC(MTYPE_ATTR,
0a50c248 6246 sizeof(esi_t));
d62a17ae 6247 str2esi(esi, bgp_static->eth_s_id);
6248 }
6249 if (routermac) {
6250 bgp_static->router_mac =
28328ea9 6251 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6252 (void)prefix_str2mac(routermac,
6253 bgp_static->router_mac);
d62a17ae 6254 }
6255 if (gwip)
6256 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6257 }
9bcb3eef 6258 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6259
d62a17ae 6260 bgp_static->valid = 1;
6261 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6262 }
718e3744 6263
d62a17ae 6264 return CMD_SUCCESS;
718e3744 6265}
6266
6267/* Configure static BGP network. */
d62a17ae 6268int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6269 const char *ip_str, const char *rd_str,
6270 const char *label_str, int evpn_type, const char *esi,
6271 const char *gwip, const char *ethtag)
6272{
6273 VTY_DECLVAR_CONTEXT(bgp, bgp);
6274 int ret;
6275 struct prefix p;
6276 struct prefix_rd prd;
9bcb3eef
DS
6277 struct bgp_dest *pdest;
6278 struct bgp_dest *dest;
d62a17ae 6279 struct bgp_table *table;
6280 struct bgp_static *bgp_static;
6281 mpls_label_t label = MPLS_INVALID_LABEL;
6282
6283 /* Convert IP prefix string to struct prefix. */
6284 ret = str2prefix(ip_str, &p);
6285 if (!ret) {
6286 vty_out(vty, "%% Malformed prefix\n");
6287 return CMD_WARNING_CONFIG_FAILED;
6288 }
6289 apply_mask(&p);
6290 if ((afi == AFI_L2VPN)
6291 && (bgp_build_evpn_prefix(evpn_type,
6292 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6293 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6294 return CMD_WARNING_CONFIG_FAILED;
6295 }
6296 ret = str2prefix_rd(rd_str, &prd);
6297 if (!ret) {
6298 vty_out(vty, "%% Malformed rd\n");
6299 return CMD_WARNING_CONFIG_FAILED;
6300 }
718e3744 6301
d62a17ae 6302 if (label_str) {
6303 unsigned long label_val;
6304 label_val = strtoul(label_str, NULL, 10);
6305 encode_label(label_val, &label);
6306 }
718e3744 6307
9bcb3eef
DS
6308 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6309 if (!bgp_dest_has_bgp_path_info_data(pdest))
6310 bgp_dest_set_bgp_table_info(pdest,
67009e22 6311 bgp_table_init(bgp, afi, safi));
d62a17ae 6312 else
9bcb3eef
DS
6313 bgp_dest_unlock_node(pdest);
6314 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6315
9bcb3eef 6316 dest = bgp_node_lookup(table, &p);
6b0655a2 6317
9bcb3eef 6318 if (dest) {
d62a17ae 6319 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6320
9bcb3eef 6321 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6322 bgp_static_free(bgp_static);
9bcb3eef
DS
6323 bgp_dest_set_bgp_static_info(dest, NULL);
6324 bgp_dest_unlock_node(dest);
6325 bgp_dest_unlock_node(dest);
d62a17ae 6326 } else
6327 vty_out(vty, "%% Can't find the route\n");
6328
6329 return CMD_SUCCESS;
6330}
6331
6332static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6333 const char *rmap_name)
6334{
6335 VTY_DECLVAR_CONTEXT(bgp, bgp);
6336 struct bgp_rmap *rmap;
6337
6338 rmap = &bgp->table_map[afi][safi];
6339 if (rmap_name) {
0a22ddfb 6340 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6341 route_map_counter_decrement(rmap->map);
d62a17ae 6342 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6343 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6344 route_map_counter_increment(rmap->map);
d62a17ae 6345 } else {
0a22ddfb 6346 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6347 route_map_counter_decrement(rmap->map);
d62a17ae 6348 rmap->map = NULL;
6349 }
73ac8160 6350
d62a17ae 6351 if (bgp_fibupd_safi(safi))
6352 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6353
d62a17ae 6354 return CMD_SUCCESS;
73ac8160
DS
6355}
6356
d62a17ae 6357static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6358 const char *rmap_name)
73ac8160 6359{
d62a17ae 6360 VTY_DECLVAR_CONTEXT(bgp, bgp);
6361 struct bgp_rmap *rmap;
73ac8160 6362
d62a17ae 6363 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6364 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6365 route_map_counter_decrement(rmap->map);
d62a17ae 6366 rmap->map = NULL;
73ac8160 6367
d62a17ae 6368 if (bgp_fibupd_safi(safi))
6369 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6370
d62a17ae 6371 return CMD_SUCCESS;
73ac8160
DS
6372}
6373
2b791107 6374void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6375 safi_t safi)
73ac8160 6376{
d62a17ae 6377 if (bgp->table_map[afi][safi].name) {
d62a17ae 6378 vty_out(vty, " table-map %s\n",
6379 bgp->table_map[afi][safi].name);
6380 }
73ac8160
DS
6381}
6382
73ac8160
DS
6383DEFUN (bgp_table_map,
6384 bgp_table_map_cmd,
6385 "table-map WORD",
6386 "BGP table to RIB route download filter\n"
6387 "Name of the route map\n")
6388{
d62a17ae 6389 int idx_word = 1;
6390 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6391 argv[idx_word]->arg);
73ac8160
DS
6392}
6393DEFUN (no_bgp_table_map,
6394 no_bgp_table_map_cmd,
6395 "no table-map WORD",
3a2d747c 6396 NO_STR
73ac8160
DS
6397 "BGP table to RIB route download filter\n"
6398 "Name of the route map\n")
6399{
d62a17ae 6400 int idx_word = 2;
6401 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6402 argv[idx_word]->arg);
73ac8160
DS
6403}
6404
37a87b8f
CS
6405DEFPY_YANG (bgp_network, bgp_network_cmd,
6406 "[no] network \
6407 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6408 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6409 backdoor$backdoor}]",
6410 NO_STR
6411 "Specify a network to announce via BGP\n"
6412 "IPv4 prefix\n"
6413 "Network number\n"
6414 "Network mask\n"
6415 "Network mask\n"
6416 "Route-map to modify the attributes\n"
6417 "Name of the route map\n"
6418 "Label index to associate with the prefix\n"
6419 "Label index value\n"
6420 "Specify a BGP backdoor route\n")
6421{
6422 char addr_prefix_str[PREFIX_STRLEN];
6423 char base_xpath[XPATH_MAXLEN];
6424 afi_t afi;
6425 safi_t safi;
e2a86ad9
DS
6426
6427 if (address_str) {
6428 int ret;
718e3744 6429
e2a86ad9 6430 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6431 addr_prefix_str,
6432 sizeof(addr_prefix_str));
e2a86ad9
DS
6433 if (!ret) {
6434 vty_out(vty, "%% Inconsistent address and mask\n");
6435 return CMD_WARNING_CONFIG_FAILED;
6436 }
d62a17ae 6437 }
718e3744 6438
37a87b8f
CS
6439 afi = bgp_node_afi(vty);
6440 safi = bgp_node_safi(vty);
6441
6442 if (no) {
6443 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6444 } else {
6445 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6446
6447 if (map_name)
6448 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6449 NB_OP_CREATE, map_name);
6450 else
6451 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6452 NB_OP_DESTROY, NULL);
6453
6454 if (label_index_str)
6455 nb_cli_enqueue_change(vty, "./label-index",
6456 NB_OP_MODIFY, label_index_str);
6457
6458 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6459 backdoor ? "true" : "false");
6460 }
6461
6462 snprintf(
6463 base_xpath, sizeof(base_xpath),
6464 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6465 yang_afi_safi_value2identity(afi, safi),
6466 bgp_afi_safi_get_container_str(afi, safi),
6467 address_str ? addr_prefix_str : prefix_str);
6468
6469 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6470}
6471
37a87b8f
CS
6472DEFPY_YANG (ipv6_bgp_network,
6473 ipv6_bgp_network_cmd,
6474 "[no] network X:X::X:X/M$prefix \
6475 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6476 NO_STR
6477 "Specify a network to announce via BGP\n"
6478 "IPv6 prefix\n"
6479 "Route-map to modify the attributes\n"
6480 "Name of the route map\n"
6481 "Label index to associate with the prefix\n"
6482 "Label index value\n")
6483{
6484 char base_xpath[XPATH_MAXLEN];
6485 afi_t afi;
6486 safi_t safi;
6487
6488 afi = bgp_node_afi(vty);
6489 safi = bgp_node_safi(vty);
6490
6491 if (no) {
6492 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6493 } else {
6494 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6495
6496 if (map_name)
6497 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6498 NB_OP_MODIFY, map_name);
6499 else
6500 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6501 NB_OP_DESTROY, NULL);
6502
6503 if (label_index_str)
6504 nb_cli_enqueue_change(vty, "./label-index",
6505 NB_OP_MODIFY, label_index_str);
6506 }
6507
6508 snprintf(
6509 base_xpath, sizeof(base_xpath),
6510 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6511 yang_afi_safi_value2identity(afi, safi),
6512 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6513
6514 return nb_cli_apply_changes(vty, base_xpath);
6515}
6516
6517void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6518 struct lyd_node *dnode,
6519 bool show_defaults)
718e3744 6520{
37a87b8f
CS
6521 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6522
6523 if (yang_dnode_exists(dnode, "./label-index"))
6524 vty_out(vty, " label-index %s",
6525 yang_dnode_get_string(dnode, "./label-index"));
6526
6527 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6528 vty_out(vty, " route-map %s",
6529 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6530
6531 if (yang_dnode_get_bool(dnode, "./backdoor"))
6532 vty_out(vty, " backdoor");
6533
6534 vty_out(vty, "\n");
1b6d5c7e
VV
6535}
6536
d62a17ae 6537static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6538{
d62a17ae 6539 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6540}
6541
d62a17ae 6542static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6543{
365ab2e7
RZ
6544 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6545 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6546 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6547 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6548 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6549}
718e3744 6550
365ab2e7
RZ
6551/**
6552 * Helper function to avoid repeated code: prepare variables for a
6553 * `route_map_apply` call.
6554 *
6555 * \returns `true` on route map match, otherwise `false`.
6556 */
6557static bool aggr_suppress_map_test(struct bgp *bgp,
6558 struct bgp_aggregate *aggregate,
6559 struct bgp_path_info *pi)
6560{
6561 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6562 route_map_result_t rmr = RMAP_DENYMATCH;
6563 struct bgp_path_info rmap_path = {};
6564 struct attr attr = {};
6565
6566 /* No route map entries created, just don't match. */
6567 if (aggregate->suppress_map == NULL)
6568 return false;
6569
6570 /* Call route map matching and return result. */
6571 attr.aspath = aspath_empty();
6572 rmap_path.peer = bgp->peer_self;
6573 rmap_path.attr = &attr;
6574
6575 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6576 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6577 bgp->peer_self->rmap_type = 0;
6578
6579 bgp_attr_flush(&attr);
6580
6581 return rmr == RMAP_PERMITMATCH;
6582}
6583
4056a5f6
RZ
6584/** Test whether the aggregation has suppressed this path or not. */
6585static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6586 struct bgp_path_info *pi)
6587{
6588 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6589 return false;
6590
6591 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6592}
6593
6594/**
6595 * Suppress this path and keep the reference.
6596 *
6597 * \returns `true` if needs processing otherwise `false`.
6598 */
6599static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6600 struct bgp_path_info *pi)
6601{
6602 struct bgp_path_info_extra *pie;
6603
6604 /* Path is already suppressed by this aggregation. */
6605 if (aggr_suppress_exists(aggregate, pi))
6606 return false;
6607
6608 pie = bgp_path_info_extra_get(pi);
6609
6610 /* This is the first suppression, allocate memory and list it. */
6611 if (pie->aggr_suppressors == NULL)
6612 pie->aggr_suppressors = list_new();
6613
6614 listnode_add(pie->aggr_suppressors, aggregate);
6615
6616 /* Only mark for processing if suppressed. */
6617 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6618 if (BGP_DEBUG(update, UPDATE_OUT))
6619 zlog_debug("aggregate-address suppressing: %pFX",
6620 bgp_dest_get_prefix(pi->net));
6621
4056a5f6
RZ
6622 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6623 return true;
6624 }
6625
6626 return false;
6627}
6628
6629/**
6630 * Unsuppress this path and remove the reference.
6631 *
6632 * \returns `true` if needs processing otherwise `false`.
6633 */
6634static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6635 struct bgp_path_info *pi)
6636{
6637 /* Path wasn't suppressed. */
6638 if (!aggr_suppress_exists(aggregate, pi))
6639 return false;
6640
6641 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6642
6643 /* Unsuppress and free extra memory if last item. */
6644 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6645 if (BGP_DEBUG(update, UPDATE_OUT))
6646 zlog_debug("aggregate-address unsuppressing: %pFX",
6647 bgp_dest_get_prefix(pi->net));
6648
4056a5f6
RZ
6649 list_delete(&pi->extra->aggr_suppressors);
6650 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6651 return true;
6652 }
6653
6654 return false;
6655}
6656
3dc339cd
DA
6657static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6658 struct aspath *aspath,
6659 struct community *comm,
6660 struct ecommunity *ecomm,
6661 struct lcommunity *lcomm)
eaaf8adb
DS
6662{
6663 static struct aspath *ae = NULL;
6664
6665 if (!ae)
6666 ae = aspath_empty();
6667
40381db7 6668 if (!pi)
3dc339cd 6669 return false;
eaaf8adb 6670
40381db7 6671 if (origin != pi->attr->origin)
3dc339cd 6672 return false;
eaaf8adb 6673
40381db7 6674 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6675 return false;
29f7d023 6676
40381db7 6677 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6678 return false;
eaaf8adb 6679
3da2cc32 6680 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6681 return false;
eaaf8adb 6682
dd18c5a9 6683 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6684 return false;
dd18c5a9 6685
40381db7 6686 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6687 return false;
7ce8a8e0 6688
3dc339cd 6689 return true;
eaaf8adb
DS
6690}
6691
5f040085
DS
6692static void bgp_aggregate_install(
6693 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6694 uint8_t origin, struct aspath *aspath, struct community *community,
6695 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6696 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6697{
9bcb3eef 6698 struct bgp_dest *dest;
c701010e 6699 struct bgp_table *table;
6f94b685 6700 struct bgp_path_info *pi, *orig, *new;
20894f50 6701 struct attr *attr;
c701010e
DS
6702
6703 table = bgp->rib[afi][safi];
6704
9bcb3eef 6705 dest = bgp_node_get(table, p);
eaaf8adb 6706
9bcb3eef 6707 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6708 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6709 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6710 break;
6711
6aabb15d
RZ
6712 /*
6713 * If we have paths with different MEDs, then don't install
6714 * (or uninstall) the aggregate route.
6715 */
6716 if (aggregate->match_med && aggregate->med_mismatched)
6717 goto uninstall_aggregate_route;
6718
c701010e 6719 if (aggregate->count > 0) {
eaaf8adb
DS
6720 /*
6721 * If the aggregate information has not changed
6722 * no need to re-install it again.
6723 */
6f94b685 6724 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6725 ecommunity, lcommunity)) {
9bcb3eef 6726 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6727
6728 if (aspath)
6729 aspath_free(aspath);
6730 if (community)
3c1f53de 6731 community_free(&community);
3da2cc32
DS
6732 if (ecommunity)
6733 ecommunity_free(&ecommunity);
dd18c5a9
DS
6734 if (lcommunity)
6735 lcommunity_free(&lcommunity);
eaaf8adb
DS
6736
6737 return;
6738 }
6739
6740 /*
6741 * Mark the old as unusable
6742 */
40381db7 6743 if (pi)
9bcb3eef 6744 bgp_path_info_delete(dest, pi);
eaaf8adb 6745
20894f50
DA
6746 attr = bgp_attr_aggregate_intern(
6747 bgp, origin, aspath, community, ecommunity, lcommunity,
6748 aggregate, atomic_aggregate, p);
6749
6750 if (!attr) {
6751 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6752 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6753 zlog_debug("%s: %pFX null attribute", __func__,
6754 p);
20894f50
DA
6755 return;
6756 }
6757
3da2cc32 6758 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6759 bgp->peer_self, attr, dest);
20894f50 6760
1defdda8 6761 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6762
9bcb3eef
DS
6763 bgp_path_info_add(dest, new);
6764 bgp_process(bgp, dest, afi, safi);
c701010e 6765 } else {
6aabb15d 6766 uninstall_aggregate_route:
6f94b685 6767 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6768 if (pi->peer == bgp->peer_self
6769 && pi->type == ZEBRA_ROUTE_BGP
6770 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6771 break;
6772
6773 /* Withdraw static BGP route from routing table. */
40381db7 6774 if (pi) {
9bcb3eef
DS
6775 bgp_path_info_delete(dest, pi);
6776 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6777 }
6778 }
6779
9bcb3eef 6780 bgp_dest_unlock_node(dest);
c701010e
DS
6781}
6782
6aabb15d
RZ
6783/**
6784 * Check if the current path has different MED than other known paths.
6785 *
6786 * \returns `true` if the MED matched the others else `false`.
6787 */
6788static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6789 struct bgp *bgp, struct bgp_path_info *pi)
6790{
6791 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6792
6793 /* This is the first route being analyzed. */
6794 if (!aggregate->med_initialized) {
6795 aggregate->med_initialized = true;
6796 aggregate->med_mismatched = false;
6797 aggregate->med_matched_value = cur_med;
6798 } else {
6799 /* Check if routes with different MED showed up. */
6800 if (cur_med != aggregate->med_matched_value)
6801 aggregate->med_mismatched = true;
6802 }
6803
6804 return !aggregate->med_mismatched;
6805}
6806
6807/**
6808 * Initializes and tests all routes in the aggregate address path for MED
6809 * values.
6810 *
6811 * \returns `true` if all MEDs are the same otherwise `false`.
6812 */
6813static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6814 struct bgp *bgp, const struct prefix *p,
6815 afi_t afi, safi_t safi)
6816{
6817 struct bgp_table *table = bgp->rib[afi][safi];
6818 const struct prefix *dest_p;
6819 struct bgp_dest *dest, *top;
6820 struct bgp_path_info *pi;
6821 bool med_matched = true;
6822
6823 aggregate->med_initialized = false;
6824
6825 top = bgp_node_get(table, p);
6826 for (dest = bgp_node_get(table, p); dest;
6827 dest = bgp_route_next_until(dest, top)) {
6828 dest_p = bgp_dest_get_prefix(dest);
6829 if (dest_p->prefixlen <= p->prefixlen)
6830 continue;
6831
6832 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6833 if (BGP_PATH_HOLDDOWN(pi))
6834 continue;
6835 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6836 continue;
6837 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6838 med_matched = false;
6839 break;
6840 }
6841 }
6842 if (!med_matched)
6843 break;
6844 }
6845 bgp_dest_unlock_node(top);
6846
6847 return med_matched;
6848}
6849
6850/**
6851 * Toggles the route suppression status for this aggregate address
6852 * configuration.
6853 */
4056a5f6
RZ
6854void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6855 struct bgp *bgp, const struct prefix *p,
6856 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6857{
6858 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6859 const struct prefix *dest_p;
6860 struct bgp_dest *dest, *top;
6861 struct bgp_path_info *pi;
6862 bool toggle_suppression;
6863
6864 /* We've found a different MED we must revert any suppressed routes. */
6865 top = bgp_node_get(table, p);
6866 for (dest = bgp_node_get(table, p); dest;
6867 dest = bgp_route_next_until(dest, top)) {
6868 dest_p = bgp_dest_get_prefix(dest);
6869 if (dest_p->prefixlen <= p->prefixlen)
6870 continue;
6871
6872 toggle_suppression = false;
6873 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6874 if (BGP_PATH_HOLDDOWN(pi))
6875 continue;
6876 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6877 continue;
6878
6aabb15d
RZ
6879 /* We are toggling suppression back. */
6880 if (suppress) {
6aabb15d 6881 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6882 if (aggr_suppress_path(aggregate, pi))
6883 toggle_suppression = true;
6aabb15d
RZ
6884 continue;
6885 }
6886
6aabb15d 6887 /* Install route if there is no more suppression. */
4056a5f6 6888 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6889 toggle_suppression = true;
6aabb15d
RZ
6890 }
6891
6892 if (toggle_suppression)
6893 bgp_process(bgp, dest, afi, safi);
6894 }
6895 bgp_dest_unlock_node(top);
6896}
6897
6898/**
6899 * Aggregate address MED matching incremental test: this function is called
6900 * when the initial aggregation occurred and we are only testing a single
6901 * new path.
6902 *
6903 * In addition to testing and setting the MED validity it also installs back
6904 * suppressed routes (if summary is configured).
6905 *
6906 * Must not be called in `bgp_aggregate_route`.
6907 */
6908static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6909 struct bgp *bgp, const struct prefix *p,
6910 afi_t afi, safi_t safi,
6911 struct bgp_path_info *pi, bool is_adding)
6912{
6913 /* MED matching disabled. */
6914 if (!aggregate->match_med)
6915 return;
6916
6917 /* Aggregation with different MED, nothing to do. */
6918 if (aggregate->med_mismatched)
6919 return;
6920
6921 /*
6922 * Test the current entry:
6923 *
6924 * is_adding == true: if the new entry doesn't match then we must
6925 * install all suppressed routes.
6926 *
6927 * is_adding == false: if the entry being removed was the last
6928 * unmatching entry then we can suppress all routes.
6929 */
6930 if (!is_adding) {
6931 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6932 && aggregate->summary_only)
6933 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6934 safi, true);
6935 } else
6936 bgp_aggregate_med_match(aggregate, bgp, pi);
6937
6938 /* No mismatches, just quit. */
6939 if (!aggregate->med_mismatched)
6940 return;
6941
6942 /* Route summarization is disabled. */
6943 if (!aggregate->summary_only)
6944 return;
6945
6946 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6947}
6948
b5d58c32 6949/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6950void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6951 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6952{
6953 struct bgp_table *table;
9bcb3eef
DS
6954 struct bgp_dest *top;
6955 struct bgp_dest *dest;
d7c0a89a 6956 uint8_t origin;
d62a17ae 6957 struct aspath *aspath = NULL;
d62a17ae 6958 struct community *community = NULL;
3da2cc32 6959 struct ecommunity *ecommunity = NULL;
dd18c5a9 6960 struct lcommunity *lcommunity = NULL;
40381db7 6961 struct bgp_path_info *pi;
d62a17ae 6962 unsigned long match = 0;
d7c0a89a 6963 uint8_t atomic_aggregate = 0;
d62a17ae 6964
9f822fa2
S
6965 /* If the bgp instance is being deleted or self peer is deleted
6966 * then do not create aggregate route
6967 */
892fedb6
DA
6968 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6969 || (bgp->peer_self == NULL))
9f822fa2
S
6970 return;
6971
6aabb15d
RZ
6972 /* Initialize and test routes for MED difference. */
6973 if (aggregate->match_med)
6974 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6975
4056a5f6
RZ
6976 /*
6977 * Reset aggregate count: we might've been called from route map
6978 * update so in that case we must retest all more specific routes.
6979 *
6980 * \see `bgp_route_map_process_update`.
6981 */
6982 aggregate->count = 0;
6983 aggregate->incomplete_origin_count = 0;
6984 aggregate->incomplete_origin_count = 0;
6985 aggregate->egp_origin_count = 0;
6986
d62a17ae 6987 /* ORIGIN attribute: If at least one route among routes that are
6988 aggregated has ORIGIN with the value INCOMPLETE, then the
6989 aggregated route must have the ORIGIN attribute with the value
6990 INCOMPLETE. Otherwise, if at least one route among routes that
6991 are aggregated has ORIGIN with the value EGP, then the aggregated
6992 route must have the origin attribute with the value EGP. In all
6993 other case the value of the ORIGIN attribute of the aggregated
6994 route is INTERNAL. */
6995 origin = BGP_ORIGIN_IGP;
718e3744 6996
d62a17ae 6997 table = bgp->rib[afi][safi];
718e3744 6998
d62a17ae 6999 top = bgp_node_get(table, p);
9bcb3eef
DS
7000 for (dest = bgp_node_get(table, p); dest;
7001 dest = bgp_route_next_until(dest, top)) {
7002 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7003
9bcb3eef 7004 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7005 continue;
d62a17ae 7006
a77e2f4b
S
7007 /* If suppress fib is enabled and route not installed
7008 * in FIB, skip the route
7009 */
7010 if (!bgp_check_advertise(bgp, dest))
7011 continue;
7012
c2ff8b3e 7013 match = 0;
d62a17ae 7014
9bcb3eef 7015 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7016 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7017 continue;
718e3744 7018
40381db7 7019 if (pi->attr->flag
c2ff8b3e
DS
7020 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7021 atomic_aggregate = 1;
d62a17ae 7022
40381db7 7023 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7024 continue;
d62a17ae 7025
f273fef1
DS
7026 /*
7027 * summary-only aggregate route suppress
7028 * aggregated route announcements.
6aabb15d
RZ
7029 *
7030 * MED matching:
7031 * Don't create summaries if MED didn't match
7032 * otherwise neither the specific routes and the
7033 * aggregation will be announced.
f273fef1 7034 */
6aabb15d
RZ
7035 if (aggregate->summary_only
7036 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7037 if (aggr_suppress_path(aggregate, pi))
7038 match++;
d62a17ae 7039 }
c2ff8b3e 7040
365ab2e7
RZ
7041 /*
7042 * Suppress more specific routes that match the route
7043 * map results.
7044 *
7045 * MED matching:
7046 * Don't suppress routes if MED matching is enabled and
7047 * it mismatched otherwise we might end up with no
7048 * routes for this path.
7049 */
7050 if (aggregate->suppress_map_name
7051 && AGGREGATE_MED_VALID(aggregate)
7052 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7053 if (aggr_suppress_path(aggregate, pi))
7054 match++;
d62a17ae 7055 }
c2ff8b3e
DS
7056
7057 aggregate->count++;
7058
f273fef1
DS
7059 /*
7060 * If at least one route among routes that are
7061 * aggregated has ORIGIN with the value INCOMPLETE,
7062 * then the aggregated route MUST have the ORIGIN
7063 * attribute with the value INCOMPLETE. Otherwise, if
7064 * at least one route among routes that are aggregated
7065 * has ORIGIN with the value EGP, then the aggregated
7066 * route MUST have the ORIGIN attribute with the value
7067 * EGP.
7068 */
fc968841
NT
7069 switch (pi->attr->origin) {
7070 case BGP_ORIGIN_INCOMPLETE:
7071 aggregate->incomplete_origin_count++;
7072 break;
7073 case BGP_ORIGIN_EGP:
7074 aggregate->egp_origin_count++;
7075 break;
7076 default:
7077 /*Do nothing.
7078 */
7079 break;
7080 }
c2ff8b3e
DS
7081
7082 if (!aggregate->as_set)
7083 continue;
7084
f273fef1
DS
7085 /*
7086 * as-set aggregate route generate origin, as path,
7087 * and community aggregation.
7088 */
fc968841
NT
7089 /* Compute aggregate route's as-path.
7090 */
ef51a7d8 7091 bgp_compute_aggregate_aspath_hash(aggregate,
7092 pi->attr->aspath);
c2ff8b3e 7093
fc968841
NT
7094 /* Compute aggregate route's community.
7095 */
7096 if (pi->attr->community)
21fec674 7097 bgp_compute_aggregate_community_hash(
fc968841
NT
7098 aggregate,
7099 pi->attr->community);
dd18c5a9 7100
fc968841
NT
7101 /* Compute aggregate route's extended community.
7102 */
7103 if (pi->attr->ecommunity)
4edd83f9 7104 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7105 aggregate,
7106 pi->attr->ecommunity);
7107
7108 /* Compute aggregate route's large community.
7109 */
7110 if (pi->attr->lcommunity)
f1eb1f05 7111 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7112 aggregate,
7113 pi->attr->lcommunity);
d62a17ae 7114 }
c2ff8b3e 7115 if (match)
9bcb3eef 7116 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7117 }
21fec674 7118 if (aggregate->as_set) {
ef51a7d8 7119 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7120 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7121 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7122 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7123 }
7124
f1eb1f05 7125
9bcb3eef 7126 bgp_dest_unlock_node(top);
718e3744 7127
718e3744 7128
fc968841
NT
7129 if (aggregate->incomplete_origin_count > 0)
7130 origin = BGP_ORIGIN_INCOMPLETE;
7131 else if (aggregate->egp_origin_count > 0)
7132 origin = BGP_ORIGIN_EGP;
d62a17ae 7133
229757f1
DA
7134 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7135 origin = aggregate->origin;
7136
fc968841
NT
7137 if (aggregate->as_set) {
7138 if (aggregate->aspath)
7139 /* Retrieve aggregate route's as-path.
7140 */
7141 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7142
fc968841
NT
7143 if (aggregate->community)
7144 /* Retrieve aggregate route's community.
7145 */
7146 community = community_dup(aggregate->community);
3da2cc32 7147
fc968841
NT
7148 if (aggregate->ecommunity)
7149 /* Retrieve aggregate route's ecommunity.
7150 */
7151 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7152
fc968841
NT
7153 if (aggregate->lcommunity)
7154 /* Retrieve aggregate route's lcommunity.
7155 */
7156 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7157 }
718e3744 7158
c701010e 7159 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7160 ecommunity, lcommunity, atomic_aggregate,
7161 aggregate);
718e3744 7162}
7163
5f040085
DS
7164void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7165 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7166{
7167 struct bgp_table *table;
9bcb3eef
DS
7168 struct bgp_dest *top;
7169 struct bgp_dest *dest;
40381db7 7170 struct bgp_path_info *pi;
3b7db173
DS
7171 unsigned long match;
7172
7173 table = bgp->rib[afi][safi];
7174
7175 /* If routes exists below this node, generate aggregate routes. */
7176 top = bgp_node_get(table, p);
9bcb3eef
DS
7177 for (dest = bgp_node_get(table, p); dest;
7178 dest = bgp_route_next_until(dest, top)) {
7179 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7180
9bcb3eef 7181 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7182 continue;
7183 match = 0;
7184
9bcb3eef 7185 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7186 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7187 continue;
7188
40381db7 7189 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7190 continue;
7191
6aabb15d
RZ
7192 if (aggregate->summary_only && pi->extra
7193 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7194 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7195 match++;
3b7db173 7196 }
3b7db173 7197
365ab2e7
RZ
7198 if (aggregate->suppress_map_name
7199 && AGGREGATE_MED_VALID(aggregate)
7200 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7201 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7202 match++;
3b7db173 7203 }
365ab2e7 7204
3b7db173 7205 aggregate->count--;
fc968841
NT
7206
7207 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7208 aggregate->incomplete_origin_count--;
7209 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7210 aggregate->egp_origin_count--;
7211
7212 if (aggregate->as_set) {
7213 /* Remove as-path from aggregate.
7214 */
ef51a7d8 7215 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7216 aggregate,
7217 pi->attr->aspath);
7218
7219 if (pi->attr->community)
7220 /* Remove community from aggregate.
7221 */
21fec674 7222 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7223 aggregate,
7224 pi->attr->community);
7225
7226 if (pi->attr->ecommunity)
7227 /* Remove ecommunity from aggregate.
7228 */
4edd83f9 7229 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7230 aggregate,
7231 pi->attr->ecommunity);
7232
7233 if (pi->attr->lcommunity)
7234 /* Remove lcommunity from aggregate.
7235 */
f1eb1f05 7236 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7237 aggregate,
7238 pi->attr->lcommunity);
7239 }
3b7db173
DS
7240 }
7241
7242 /* If this node was suppressed, process the change. */
7243 if (match)
9bcb3eef 7244 bgp_process(bgp, dest, afi, safi);
3b7db173 7245 }
f1eb1f05 7246 if (aggregate->as_set) {
ef51a7d8 7247 aspath_free(aggregate->aspath);
7248 aggregate->aspath = NULL;
21fec674 7249 if (aggregate->community)
7250 community_free(&aggregate->community);
4edd83f9 7251 if (aggregate->ecommunity)
7252 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7253 if (aggregate->lcommunity)
7254 lcommunity_free(&aggregate->lcommunity);
7255 }
7256
9bcb3eef 7257 bgp_dest_unlock_node(top);
3b7db173 7258}
718e3744 7259
5f040085
DS
7260static void bgp_add_route_to_aggregate(struct bgp *bgp,
7261 const struct prefix *aggr_p,
fc968841
NT
7262 struct bgp_path_info *pinew, afi_t afi,
7263 safi_t safi,
7264 struct bgp_aggregate *aggregate)
7265{
7266 uint8_t origin;
7267 struct aspath *aspath = NULL;
7268 uint8_t atomic_aggregate = 0;
7269 struct community *community = NULL;
7270 struct ecommunity *ecommunity = NULL;
7271 struct lcommunity *lcommunity = NULL;
7272
a4559740 7273 /* If the bgp instance is being deleted or self peer is deleted
7274 * then do not create aggregate route
7275 */
7276 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7277 || (bgp->peer_self == NULL))
7278 return;
7279
fc968841
NT
7280 /* ORIGIN attribute: If at least one route among routes that are
7281 * aggregated has ORIGIN with the value INCOMPLETE, then the
7282 * aggregated route must have the ORIGIN attribute with the value
7283 * INCOMPLETE. Otherwise, if at least one route among routes that
7284 * are aggregated has ORIGIN with the value EGP, then the aggregated
7285 * route must have the origin attribute with the value EGP. In all
7286 * other case the value of the ORIGIN attribute of the aggregated
7287 * route is INTERNAL.
7288 */
7289 origin = BGP_ORIGIN_IGP;
7290
7291 aggregate->count++;
7292
6aabb15d
RZ
7293 /*
7294 * This must be called before `summary` check to avoid
7295 * "suppressing" twice.
7296 */
7297 if (aggregate->match_med)
7298 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7299 pinew, true);
7300
7301 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7302 aggr_suppress_path(aggregate, pinew);
fc968841 7303
365ab2e7
RZ
7304 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7305 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7306 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7307
7308 switch (pinew->attr->origin) {
7309 case BGP_ORIGIN_INCOMPLETE:
7310 aggregate->incomplete_origin_count++;
7311 break;
7312 case BGP_ORIGIN_EGP:
7313 aggregate->egp_origin_count++;
7314 break;
7315 default:
7316 /* Do nothing.
7317 */
7318 break;
7319 }
7320
7321 if (aggregate->incomplete_origin_count > 0)
7322 origin = BGP_ORIGIN_INCOMPLETE;
7323 else if (aggregate->egp_origin_count > 0)
7324 origin = BGP_ORIGIN_EGP;
7325
229757f1
DA
7326 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7327 origin = aggregate->origin;
7328
fc968841
NT
7329 if (aggregate->as_set) {
7330 /* Compute aggregate route's as-path.
7331 */
7332 bgp_compute_aggregate_aspath(aggregate,
7333 pinew->attr->aspath);
7334
7335 /* Compute aggregate route's community.
7336 */
7337 if (pinew->attr->community)
7338 bgp_compute_aggregate_community(
7339 aggregate,
7340 pinew->attr->community);
7341
7342 /* Compute aggregate route's extended community.
7343 */
7344 if (pinew->attr->ecommunity)
7345 bgp_compute_aggregate_ecommunity(
7346 aggregate,
7347 pinew->attr->ecommunity);
7348
7349 /* Compute aggregate route's large community.
7350 */
7351 if (pinew->attr->lcommunity)
7352 bgp_compute_aggregate_lcommunity(
7353 aggregate,
7354 pinew->attr->lcommunity);
7355
7356 /* Retrieve aggregate route's as-path.
7357 */
7358 if (aggregate->aspath)
7359 aspath = aspath_dup(aggregate->aspath);
7360
7361 /* Retrieve aggregate route's community.
7362 */
7363 if (aggregate->community)
7364 community = community_dup(aggregate->community);
7365
7366 /* Retrieve aggregate route's ecommunity.
7367 */
7368 if (aggregate->ecommunity)
7369 ecommunity = ecommunity_dup(aggregate->ecommunity);
7370
7371 /* Retrieve aggregate route's lcommunity.
7372 */
7373 if (aggregate->lcommunity)
7374 lcommunity = lcommunity_dup(aggregate->lcommunity);
7375 }
7376
7377 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7378 aspath, community, ecommunity,
7379 lcommunity, atomic_aggregate, aggregate);
7380}
7381
7382static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7383 safi_t safi,
7384 struct bgp_path_info *pi,
7385 struct bgp_aggregate *aggregate,
5f040085 7386 const struct prefix *aggr_p)
fc968841
NT
7387{
7388 uint8_t origin;
7389 struct aspath *aspath = NULL;
7390 uint8_t atomic_aggregate = 0;
7391 struct community *community = NULL;
7392 struct ecommunity *ecommunity = NULL;
7393 struct lcommunity *lcommunity = NULL;
7394 unsigned long match = 0;
7395
a4559740 7396 /* If the bgp instance is being deleted or self peer is deleted
7397 * then do not create aggregate route
7398 */
7399 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7400 || (bgp->peer_self == NULL))
7401 return;
7402
fc968841
NT
7403 if (BGP_PATH_HOLDDOWN(pi))
7404 return;
7405
7406 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7407 return;
7408
4056a5f6
RZ
7409 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7410 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7411 match++;
fc968841 7412
365ab2e7 7413 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7414 && aggr_suppress_map_test(bgp, aggregate, pi))
7415 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7416 match++;
fc968841 7417
6aabb15d 7418 /*
365ab2e7 7419 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7420 * "unsuppressing" twice.
7421 */
7422 if (aggregate->match_med)
7423 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7424 true);
7425
fc968841
NT
7426 if (aggregate->count > 0)
7427 aggregate->count--;
7428
7429 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7430 aggregate->incomplete_origin_count--;
7431 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7432 aggregate->egp_origin_count--;
7433
7434 if (aggregate->as_set) {
7435 /* Remove as-path from aggregate.
7436 */
7437 bgp_remove_aspath_from_aggregate(aggregate,
7438 pi->attr->aspath);
7439
7440 if (pi->attr->community)
7441 /* Remove community from aggregate.
7442 */
7443 bgp_remove_community_from_aggregate(
7444 aggregate,
7445 pi->attr->community);
7446
7447 if (pi->attr->ecommunity)
7448 /* Remove ecommunity from aggregate.
7449 */
7450 bgp_remove_ecommunity_from_aggregate(
7451 aggregate,
7452 pi->attr->ecommunity);
7453
7454 if (pi->attr->lcommunity)
7455 /* Remove lcommunity from aggregate.
7456 */
7457 bgp_remove_lcommunity_from_aggregate(
7458 aggregate,
7459 pi->attr->lcommunity);
7460 }
7461
7462 /* If this node was suppressed, process the change. */
7463 if (match)
7464 bgp_process(bgp, pi->net, afi, safi);
7465
7466 origin = BGP_ORIGIN_IGP;
7467 if (aggregate->incomplete_origin_count > 0)
7468 origin = BGP_ORIGIN_INCOMPLETE;
7469 else if (aggregate->egp_origin_count > 0)
7470 origin = BGP_ORIGIN_EGP;
7471
229757f1
DA
7472 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7473 origin = aggregate->origin;
7474
fc968841
NT
7475 if (aggregate->as_set) {
7476 /* Retrieve aggregate route's as-path.
7477 */
7478 if (aggregate->aspath)
7479 aspath = aspath_dup(aggregate->aspath);
7480
7481 /* Retrieve aggregate route's community.
7482 */
7483 if (aggregate->community)
7484 community = community_dup(aggregate->community);
7485
7486 /* Retrieve aggregate route's ecommunity.
7487 */
7488 if (aggregate->ecommunity)
7489 ecommunity = ecommunity_dup(aggregate->ecommunity);
7490
7491 /* Retrieve aggregate route's lcommunity.
7492 */
7493 if (aggregate->lcommunity)
7494 lcommunity = lcommunity_dup(aggregate->lcommunity);
7495 }
7496
7497 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7498 aspath, community, ecommunity,
7499 lcommunity, atomic_aggregate, aggregate);
7500}
7501
5a1ae2c2 7502void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7503 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7504{
9bcb3eef
DS
7505 struct bgp_dest *child;
7506 struct bgp_dest *dest;
d62a17ae 7507 struct bgp_aggregate *aggregate;
7508 struct bgp_table *table;
718e3744 7509
d62a17ae 7510 table = bgp->aggregate[afi][safi];
f018db83 7511
d62a17ae 7512 /* No aggregates configured. */
7513 if (bgp_table_top_nolock(table) == NULL)
7514 return;
f018db83 7515
d62a17ae 7516 if (p->prefixlen == 0)
7517 return;
718e3744 7518
40381db7 7519 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7520 return;
718e3744 7521
a77e2f4b
S
7522 /* If suppress fib is enabled and route not installed
7523 * in FIB, do not update the aggregate route
7524 */
7525 if (!bgp_check_advertise(bgp, pi->net))
7526 return;
7527
d62a17ae 7528 child = bgp_node_get(table, p);
718e3744 7529
d62a17ae 7530 /* Aggregate address configuration check. */
9bcb3eef
DS
7531 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7532 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7533
9bcb3eef
DS
7534 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7535 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7536 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7537 aggregate);
d62a17ae 7538 }
b1e62edd 7539 }
9bcb3eef 7540 bgp_dest_unlock_node(child);
718e3744 7541}
7542
5a1ae2c2 7543void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7544 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7545{
9bcb3eef
DS
7546 struct bgp_dest *child;
7547 struct bgp_dest *dest;
d62a17ae 7548 struct bgp_aggregate *aggregate;
7549 struct bgp_table *table;
718e3744 7550
d62a17ae 7551 table = bgp->aggregate[afi][safi];
718e3744 7552
d62a17ae 7553 /* No aggregates configured. */
7554 if (bgp_table_top_nolock(table) == NULL)
7555 return;
718e3744 7556
d62a17ae 7557 if (p->prefixlen == 0)
7558 return;
718e3744 7559
d62a17ae 7560 child = bgp_node_get(table, p);
718e3744 7561
d62a17ae 7562 /* Aggregate address configuration check. */
9bcb3eef
DS
7563 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7564 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7565
9bcb3eef
DS
7566 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7567 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7568 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7569 aggregate, dest_p);
d62a17ae 7570 }
b1e62edd 7571 }
9bcb3eef 7572 bgp_dest_unlock_node(child);
d62a17ae 7573}
718e3744 7574
718e3744 7575/* Aggregate route attribute. */
7576#define AGGREGATE_SUMMARY_ONLY 1
7577#define AGGREGATE_AS_SET 1
fb29348a 7578#define AGGREGATE_AS_UNSET 0
718e3744 7579
229757f1
DA
7580static const char *bgp_origin2str(uint8_t origin)
7581{
7582 switch (origin) {
7583 case BGP_ORIGIN_IGP:
7584 return "igp";
7585 case BGP_ORIGIN_EGP:
7586 return "egp";
7587 case BGP_ORIGIN_INCOMPLETE:
7588 return "incomplete";
7589 }
7590 return "n/a";
7591}
7592
fdeb5a81 7593static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7594{
7595 switch (v_state) {
fdeb5a81
DS
7596 case RPKI_NOT_BEING_USED:
7597 return "not used";
7598 case RPKI_VALID:
b5b99af8 7599 return "valid";
fdeb5a81 7600 case RPKI_NOTFOUND:
b5b99af8 7601 return "not found";
fdeb5a81 7602 case RPKI_INVALID:
b5b99af8 7603 return "invalid";
b5b99af8 7604 }
fdeb5a81
DS
7605
7606 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7607 return "ERROR";
7608}
7609
37a87b8f
CS
7610int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7611 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7612{
9bcb3eef 7613 struct bgp_dest *dest;
d62a17ae 7614 struct bgp_aggregate *aggregate;
718e3744 7615
a4559740 7616 /* If the bgp instance is being deleted or self peer is deleted
7617 * then do not create aggregate route
7618 */
7619 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7620 || (bgp->peer_self == NULL))
7621 return 0;
7622
37a87b8f 7623 apply_mask(prefix);
d62a17ae 7624 /* Old configuration check. */
37a87b8f 7625 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7626 if (!dest) {
37a87b8f
CS
7627 snprintf(errmsg, errmsg_len,
7628 "There is no aggregate-address configuration.\n");
7629 return -1;
d62a17ae 7630 }
f6269b4f 7631
9bcb3eef 7632 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7633 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7634 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7635 0, aggregate);
d62a17ae 7636
7637 /* Unlock aggregate address configuration. */
9bcb3eef 7638 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7639
7640 if (aggregate->community)
7641 community_free(&aggregate->community);
7642
7643 if (aggregate->community_hash) {
7644 /* Delete all communities in the hash.
7645 */
7646 hash_clean(aggregate->community_hash,
7647 bgp_aggr_community_remove);
7648 /* Free up the community_hash.
7649 */
7650 hash_free(aggregate->community_hash);
7651 }
7652
7653 if (aggregate->ecommunity)
7654 ecommunity_free(&aggregate->ecommunity);
7655
7656 if (aggregate->ecommunity_hash) {
7657 /* Delete all ecommunities in the hash.
7658 */
7659 hash_clean(aggregate->ecommunity_hash,
7660 bgp_aggr_ecommunity_remove);
7661 /* Free up the ecommunity_hash.
7662 */
7663 hash_free(aggregate->ecommunity_hash);
7664 }
7665
7666 if (aggregate->lcommunity)
7667 lcommunity_free(&aggregate->lcommunity);
7668
7669 if (aggregate->lcommunity_hash) {
7670 /* Delete all lcommunities in the hash.
7671 */
7672 hash_clean(aggregate->lcommunity_hash,
7673 bgp_aggr_lcommunity_remove);
7674 /* Free up the lcommunity_hash.
7675 */
7676 hash_free(aggregate->lcommunity_hash);
7677 }
7678
7679 if (aggregate->aspath)
7680 aspath_free(aggregate->aspath);
7681
7682 if (aggregate->aspath_hash) {
7683 /* Delete all as-paths in the hash.
7684 */
7685 hash_clean(aggregate->aspath_hash,
7686 bgp_aggr_aspath_remove);
7687 /* Free up the aspath_hash.
7688 */
7689 hash_free(aggregate->aspath_hash);
7690 }
7691
d62a17ae 7692 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7693 bgp_dest_unlock_node(dest);
7694 bgp_dest_unlock_node(dest);
d62a17ae 7695
37a87b8f 7696 return 0;
d62a17ae 7697}
7698
37a87b8f
CS
7699int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7700 safi_t safi, const char *rmap, uint8_t summary_only,
7701 uint8_t as_set, uint8_t origin, bool match_med,
7702 const char *suppress_map,
7703 char *errmsg, size_t errmsg_len)
d62a17ae 7704{
d62a17ae 7705 int ret;
9bcb3eef 7706 struct bgp_dest *dest;
d62a17ae 7707 struct bgp_aggregate *aggregate;
fb29348a 7708 uint8_t as_set_new = as_set;
37a87b8f 7709 char buf[PREFIX2STR_BUFFER];
d62a17ae 7710
365ab2e7 7711 if (suppress_map && summary_only) {
37a87b8f 7712 snprintf(errmsg, errmsg_len,
365ab2e7 7713 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7714 return -1;
365ab2e7
RZ
7715 }
7716
37a87b8f 7717 apply_mask(prefix);
d62a17ae 7718
37a87b8f
CS
7719 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7720 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7721 snprintf(
7722 errmsg, errmsg_len,
7723 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7724 prefix2str(prefix, buf, PREFIX_STRLEN));
7725 return -1;
3624ac81
DS
7726 }
7727
d62a17ae 7728 /* Old configuration check. */
37a87b8f 7729 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7730 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7731
20894f50 7732 if (aggregate) {
37a87b8f
CS
7733 snprintf(errmsg, errmsg_len,
7734 "There is already same aggregate network.\n");
d62a17ae 7735 /* try to remove the old entry */
37a87b8f
CS
7736 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7737 errmsg_len);
d62a17ae 7738 if (ret) {
37a87b8f
CS
7739 snprintf(errmsg, errmsg_len,
7740 "Error deleting aggregate.\n");
9bcb3eef 7741 bgp_dest_unlock_node(dest);
37a87b8f 7742 return -1;
d62a17ae 7743 }
7744 }
718e3744 7745
d62a17ae 7746 /* Make aggregate address structure. */
7747 aggregate = bgp_aggregate_new();
7748 aggregate->summary_only = summary_only;
6aabb15d 7749 aggregate->match_med = match_med;
fb29348a
DA
7750
7751 /* Network operators MUST NOT locally generate any new
7752 * announcements containing AS_SET or AS_CONFED_SET. If they have
7753 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7754 * SHOULD withdraw those routes and re-announce routes for the
7755 * aggregate or component prefixes (i.e., the more-specific routes
7756 * subsumed by the previously aggregated route) without AS_SET
7757 * or AS_CONFED_SET in the updates.
7758 */
7f972cd8 7759 if (bgp->reject_as_sets) {
fb29348a
DA
7760 if (as_set == AGGREGATE_AS_SET) {
7761 as_set_new = AGGREGATE_AS_UNSET;
7762 zlog_warn(
63efca0e 7763 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7764 __func__);
37a87b8f
CS
7765 snprintf(
7766 errmsg, errmsg_len,
fb29348a
DA
7767 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7768 }
7769 }
7770
7771 aggregate->as_set = as_set_new;
d62a17ae 7772 aggregate->safi = safi;
229757f1
DA
7773 /* Override ORIGIN attribute if defined.
7774 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7775 * to IGP which is not what rfc4271 says.
7776 * This enables the same behavior, optionally.
7777 */
7778 aggregate->origin = origin;
20894f50
DA
7779
7780 if (rmap) {
7781 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7782 route_map_counter_decrement(aggregate->rmap.map);
7783 aggregate->rmap.name =
7784 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7785 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7786 route_map_counter_increment(aggregate->rmap.map);
7787 }
365ab2e7
RZ
7788
7789 if (suppress_map) {
7790 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7791 route_map_counter_decrement(aggregate->suppress_map);
7792
7793 aggregate->suppress_map_name =
7794 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7795 aggregate->suppress_map =
7796 route_map_lookup_by_name(aggregate->suppress_map_name);
7797 route_map_counter_increment(aggregate->suppress_map);
7798 }
7799
9bcb3eef 7800 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7801
d62a17ae 7802 /* Aggregate address insert into BGP routing table. */
37a87b8f 7803 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7804
37a87b8f 7805 return 0;
718e3744 7806}
7807
37a87b8f
CS
7808DEFPY_YANG(
7809 aggregate_addressv4, aggregate_addressv4_cmd,
faff43d0 7810 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
37a87b8f
CS
7811 "as-set$as_set_s"
7812 "|summary-only$summary_only"
7813 "|route-map WORD$rmap_name"
7814 "|origin <egp|igp|incomplete>$origin_s"
7815 "|matching-MED-only$match_med"
90e21f35 7816 "|suppress-map WORD$suppress_map"
faff43d0 7817 "}]",
37a87b8f
CS
7818 NO_STR
7819 "Configure BGP aggregate entries\n"
7820 "Aggregate prefix\n"
7821 "Aggregate address\n"
7822 "Aggregate mask\n"
7823 "Generate AS set path information\n"
7824 "Filter more specific routes from updates\n"
7825 "Apply route map to aggregate network\n"
7826 "Route map name\n"
7827 "BGP origin code\n"
7828 "Remote EGP\n"
7829 "Local IGP\n"
7830 "Unknown heritage\n"
7831 "Only aggregate routes with matching MED\n"
90e21f35
CS
7832 "Suppress the selected more specific routes\n"
7833 "Route map with the route selectors\n")
37a87b8f
CS
7834{
7835 char base_xpath[XPATH_MAXLEN];
554b3b10 7836 safi_t safi = bgp_node_safi(vty);
554b3b10 7837 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7838
554b3b10 7839 if (addr_str) {
7533cad7
QY
7840 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
7841 sizeof(prefix_buf))
554b3b10
RZ
7842 == 0) {
7843 vty_out(vty, "%% Inconsistent address and mask\n");
7844 return CMD_WARNING_CONFIG_FAILED;
7845 }
37a87b8f
CS
7846 } else {
7847 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7848 }
7849
37a87b8f
CS
7850 if (!no && origin_s)
7851 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7852
7853 if (!no && as_set_s)
7854 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7855 else
7856 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7857
7858 if (!no && summary_only)
7859 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7860 "true");
7861 else
7862 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7863 "false");
7864
fa423774
CS
7865 if (!no && match_med)
7866 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7867 else
7868 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7869 "false");
7870
37a87b8f
CS
7871 if (rmap_name)
7872 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7873 rmap_name);
7874 else
7875 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7876 NB_OP_DESTROY, NULL);
7877
90e21f35
CS
7878 if (suppress_map)
7879 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7880 suppress_map);
7881 else
7882 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7883 NULL);
7884
37a87b8f
CS
7885 snprintf(
7886 base_xpath, sizeof(base_xpath),
7887 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7888 yang_afi_safi_value2identity(AFI_IP, safi),
7889 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7890
554b3b10 7891 if (no)
37a87b8f
CS
7892 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7893 else
7894 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7895
7896 return nb_cli_apply_changes(vty, base_xpath);
7897}
7898
7899DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
faff43d0 7900 "[no] aggregate-address X:X::X:X/M$prefix [{"
37a87b8f
CS
7901 "as-set$as_set_s"
7902 "|summary-only$summary_only"
7903 "|route-map WORD$rmap_name"
7904 "|origin <egp|igp|incomplete>$origin_s"
7905 "|matching-MED-only$match_med"
90e21f35 7906 "|suppress-map WORD$suppress_map"
faff43d0 7907 "}]",
37a87b8f
CS
7908 NO_STR
7909 "Configure BGP aggregate entries\n"
7910 "Aggregate prefix\n"
7911 "Generate AS set path information\n"
7912 "Filter more specific routes from updates\n"
7913 "Apply route map to aggregate network\n"
7914 "Route map name\n"
7915 "BGP origin code\n"
7916 "Remote EGP\n"
7917 "Local IGP\n"
7918 "Unknown heritage\n"
7919 "Only aggregate routes with matching MED\n"
7920 "Suppress the selected more specific routes\n"
90e21f35 7921 "Route map with the route selectors\n")
37a87b8f
CS
7922{
7923 char base_xpath[XPATH_MAXLEN];
7924 safi_t safi = bgp_node_safi(vty);
7925
7926 if (!no && origin_s)
7927 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7928
7929 if (!no && as_set_s)
7930 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7931 else
7932 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7933
7934 if (!no && summary_only)
7935 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7936 "true");
7937 else
7938 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7939 "false");
7940
fa423774
CS
7941 if (!no && match_med)
7942 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7943 else
7944 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7945 "false");
7946
37a87b8f
CS
7947 if (rmap_name)
7948 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7949 rmap_name);
7950
90e21f35
CS
7951 if (suppress_map)
7952 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7953 suppress_map);
7954 else
7955 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7956 NULL);
7957
37a87b8f
CS
7958 snprintf(
7959 base_xpath, sizeof(base_xpath),
7960 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7961 yang_afi_safi_value2identity(AFI_IP6, safi),
7962 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7963
554b3b10 7964 if (no)
37a87b8f
CS
7965 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7966 else
7967 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7968
37a87b8f
CS
7969 return nb_cli_apply_changes(vty, base_xpath);
7970}
7971
7972void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7973 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7974{
7975 uint8_t origin;
7976
7977 vty_out(vty, " aggregate-address %s",
7978 yang_dnode_get_string(dnode, "./prefix"));
7979
7980 if (yang_dnode_get_bool(dnode, "./as-set"))
7981 vty_out(vty, " as-set");
7982
7983 if (yang_dnode_get_bool(dnode, "./summary-only"))
7984 vty_out(vty, " summary-only");
7985
7986 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7987 vty_out(vty, " route-map %s",
7988 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7989
7990 origin = yang_dnode_get_enum(dnode, "./origin");
7991 if (origin != BGP_ORIGIN_UNSPECIFIED)
7992 vty_out(vty, " origin %s", bgp_origin2str(origin));
7993
fa423774
CS
7994 if (yang_dnode_get_bool(dnode, "./match-med"))
7995 vty_out(vty, " matching-MED-only");
7996
37a87b8f 7997 vty_out(vty, "\n");
718e3744 7998}
7999
718e3744 8000/* Redistribute route treatment. */
d62a17ae 8001void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
8002 const union g_addr *nexthop, ifindex_t ifindex,
8003 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
8004 uint8_t type, unsigned short instance,
8005 route_tag_t tag)
d62a17ae 8006{
4b7e6066 8007 struct bgp_path_info *new;
40381db7
DS
8008 struct bgp_path_info *bpi;
8009 struct bgp_path_info rmap_path;
9bcb3eef 8010 struct bgp_dest *bn;
d62a17ae 8011 struct attr attr;
8012 struct attr *new_attr;
8013 afi_t afi;
b68885f9 8014 route_map_result_t ret;
d62a17ae 8015 struct bgp_redist *red;
8016
8017 /* Make default attribute. */
8018 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8019 /*
8020 * This must not be NULL to satisfy Coverity SA
8021 */
8022 assert(attr.aspath);
9de1f7ff 8023
a4d82a8a 8024 switch (nhtype) {
9de1f7ff
DS
8025 case NEXTHOP_TYPE_IFINDEX:
8026 break;
8027 case NEXTHOP_TYPE_IPV4:
8028 case NEXTHOP_TYPE_IPV4_IFINDEX:
8029 attr.nexthop = nexthop->ipv4;
8030 break;
8031 case NEXTHOP_TYPE_IPV6:
8032 case NEXTHOP_TYPE_IPV6_IFINDEX:
8033 attr.mp_nexthop_global = nexthop->ipv6;
8034 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8035 break;
8036 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8037 switch (p->family) {
8038 case AF_INET:
9de1f7ff 8039 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8040 break;
8041 case AF_INET6:
9de1f7ff
DS
8042 memset(&attr.mp_nexthop_global, 0,
8043 sizeof(attr.mp_nexthop_global));
74489921 8044 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8045 break;
74489921 8046 }
9de1f7ff 8047 break;
d62a17ae 8048 }
74489921 8049 attr.nh_ifindex = ifindex;
f04a80a5 8050
d62a17ae 8051 attr.med = metric;
8052 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8053 attr.tag = tag;
718e3744 8054
d62a17ae 8055 afi = family2afi(p->family);
6aeb9e78 8056
d62a17ae 8057 red = bgp_redist_lookup(bgp, afi, type, instance);
8058 if (red) {
8059 struct attr attr_new;
718e3744 8060
d62a17ae 8061 /* Copy attribute for modification. */
6f4f49b2 8062 attr_new = attr;
718e3744 8063
d62a17ae 8064 if (red->redist_metric_flag)
8065 attr_new.med = red->redist_metric;
718e3744 8066
d62a17ae 8067 /* Apply route-map. */
8068 if (red->rmap.name) {
40381db7
DS
8069 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8070 rmap_path.peer = bgp->peer_self;
8071 rmap_path.attr = &attr_new;
718e3744 8072
d62a17ae 8073 SET_FLAG(bgp->peer_self->rmap_type,
8074 PEER_RMAP_TYPE_REDISTRIBUTE);
8075
1782514f 8076 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8077
8078 bgp->peer_self->rmap_type = 0;
8079
8080 if (ret == RMAP_DENYMATCH) {
8081 /* Free uninterned attribute. */
8082 bgp_attr_flush(&attr_new);
8083
8084 /* Unintern original. */
8085 aspath_unintern(&attr.aspath);
8086 bgp_redistribute_delete(bgp, p, type, instance);
8087 return;
8088 }
8089 }
8090
637e5ba4 8091 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8092 bgp_attr_add_gshut_community(&attr_new);
8093
d62a17ae 8094 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8095 SAFI_UNICAST, p, NULL);
8096
8097 new_attr = bgp_attr_intern(&attr_new);
8098
9bcb3eef 8099 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8100 if (bpi->peer == bgp->peer_self
8101 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8102 break;
8103
40381db7 8104 if (bpi) {
d62a17ae 8105 /* Ensure the (source route) type is updated. */
40381db7
DS
8106 bpi->type = type;
8107 if (attrhash_cmp(bpi->attr, new_attr)
8108 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8109 bgp_attr_unintern(&new_attr);
8110 aspath_unintern(&attr.aspath);
9bcb3eef 8111 bgp_dest_unlock_node(bn);
d62a17ae 8112 return;
8113 } else {
8114 /* The attribute is changed. */
40381db7 8115 bgp_path_info_set_flag(bn, bpi,
18ee8310 8116 BGP_PATH_ATTR_CHANGED);
d62a17ae 8117
8118 /* Rewrite BGP route information. */
40381db7
DS
8119 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8120 bgp_path_info_restore(bn, bpi);
d62a17ae 8121 else
40381db7
DS
8122 bgp_aggregate_decrement(
8123 bgp, p, bpi, afi, SAFI_UNICAST);
8124 bgp_attr_unintern(&bpi->attr);
8125 bpi->attr = new_attr;
8126 bpi->uptime = bgp_clock();
d62a17ae 8127
8128 /* Process change. */
40381db7 8129 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8130 SAFI_UNICAST);
8131 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8132 bgp_dest_unlock_node(bn);
d62a17ae 8133 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8134
8135 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8136 || (bgp->inst_type
8137 == BGP_INSTANCE_TYPE_DEFAULT)) {
8138
8139 vpn_leak_from_vrf_update(
40381db7 8140 bgp_get_default(), bgp, bpi);
ddb5b488 8141 }
d62a17ae 8142 return;
8143 }
8144 }
8145
8146 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8147 bgp->peer_self, new_attr, bn);
1defdda8 8148 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8149
8150 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8151 bgp_path_info_add(bn, new);
9bcb3eef 8152 bgp_dest_unlock_node(bn);
d62a17ae 8153 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8154
8155 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8156 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8157
8158 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8159 }
d62a17ae 8160 }
8161
8162 /* Unintern original. */
8163 aspath_unintern(&attr.aspath);
718e3744 8164}
8165
d7c0a89a
QY
8166void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8167 unsigned short instance)
718e3744 8168{
d62a17ae 8169 afi_t afi;
9bcb3eef 8170 struct bgp_dest *dest;
40381db7 8171 struct bgp_path_info *pi;
d62a17ae 8172 struct bgp_redist *red;
718e3744 8173
d62a17ae 8174 afi = family2afi(p->family);
718e3744 8175
d62a17ae 8176 red = bgp_redist_lookup(bgp, afi, type, instance);
8177 if (red) {
9bcb3eef
DS
8178 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8179 SAFI_UNICAST, p, NULL);
d62a17ae 8180
9bcb3eef 8181 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8182 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8183 break;
8184
40381db7 8185 if (pi) {
ddb5b488
PZ
8186 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8187 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8188
8189 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8190 bgp, pi);
ddb5b488 8191 }
40381db7 8192 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8193 bgp_path_info_delete(dest, pi);
8194 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8195 }
9bcb3eef 8196 bgp_dest_unlock_node(dest);
d62a17ae 8197 }
8198}
8199
8200/* Withdraw specified route type's route. */
8201void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8202 unsigned short instance)
d62a17ae 8203{
9bcb3eef 8204 struct bgp_dest *dest;
40381db7 8205 struct bgp_path_info *pi;
d62a17ae 8206 struct bgp_table *table;
8207
8208 table = bgp->rib[afi][SAFI_UNICAST];
8209
9bcb3eef
DS
8210 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8211 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8212 if (pi->peer == bgp->peer_self && pi->type == type
8213 && pi->instance == instance)
d62a17ae 8214 break;
8215
40381db7 8216 if (pi) {
ddb5b488
PZ
8217 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8218 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8219
8220 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8221 bgp, pi);
ddb5b488 8222 }
9bcb3eef 8223 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8224 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8225 bgp_path_info_delete(dest, pi);
8226 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8227 }
718e3744 8228 }
718e3744 8229}
6b0655a2 8230
718e3744 8231/* Static function to display route. */
7d3cae70
DA
8232static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8233 struct vty *vty, json_object *json, bool wide)
718e3744 8234{
be054588 8235 int len = 0;
d62a17ae 8236 char buf[BUFSIZ];
50e05855 8237 char buf2[BUFSIZ];
718e3744 8238
d62a17ae 8239 if (p->family == AF_INET) {
c6462ff4 8240 if (!json) {
8228a9a7 8241 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8242 } else {
8243 json_object_string_add(json, "prefix",
8244 inet_ntop(p->family,
8245 &p->u.prefix, buf,
8246 BUFSIZ));
8247 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8248 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8249 json_object_string_add(json, "network", buf2);
7d3cae70 8250 json_object_int_add(json, "version", dest->version);
c6462ff4 8251 }
d62a17ae 8252 } else if (p->family == AF_ETHERNET) {
8228a9a7 8253 len = vty_out(vty, "%pFX", p);
b03b8898 8254 } else if (p->family == AF_EVPN) {
57f7feb6 8255 if (!json)
2dbe669b 8256 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8257 else
60466a63 8258 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8259 } else if (p->family == AF_FLOWSPEC) {
8260 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8261 json ?
8262 NLRI_STRING_FORMAT_JSON_SIMPLE :
8263 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8264 } else {
c6462ff4 8265 if (!json)
8228a9a7 8266 len = vty_out(vty, "%pFX", p);
50e05855
AD
8267 else {
8268 json_object_string_add(json, "prefix",
8269 inet_ntop(p->family,
8270 &p->u.prefix, buf,
8271 BUFSIZ));
8272 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8273 prefix2str(p, buf2, PREFIX_STRLEN);
8274 json_object_string_add(json, "network", buf2);
7d3cae70 8275 json_object_int_add(json, "version", dest->version);
37d4e0df 8276 }
9c92b5f7 8277 }
d62a17ae 8278
9c92b5f7 8279 if (!json) {
ae248832 8280 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8281 if (len < 1)
8282 vty_out(vty, "\n%*s", 20, " ");
8283 else
8284 vty_out(vty, "%*s", len, " ");
8285 }
718e3744 8286}
8287
d62a17ae 8288enum bgp_display_type {
8289 normal_list,
718e3744 8290};
8291
bbb46eb5
DA
8292static const char *
8293bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8294{
8295 switch (reason) {
8296 case bgp_path_selection_none:
8297 return "Nothing to Select";
8298 case bgp_path_selection_first:
8299 return "First path received";
8300 case bgp_path_selection_evpn_sticky_mac:
8301 return "EVPN Sticky Mac";
8302 case bgp_path_selection_evpn_seq:
8303 return "EVPN sequence number";
8304 case bgp_path_selection_evpn_lower_ip:
8305 return "EVPN lower IP";
8306 case bgp_path_selection_evpn_local_path:
8307 return "EVPN local ES path";
8308 case bgp_path_selection_evpn_non_proxy:
8309 return "EVPN non proxy";
8310 case bgp_path_selection_weight:
8311 return "Weight";
8312 case bgp_path_selection_local_pref:
8313 return "Local Pref";
8314 case bgp_path_selection_local_route:
8315 return "Local Route";
8316 case bgp_path_selection_confed_as_path:
8317 return "Confederation based AS Path";
8318 case bgp_path_selection_as_path:
8319 return "AS Path";
8320 case bgp_path_selection_origin:
8321 return "Origin";
8322 case bgp_path_selection_med:
8323 return "MED";
8324 case bgp_path_selection_peer:
8325 return "Peer Type";
8326 case bgp_path_selection_confed:
8327 return "Confed Peer Type";
8328 case bgp_path_selection_igp_metric:
8329 return "IGP Metric";
8330 case bgp_path_selection_older:
8331 return "Older Path";
8332 case bgp_path_selection_router_id:
8333 return "Router ID";
8334 case bgp_path_selection_cluster_length:
bcab253c 8335 return "Cluster length";
bbb46eb5
DA
8336 case bgp_path_selection_stale:
8337 return "Path Staleness";
8338 case bgp_path_selection_local_configured:
8339 return "Locally configured route";
8340 case bgp_path_selection_neighbor_ip:
8341 return "Neighbor IP";
8342 case bgp_path_selection_default:
8343 return "Nothing left to compare";
8344 }
8345 return "Invalid (internal error)";
8346}
8347
18ee8310 8348/* Print the short form route status for a bgp_path_info */
4b7e6066 8349static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8350 struct bgp_path_info *path,
82c298be 8351 const struct prefix *p,
d62a17ae 8352 json_object *json_path)
718e3744 8353{
82c298be
DA
8354 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8355
d62a17ae 8356 if (json_path) {
b05a1c8b 8357
d62a17ae 8358 /* Route status display. */
9b6d8fcf 8359 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8360 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8361
9b6d8fcf 8362 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8363 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8364
4056a5f6 8365 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8366 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8367
9b6d8fcf
DS
8368 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8369 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8370 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8371
d62a17ae 8372 /* Selected */
9b6d8fcf 8373 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8374 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8375
9b6d8fcf 8376 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8377 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8378
bbb46eb5 8379 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8380 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8381 json_object_string_add(json_path, "selectionReason",
8382 bgp_path_selection_reason2str(
8383 path->net->reason));
8384 }
b05a1c8b 8385
9b6d8fcf 8386 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8387 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8388
d62a17ae 8389 /* Internal route. */
9b6d8fcf
DS
8390 if ((path->peer->as)
8391 && (path->peer->as == path->peer->local_as))
d62a17ae 8392 json_object_string_add(json_path, "pathFrom",
8393 "internal");
8394 else
8395 json_object_string_add(json_path, "pathFrom",
8396 "external");
b05a1c8b 8397
d62a17ae 8398 return;
8399 }
b05a1c8b 8400
82c298be
DA
8401 /* RPKI validation state */
8402 rpki_state =
8403 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8404
8405 if (rpki_state == RPKI_VALID)
8406 vty_out(vty, "V");
8407 else if (rpki_state == RPKI_INVALID)
8408 vty_out(vty, "I");
8409 else if (rpki_state == RPKI_NOTFOUND)
8410 vty_out(vty, "N");
8411
d62a17ae 8412 /* Route status display. */
9b6d8fcf 8413 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8414 vty_out(vty, "R");
9b6d8fcf 8415 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8416 vty_out(vty, "S");
4056a5f6 8417 else if (bgp_path_suppressed(path))
d62a17ae 8418 vty_out(vty, "s");
9b6d8fcf
DS
8419 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8420 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8421 vty_out(vty, "*");
8422 else
8423 vty_out(vty, " ");
8424
8425 /* Selected */
9b6d8fcf 8426 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8427 vty_out(vty, "h");
9b6d8fcf 8428 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8429 vty_out(vty, "d");
9b6d8fcf 8430 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8431 vty_out(vty, ">");
9b6d8fcf 8432 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8433 vty_out(vty, "=");
8434 else
8435 vty_out(vty, " ");
718e3744 8436
d62a17ae 8437 /* Internal route. */
9b6d8fcf
DS
8438 if (path->peer && (path->peer->as)
8439 && (path->peer->as == path->peer->local_as))
d62a17ae 8440 vty_out(vty, "i");
8441 else
8442 vty_out(vty, " ");
b40d939b 8443}
8444
2ba93fd6
DA
8445static char *bgp_nexthop_hostname(struct peer *peer,
8446 struct bgp_nexthop_cache *bnc)
25b5da8d 8447{
892fedb6 8448 if (peer->hostname
aef999a2 8449 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8450 return peer->hostname;
8451 return NULL;
8452}
8453
b40d939b 8454/* called from terminal list command */
bd494ec5 8455void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8456 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8457 json_object *json_paths, bool wide)
d62a17ae 8458{
aef999a2 8459 int len;
515c2602 8460 struct attr *attr = path->attr;
d62a17ae 8461 json_object *json_path = NULL;
8462 json_object *json_nexthops = NULL;
8463 json_object *json_nexthop_global = NULL;
8464 json_object *json_nexthop_ll = NULL;
6f214dd3 8465 json_object *json_ext_community = NULL;
9df8b37c 8466 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8467 bool nexthop_self =
9b6d8fcf 8468 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8469 bool nexthop_othervrf = false;
43089216 8470 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8471 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8472 char *nexthop_hostname =
8473 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8474 char esi_buf[ESI_STR_LEN];
d62a17ae 8475
8476 if (json_paths)
8477 json_path = json_object_new_object();
8478
8479 /* short status lead text */
82c298be 8480 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8481
8482 if (!json_paths) {
8483 /* print prefix and mask */
8484 if (!display)
7d3cae70 8485 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8486 else
ae248832 8487 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8488 } else {
7d3cae70 8489 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8490 }
47fc97cc 8491
9df8b37c
PZ
8492 /*
8493 * If vrf id of nexthop is different from that of prefix,
8494 * set up printable string to append
8495 */
9b6d8fcf 8496 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8497 const char *self = "";
8498
8499 if (nexthop_self)
8500 self = "<";
8501
8502 nexthop_othervrf = true;
9b6d8fcf 8503 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8504
9b6d8fcf 8505 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8506 snprintf(vrf_id_str, sizeof(vrf_id_str),
8507 "@%s%s", VRFID_NONE_STR, self);
8508 else
8509 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8510 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8511
9b6d8fcf
DS
8512 if (path->extra->bgp_orig->inst_type
8513 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8514
9b6d8fcf 8515 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8516 } else {
8517 const char *self = "";
8518
8519 if (nexthop_self)
8520 self = "<";
8521
8522 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8523 }
8524
445c2480
DS
8525 /*
8526 * For ENCAP and EVPN routes, nexthop address family is not
8527 * neccessarily the same as the prefix address family.
8528 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8529 * EVPN routes are also exchanged with a MP nexthop. Currently,
8530 * this
8531 * is only IPv4, the value will be present in either
8532 * attr->nexthop or
8533 * attr->mp_nexthop_global_in
8534 */
8535 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8536 char buf[BUFSIZ];
8537 char nexthop[128];
8538 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8539
8540 switch (af) {
8541 case AF_INET:
772270f3
QY
8542 snprintf(nexthop, sizeof(nexthop), "%s",
8543 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8544 BUFSIZ));
445c2480
DS
8545 break;
8546 case AF_INET6:
772270f3
QY
8547 snprintf(nexthop, sizeof(nexthop), "%s",
8548 inet_ntop(af, &attr->mp_nexthop_global, buf,
8549 BUFSIZ));
445c2480
DS
8550 break;
8551 default:
772270f3 8552 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8553 break;
d62a17ae 8554 }
d62a17ae 8555
445c2480
DS
8556 if (json_paths) {
8557 json_nexthop_global = json_object_new_object();
8558
515c2602
DA
8559 json_object_string_add(json_nexthop_global, "ip",
8560 nexthop);
8561
939a97f4 8562 if (path->peer->hostname)
515c2602
DA
8563 json_object_string_add(json_nexthop_global,
8564 "hostname",
939a97f4 8565 path->peer->hostname);
515c2602
DA
8566
8567 json_object_string_add(json_nexthop_global, "afi",
8568 (af == AF_INET) ? "ipv4"
8569 : "ipv6");
445c2480
DS
8570 json_object_boolean_true_add(json_nexthop_global,
8571 "used");
aef999a2
DA
8572 } else {
8573 if (nexthop_hostname)
8574 len = vty_out(vty, "%s(%s)%s", nexthop,
8575 nexthop_hostname, vrf_id_str);
8576 else
8577 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8578
ae248832 8579 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8580 if (len < 1)
8581 vty_out(vty, "\n%*s", 36, " ");
8582 else
8583 vty_out(vty, "%*s", len, " ");
8584 }
445c2480
DS
8585 } else if (safi == SAFI_EVPN) {
8586 if (json_paths) {
23d0a753
DA
8587 char buf[BUFSIZ] = {0};
8588
445c2480
DS
8589 json_nexthop_global = json_object_new_object();
8590
515c2602 8591 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8592 inet_ntop(AF_INET,
8593 &attr->nexthop, buf,
8594 sizeof(buf)));
515c2602 8595
939a97f4 8596 if (path->peer->hostname)
515c2602
DA
8597 json_object_string_add(json_nexthop_global,
8598 "hostname",
939a97f4 8599 path->peer->hostname);
515c2602 8600
a4d82a8a
PZ
8601 json_object_string_add(json_nexthop_global, "afi",
8602 "ipv4");
445c2480
DS
8603 json_object_boolean_true_add(json_nexthop_global,
8604 "used");
aef999a2
DA
8605 } else {
8606 if (nexthop_hostname)
8607 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8608 nexthop_hostname, vrf_id_str);
8609 else
8610 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8611 vrf_id_str);
8612
ae248832 8613 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8614 if (len < 1)
8615 vty_out(vty, "\n%*s", 36, " ");
8616 else
8617 vty_out(vty, "%*s", len, " ");
8618 }
d33fc23b 8619 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8620 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8621 if (json_paths) {
23d0a753
DA
8622 char buf[BUFSIZ] = {0};
8623
026b914a 8624 json_nexthop_global = json_object_new_object();
515c2602 8625
026b914a
PG
8626 json_object_string_add(json_nexthop_global,
8627 "afi", "ipv4");
515c2602
DA
8628 json_object_string_add(
8629 json_nexthop_global, "ip",
23d0a753
DA
8630 inet_ntop(AF_INET, &attr->nexthop, buf,
8631 sizeof(buf)));
515c2602 8632
939a97f4 8633 if (path->peer->hostname)
515c2602
DA
8634 json_object_string_add(
8635 json_nexthop_global, "hostname",
939a97f4 8636 path->peer->hostname);
515c2602 8637
50e05855
AD
8638 json_object_boolean_true_add(
8639 json_nexthop_global,
026b914a
PG
8640 "used");
8641 } else {
aef999a2
DA
8642 if (nexthop_hostname)
8643 len = vty_out(vty, "%pI4(%s)%s",
8644 &attr->nexthop,
8645 nexthop_hostname,
8646 vrf_id_str);
8647 else
8648 len = vty_out(vty, "%pI4%s",
8649 &attr->nexthop,
8650 vrf_id_str);
8651
ae248832 8652 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8653 if (len < 1)
8654 vty_out(vty, "\n%*s", 36, " ");
8655 else
8656 vty_out(vty, "%*s", len, " ");
026b914a
PG
8657 }
8658 }
d33fc23b 8659 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8660 if (json_paths) {
23d0a753
DA
8661 char buf[BUFSIZ] = {0};
8662
445c2480 8663 json_nexthop_global = json_object_new_object();
d62a17ae 8664
515c2602 8665 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8666 inet_ntop(AF_INET,
8667 &attr->nexthop, buf,
8668 sizeof(buf)));
515c2602 8669
939a97f4 8670 if (path->peer->hostname)
515c2602
DA
8671 json_object_string_add(json_nexthop_global,
8672 "hostname",
939a97f4 8673 path->peer->hostname);
445c2480 8674
a4d82a8a
PZ
8675 json_object_string_add(json_nexthop_global, "afi",
8676 "ipv4");
445c2480
DS
8677 json_object_boolean_true_add(json_nexthop_global,
8678 "used");
8679 } else {
aef999a2
DA
8680 if (nexthop_hostname)
8681 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8682 nexthop_hostname, vrf_id_str);
8683 else
8684 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8685 vrf_id_str);
9df8b37c 8686
ae248832 8687 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8688 if (len < 1)
8689 vty_out(vty, "\n%*s", 36, " ");
8690 else
8691 vty_out(vty, "%*s", len, " ");
d62a17ae 8692 }
445c2480 8693 }
b05a1c8b 8694
445c2480 8695 /* IPv6 Next Hop */
a4d82a8a 8696 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8697 char buf[BUFSIZ];
d62a17ae 8698
445c2480
DS
8699 if (json_paths) {
8700 json_nexthop_global = json_object_new_object();
a4d82a8a 8701 json_object_string_add(
515c2602
DA
8702 json_nexthop_global, "ip",
8703 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8704 buf, BUFSIZ));
8705
939a97f4 8706 if (path->peer->hostname)
515c2602
DA
8707 json_object_string_add(json_nexthop_global,
8708 "hostname",
939a97f4 8709 path->peer->hostname);
515c2602 8710
a4d82a8a
PZ
8711 json_object_string_add(json_nexthop_global, "afi",
8712 "ipv6");
8713 json_object_string_add(json_nexthop_global, "scope",
8714 "global");
445c2480
DS
8715
8716 /* We display both LL & GL if both have been
8717 * received */
0606039c
DA
8718 if ((attr->mp_nexthop_len
8719 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8720 || (path->peer->conf_if)) {
a4d82a8a 8721 json_nexthop_ll = json_object_new_object();
d62a17ae 8722 json_object_string_add(
515c2602
DA
8723 json_nexthop_ll, "ip",
8724 inet_ntop(AF_INET6,
8725 &attr->mp_nexthop_local, buf,
8726 BUFSIZ));
8727
939a97f4 8728 if (path->peer->hostname)
515c2602
DA
8729 json_object_string_add(
8730 json_nexthop_ll, "hostname",
939a97f4 8731 path->peer->hostname);
515c2602 8732
a4d82a8a
PZ
8733 json_object_string_add(json_nexthop_ll, "afi",
8734 "ipv6");
8735 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8736 "link-local");
d62a17ae 8737
a4d82a8a
PZ
8738 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8739 &attr->mp_nexthop_local)
445c2480
DS
8740 != 0)
8741 && !attr->mp_nexthop_prefer_global)
d62a17ae 8742 json_object_boolean_true_add(
a4d82a8a 8743 json_nexthop_ll, "used");
445c2480
DS
8744 else
8745 json_object_boolean_true_add(
a4d82a8a 8746 json_nexthop_global, "used");
445c2480
DS
8747 } else
8748 json_object_boolean_true_add(
8749 json_nexthop_global, "used");
8750 } else {
8751 /* Display LL if LL/Global both in table unless
8752 * prefer-global is set */
0606039c
DA
8753 if (((attr->mp_nexthop_len
8754 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8755 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8756 || (path->peer->conf_if)) {
8757 if (path->peer->conf_if) {
a4d82a8a 8758 len = vty_out(vty, "%s",
9b6d8fcf 8759 path->peer->conf_if);
ae248832
MK
8760 /* len of IPv6 addr + max len of def
8761 * ifname */
8762 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8763
8764 if (len < 1)
a4d82a8a 8765 vty_out(vty, "\n%*s", 36, " ");
445c2480 8766 else
a4d82a8a 8767 vty_out(vty, "%*s", len, " ");
d62a17ae 8768 } else {
aef999a2
DA
8769 if (nexthop_hostname)
8770 len = vty_out(
8771 vty, "%pI6(%s)%s",
8772 &attr->mp_nexthop_local,
8773 nexthop_hostname,
8774 vrf_id_str);
8775 else
8776 len = vty_out(
8777 vty, "%pI6%s",
8778 &attr->mp_nexthop_local,
8779 vrf_id_str);
8780
ae248832 8781 len = wide ? (41 - len) : (16 - len);
d62a17ae 8782
8783 if (len < 1)
a4d82a8a 8784 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8785 else
a4d82a8a 8786 vty_out(vty, "%*s", len, " ");
d62a17ae 8787 }
445c2480 8788 } else {
aef999a2
DA
8789 if (nexthop_hostname)
8790 len = vty_out(vty, "%pI6(%s)%s",
8791 &attr->mp_nexthop_global,
8792 nexthop_hostname,
8793 vrf_id_str);
8794 else
8795 len = vty_out(vty, "%pI6%s",
8796 &attr->mp_nexthop_global,
8797 vrf_id_str);
8798
ae248832 8799 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8800
8801 if (len < 1)
8802 vty_out(vty, "\n%*s", 36, " ");
8803 else
8804 vty_out(vty, "%*s", len, " ");
d62a17ae 8805 }
8806 }
445c2480 8807 }
718e3744 8808
445c2480
DS
8809 /* MED/Metric */
8810 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8811 if (json_paths)
50e05855 8812 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8813 else if (wide)
8814 vty_out(vty, "%7u", attr->med);
0fbac0b4 8815 else
445c2480 8816 vty_out(vty, "%10u", attr->med);
ae248832
MK
8817 else if (!json_paths) {
8818 if (wide)
8819 vty_out(vty, "%*s", 7, " ");
8820 else
8821 vty_out(vty, "%*s", 10, " ");
8822 }
d62a17ae 8823
445c2480
DS
8824 /* Local Pref */
8825 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8826 if (json_paths)
50e05855 8827 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8828 attr->local_pref);
8829 else
445c2480
DS
8830 vty_out(vty, "%7u", attr->local_pref);
8831 else if (!json_paths)
8832 vty_out(vty, " ");
d62a17ae 8833
445c2480
DS
8834 if (json_paths)
8835 json_object_int_add(json_path, "weight", attr->weight);
8836 else
8837 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8838
445c2480
DS
8839 if (json_paths) {
8840 char buf[BUFSIZ];
a4d82a8a
PZ
8841 json_object_string_add(
8842 json_path, "peerId",
9b6d8fcf 8843 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8844 }
b05a1c8b 8845
445c2480
DS
8846 /* Print aspath */
8847 if (attr->aspath) {
0fbac0b4 8848 if (json_paths)
50e05855 8849 json_object_string_add(json_path, "path",
0fbac0b4
DA
8850 attr->aspath->str);
8851 else
445c2480 8852 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8853 }
f1aa5d8a 8854
445c2480
DS
8855 /* Print origin */
8856 if (json_paths)
a4d82a8a
PZ
8857 json_object_string_add(json_path, "origin",
8858 bgp_origin_long_str[attr->origin]);
445c2480
DS
8859 else
8860 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8861
9df8b37c 8862 if (json_paths) {
d071f237 8863 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8864 json_object_string_add(json_path, "esi",
8865 esi_to_str(&attr->esi,
8866 esi_buf, sizeof(esi_buf)));
8867 }
6f214dd3
CS
8868 if (safi == SAFI_EVPN &&
8869 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8870 json_ext_community = json_object_new_object();
8871 json_object_string_add(json_ext_community,
8872 "string",
8873 attr->ecommunity->str);
8874 json_object_object_add(json_path,
8875 "extendedCommunity",
8876 json_ext_community);
8877 }
8878
9df8b37c
PZ
8879 if (nexthop_self)
8880 json_object_boolean_true_add(json_path,
8881 "announceNexthopSelf");
8882 if (nexthop_othervrf) {
8883 json_object_string_add(json_path, "nhVrfName",
8884 nexthop_vrfname);
8885
8886 json_object_int_add(json_path, "nhVrfId",
8887 ((nexthop_vrfid == VRF_UNKNOWN)
8888 ? -1
8889 : (int)nexthop_vrfid));
8890 }
8891 }
8892
d62a17ae 8893 if (json_paths) {
8894 if (json_nexthop_global || json_nexthop_ll) {
8895 json_nexthops = json_object_new_array();
f1aa5d8a 8896
d62a17ae 8897 if (json_nexthop_global)
8898 json_object_array_add(json_nexthops,
8899 json_nexthop_global);
f1aa5d8a 8900
d62a17ae 8901 if (json_nexthop_ll)
8902 json_object_array_add(json_nexthops,
8903 json_nexthop_ll);
f1aa5d8a 8904
d62a17ae 8905 json_object_object_add(json_path, "nexthops",
8906 json_nexthops);
8907 }
8908
8909 json_object_array_add(json_paths, json_path);
8910 } else {
8911 vty_out(vty, "\n");
6f214dd3 8912
b5e140c8 8913 if (safi == SAFI_EVPN) {
229587fb
AK
8914 struct bgp_path_es_info *path_es_info = NULL;
8915
d071f237 8916 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8917 /* XXX - add these params to the json out */
b5e140c8 8918 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8919 vty_out(vty, "ESI:%s",
8920 esi_to_str(&attr->esi, esi_buf,
8921 sizeof(esi_buf)));
60605cbc
AK
8922
8923 if (path->extra && path->extra->mh_info)
8924 path_es_info =
8925 path->extra->mh_info->es_info;
8926
229587fb
AK
8927 if (path_es_info && path_es_info->es)
8928 vty_out(vty, " VNI: %u",
8929 path_es_info->vni);
8930 vty_out(vty, "\n");
b5e140c8
AK
8931 }
8932 if (attr->flag &
8933 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8934 vty_out(vty, "%*s", 20, " ");
8935 vty_out(vty, "%s\n", attr->ecommunity->str);
8936 }
6f214dd3
CS
8937 }
8938
49e5a4a0 8939#ifdef ENABLE_BGP_VNC
d62a17ae 8940 /* prints an additional line, indented, with VNC info, if
8941 * present */
8942 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8943 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8944#endif
d62a17ae 8945 }
8946}
718e3744 8947
8948/* called from terminal list command */
7d3cae70
DA
8949void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
8950 const struct prefix *p, struct attr *attr, safi_t safi,
8951 bool use_json, json_object *json_ar, bool wide)
d62a17ae 8952{
8953 json_object *json_status = NULL;
8954 json_object *json_net = NULL;
aef999a2 8955 int len;
d62a17ae 8956 char buff[BUFSIZ];
dc387b0f 8957
d62a17ae 8958 /* Route status display. */
8959 if (use_json) {
8960 json_status = json_object_new_object();
8961 json_net = json_object_new_object();
8962 } else {
8963 vty_out(vty, "*");
8964 vty_out(vty, ">");
8965 vty_out(vty, " ");
8966 }
718e3744 8967
d62a17ae 8968 /* print prefix and mask */
50e05855 8969 if (use_json) {
dc387b0f
LK
8970 if (safi == SAFI_EVPN)
8971 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8972 else if (p->family == AF_INET || p->family == AF_INET6) {
8973 json_object_string_add(
8974 json_net, "addrPrefix",
8975 inet_ntop(p->family, &p->u.prefix, buff,
8976 BUFSIZ));
8977 json_object_int_add(json_net, "prefixLen",
8978 p->prefixlen);
8979 prefix2str(p, buff, PREFIX_STRLEN);
8980 json_object_string_add(json_net, "network", buff);
8981 }
50e05855 8982 } else
7d3cae70 8983 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 8984
8985 /* Print attribute */
8986 if (attr) {
8987 if (use_json) {
23d0a753
DA
8988 char buf[BUFSIZ] = {0};
8989
d62a17ae 8990 if (p->family == AF_INET
8991 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8992 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8993 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8994 json_object_string_add(
8995 json_net, "nextHop",
23d0a753
DA
8996 inet_ntop(
8997 AF_INET,
8998 &attr->mp_nexthop_global_in,
8999 buf, sizeof(buf)));
d62a17ae 9000 else
9001 json_object_string_add(
9002 json_net, "nextHop",
23d0a753
DA
9003 inet_ntop(AF_INET,
9004 &attr->nexthop, buf,
9005 sizeof(buf)));
d62a17ae 9006 } else if (p->family == AF_INET6
9007 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9008 char buf[BUFSIZ];
9009
9010 json_object_string_add(
aa0a10fc 9011 json_net, "nextHopGlobal",
d62a17ae 9012 inet_ntop(AF_INET6,
9013 &attr->mp_nexthop_global, buf,
9014 BUFSIZ));
23d0a753
DA
9015 } else if (p->family == AF_EVPN
9016 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9017 char buf[BUFSIZ] = {0};
9018
9019 json_object_string_add(
9020 json_net, "nextHop",
9021 inet_ntop(AF_INET,
9022 &attr->mp_nexthop_global_in,
9023 buf, sizeof(buf)));
9024 }
d62a17ae 9025
9026 if (attr->flag
9027 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9028 json_object_int_add(json_net, "metric",
9029 attr->med);
9030
0fbac0b4 9031 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9032 json_object_int_add(json_net, "locPrf",
0fbac0b4 9033 attr->local_pref);
d62a17ae 9034
9035 json_object_int_add(json_net, "weight", attr->weight);
9036
9037 /* Print aspath */
0fbac0b4 9038 if (attr->aspath)
50e05855 9039 json_object_string_add(json_net, "path",
0fbac0b4 9040 attr->aspath->str);
d62a17ae 9041
9042 /* Print origin */
9043 json_object_string_add(json_net, "bgpOriginCode",
9044 bgp_origin_str[attr->origin]);
9045 } else {
9046 if (p->family == AF_INET
9047 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9048 || safi == SAFI_EVPN
9049 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9050 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9051 || safi == SAFI_EVPN)
23d0a753
DA
9052 vty_out(vty, "%-16pI4",
9053 &attr->mp_nexthop_global_in);
ae248832 9054 else if (wide)
23d0a753 9055 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9056 else
23d0a753 9057 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9058 } else if (p->family == AF_INET6
9059 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9060 char buf[BUFSIZ];
9061
9062 len = vty_out(
9063 vty, "%s",
9064 inet_ntop(AF_INET6,
9065 &attr->mp_nexthop_global, buf,
9066 BUFSIZ));
ae248832 9067 len = wide ? (41 - len) : (16 - len);
d62a17ae 9068 if (len < 1)
9069 vty_out(vty, "\n%*s", 36, " ");
9070 else
9071 vty_out(vty, "%*s", len, " ");
9072 }
9073 if (attr->flag
9074 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9075 if (wide)
9076 vty_out(vty, "%7u", attr->med);
9077 else
9078 vty_out(vty, "%10u", attr->med);
9079 else if (wide)
9080 vty_out(vty, " ");
d62a17ae 9081 else
9082 vty_out(vty, " ");
718e3744 9083
d62a17ae 9084 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9085 vty_out(vty, "%7u", attr->local_pref);
9086 else
9087 vty_out(vty, " ");
9088
9089 vty_out(vty, "%7u ", attr->weight);
9090
9091 /* Print aspath */
9092 if (attr->aspath)
9093 aspath_print_vty(vty, "%s", attr->aspath, " ");
9094
9095 /* Print origin */
9096 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9097 }
9098 }
9099 if (use_json) {
9100 json_object_boolean_true_add(json_status, "*");
9101 json_object_boolean_true_add(json_status, ">");
9102 json_object_object_add(json_net, "appliedStatusSymbols",
9103 json_status);
1608ff77 9104
dc387b0f
LK
9105 prefix2str(p, buff, PREFIX_STRLEN);
9106 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9107 } else
9108 vty_out(vty, "\n");
9109}
9110
bd494ec5 9111void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9112 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9113 json_object *json)
9114{
9115 json_object *json_out = NULL;
9116 struct attr *attr;
9117 mpls_label_t label = MPLS_INVALID_LABEL;
9118
9b6d8fcf 9119 if (!path->extra)
d62a17ae 9120 return;
9121
9122 if (json)
9123 json_out = json_object_new_object();
9124
9125 /* short status lead text */
82c298be 9126 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9127
9128 /* print prefix and mask */
9129 if (json == NULL) {
9130 if (!display)
7d3cae70 9131 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9132 else
9133 vty_out(vty, "%*s", 17, " ");
9134 }
9135
9136 /* Print attribute */
9b6d8fcf 9137 attr = path->attr;
05864da7
DS
9138 if (((p->family == AF_INET)
9139 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9140 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9141 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9142 char buf[BUFSIZ] = {0};
9143
05864da7
DS
9144 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9145 || safi == SAFI_EVPN) {
9146 if (json)
9147 json_object_string_add(
9148 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9149 inet_ntop(AF_INET,
9150 &attr->mp_nexthop_global_in,
9151 buf, sizeof(buf)));
05864da7 9152 else
23d0a753
DA
9153 vty_out(vty, "%-16pI4",
9154 &attr->mp_nexthop_global_in);
05864da7
DS
9155 } else {
9156 if (json)
9157 json_object_string_add(
9158 json_out, "nexthop",
23d0a753
DA
9159 inet_ntop(AF_INET, &attr->nexthop, buf,
9160 sizeof(buf)));
05864da7 9161 else
23d0a753 9162 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9163 }
9164 } else if (((p->family == AF_INET6)
9165 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9166 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9167 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9168 char buf_a[512];
9169
9170 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9171 if (json)
9172 json_object_string_add(
9173 json_out, "mpNexthopGlobalIn",
9174 inet_ntop(AF_INET6,
9175 &attr->mp_nexthop_global,
9176 buf_a, sizeof(buf_a)));
9177 else
9178 vty_out(vty, "%s",
9179 inet_ntop(AF_INET6,
9180 &attr->mp_nexthop_global,
9181 buf_a, sizeof(buf_a)));
9182 } else if (attr->mp_nexthop_len
9183 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9184 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9185 &attr->mp_nexthop_global,
9186 &attr->mp_nexthop_local);
9187 if (json)
9188 json_object_string_add(json_out,
9189 "mpNexthopGlobalLocal",
9190 buf_a);
9191 else
9192 vty_out(vty, "%s", buf_a);
d62a17ae 9193 }
9194 }
9195
9b6d8fcf 9196 label = decode_label(&path->extra->label[0]);
d62a17ae 9197
9198 if (bgp_is_valid_label(&label)) {
9199 if (json) {
9200 json_object_int_add(json_out, "notag", label);
9201 json_object_array_add(json, json_out);
9202 } else {
9203 vty_out(vty, "notag/%d", label);
9204 vty_out(vty, "\n");
9205 }
9206 }
9207}
718e3744 9208
bd494ec5 9209void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9210 struct bgp_path_info *path, int display,
d62a17ae 9211 json_object *json_paths)
718e3744 9212{
d62a17ae 9213 struct attr *attr;
14f51eba 9214 char buf[BUFSIZ] = {0};
d62a17ae 9215 json_object *json_path = NULL;
14f51eba
LK
9216 json_object *json_nexthop = NULL;
9217 json_object *json_overlay = NULL;
856ca177 9218
9b6d8fcf 9219 if (!path->extra)
d62a17ae 9220 return;
718e3744 9221
14f51eba
LK
9222 if (json_paths) {
9223 json_path = json_object_new_object();
9224 json_overlay = json_object_new_object();
9225 json_nexthop = json_object_new_object();
9226 }
9227
d62a17ae 9228 /* short status lead text */
82c298be 9229 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9230
d62a17ae 9231 /* print prefix and mask */
9232 if (!display)
7d3cae70 9233 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9234 else
9235 vty_out(vty, "%*s", 17, " ");
9236
9237 /* Print attribute */
9b6d8fcf 9238 attr = path->attr;
05864da7
DS
9239 char buf1[BUFSIZ];
9240 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9241
05864da7
DS
9242 switch (af) {
9243 case AF_INET:
9244 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9245 if (!json_path) {
9246 vty_out(vty, "%-16s", buf);
9247 } else {
9248 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9249
05864da7 9250 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9251
05864da7
DS
9252 json_object_object_add(json_path, "nexthop",
9253 json_nexthop);
9254 }
9255 break;
9256 case AF_INET6:
9257 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9258 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9259 if (!json_path) {
9260 vty_out(vty, "%s(%s)", buf, buf1);
9261 } else {
9262 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9263
05864da7
DS
9264 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9265 buf1);
14f51eba 9266
05864da7 9267 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9268
05864da7
DS
9269 json_object_object_add(json_path, "nexthop",
9270 json_nexthop);
9271 }
9272 break;
9273 default:
9274 if (!json_path) {
9275 vty_out(vty, "?");
9276 } else {
9277 json_object_string_add(json_nexthop, "Error",
9278 "Unsupported address-family");
d62a17ae 9279 }
05864da7 9280 }
988258b4 9281
6c924775
DS
9282 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9283
9284 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9285 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9286 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9287 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9288
05864da7
DS
9289 if (!json_path)
9290 vty_out(vty, "/%s", buf);
9291 else
9292 json_object_string_add(json_overlay, "gw", buf);
9293
9294 if (attr->ecommunity) {
9295 char *mac = NULL;
9296 struct ecommunity_val *routermac = ecommunity_lookup(
9297 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9298 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9299
9300 if (routermac)
9301 mac = ecom_mac2str((char *)routermac->val);
9302 if (mac) {
9303 if (!json_path) {
c4efd0f4 9304 vty_out(vty, "/%s", mac);
05864da7
DS
9305 } else {
9306 json_object_string_add(json_overlay, "rmac",
9307 mac);
988258b4 9308 }
05864da7 9309 XFREE(MTYPE_TMP, mac);
988258b4 9310 }
05864da7 9311 }
718e3744 9312
05864da7
DS
9313 if (!json_path) {
9314 vty_out(vty, "\n");
9315 } else {
9316 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9317
05864da7 9318 json_object_array_add(json_paths, json_path);
14f51eba 9319 }
d62a17ae 9320}
718e3744 9321
d62a17ae 9322/* dampening route */
5f040085
DS
9323static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9324 struct bgp_path_info *path, int display,
9325 afi_t afi, safi_t safi, bool use_json,
9326 json_object *json)
d62a17ae 9327{
9328 struct attr *attr;
9329 int len;
9330 char timebuf[BGP_UPTIME_LEN];
9331
9332 /* short status lead text */
82c298be 9333 route_vty_short_status_out(vty, path, p, json);
d62a17ae 9334
9335 /* print prefix and mask */
9336 if (!use_json) {
9337 if (!display)
7d3cae70 9338 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9339 else
9340 vty_out(vty, "%*s", 17, " ");
9341 }
9342
9b6d8fcf 9343 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9344 len = 17 - len;
9345 if (len < 1) {
9346 if (!use_json)
9347 vty_out(vty, "\n%*s", 34, " ");
9348 } else {
9349 if (use_json)
9350 json_object_int_add(json, "peerHost", len);
9351 else
9352 vty_out(vty, "%*s", len, " ");
9353 }
9354
9355 if (use_json)
a935f597
DA
9356 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9357 safi, use_json, json);
d62a17ae 9358 else
9b6d8fcf
DS
9359 vty_out(vty, "%s ",
9360 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9361 BGP_UPTIME_LEN, afi, safi,
9362 use_json, json));
d62a17ae 9363
9364 /* Print attribute */
9b6d8fcf 9365 attr = path->attr;
d62a17ae 9366
05864da7
DS
9367 /* Print aspath */
9368 if (attr->aspath) {
d62a17ae 9369 if (use_json)
05864da7
DS
9370 json_object_string_add(json, "asPath",
9371 attr->aspath->str);
d62a17ae 9372 else
05864da7 9373 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9374 }
05864da7
DS
9375
9376 /* Print origin */
9377 if (use_json)
9378 json_object_string_add(json, "origin",
9379 bgp_origin_str[attr->origin]);
9380 else
9381 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9382
d62a17ae 9383 if (!use_json)
9384 vty_out(vty, "\n");
9385}
718e3744 9386
d62a17ae 9387/* flap route */
5f040085
DS
9388static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9389 struct bgp_path_info *path, int display,
9390 afi_t afi, safi_t safi, bool use_json,
9391 json_object *json)
784d3a42 9392{
d62a17ae 9393 struct attr *attr;
9394 struct bgp_damp_info *bdi;
9395 char timebuf[BGP_UPTIME_LEN];
9396 int len;
784d3a42 9397
9b6d8fcf 9398 if (!path->extra)
d62a17ae 9399 return;
784d3a42 9400
9b6d8fcf 9401 bdi = path->extra->damp_info;
784d3a42 9402
d62a17ae 9403 /* short status lead text */
82c298be 9404 route_vty_short_status_out(vty, path, p, json);
784d3a42 9405
d62a17ae 9406 /* print prefix and mask */
9407 if (!use_json) {
9408 if (!display)
7d3cae70 9409 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9410 else
9411 vty_out(vty, "%*s", 17, " ");
9412 }
784d3a42 9413
9b6d8fcf 9414 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9415 len = 16 - len;
9416 if (len < 1) {
9417 if (!use_json)
9418 vty_out(vty, "\n%*s", 33, " ");
9419 } else {
9420 if (use_json)
9421 json_object_int_add(json, "peerHost", len);
9422 else
9423 vty_out(vty, "%*s", len, " ");
9424 }
784d3a42 9425
d62a17ae 9426 len = vty_out(vty, "%d", bdi->flap);
9427 len = 5 - len;
9428 if (len < 1) {
9429 if (!use_json)
9430 vty_out(vty, " ");
9431 } else {
9432 if (use_json)
9433 json_object_int_add(json, "bdiFlap", len);
9434 else
9435 vty_out(vty, "%*s", len, " ");
9436 }
9437
9438 if (use_json)
9439 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9440 json);
9441 else
996c9314
LB
9442 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9443 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9444
9b6d8fcf
DS
9445 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9446 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9447 if (use_json)
9b6d8fcf 9448 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9449 BGP_UPTIME_LEN, afi, safi,
9450 use_json, json);
d62a17ae 9451 else
9452 vty_out(vty, "%s ",
9b6d8fcf 9453 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9454 BGP_UPTIME_LEN, afi,
9455 safi, use_json, json));
d62a17ae 9456 } else {
9457 if (!use_json)
9458 vty_out(vty, "%*s ", 8, " ");
9459 }
9460
9461 /* Print attribute */
9b6d8fcf 9462 attr = path->attr;
d62a17ae 9463
05864da7
DS
9464 /* Print aspath */
9465 if (attr->aspath) {
d62a17ae 9466 if (use_json)
05864da7
DS
9467 json_object_string_add(json, "asPath",
9468 attr->aspath->str);
d62a17ae 9469 else
05864da7 9470 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9471 }
05864da7
DS
9472
9473 /* Print origin */
9474 if (use_json)
9475 json_object_string_add(json, "origin",
9476 bgp_origin_str[attr->origin]);
9477 else
9478 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9479
d62a17ae 9480 if (!use_json)
9481 vty_out(vty, "\n");
9482}
9483
9484static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9485 int *first, const char *header,
9486 json_object *json_adv_to)
9487{
9488 char buf1[INET6_ADDRSTRLEN];
9489 json_object *json_peer = NULL;
9490
9491 if (json_adv_to) {
9492 /* 'advertised-to' is a dictionary of peers we have advertised
9493 * this
9494 * prefix too. The key is the peer's IP or swpX, the value is
9495 * the
9496 * hostname if we know it and "" if not.
9497 */
9498 json_peer = json_object_new_object();
9499
9500 if (peer->hostname)
9501 json_object_string_add(json_peer, "hostname",
9502 peer->hostname);
9503
9504 if (peer->conf_if)
9505 json_object_object_add(json_adv_to, peer->conf_if,
9506 json_peer);
9507 else
9508 json_object_object_add(
9509 json_adv_to,
9510 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9511 json_peer);
9512 } else {
9513 if (*first) {
9514 vty_out(vty, "%s", header);
9515 *first = 0;
9516 }
9517
9518 if (peer->hostname
892fedb6 9519 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9520 if (peer->conf_if)
9521 vty_out(vty, " %s(%s)", peer->hostname,
9522 peer->conf_if);
9523 else
9524 vty_out(vty, " %s(%s)", peer->hostname,
9525 sockunion2str(&peer->su, buf1,
9526 SU_ADDRSTRLEN));
9527 } else {
9528 if (peer->conf_if)
9529 vty_out(vty, " %s", peer->conf_if);
9530 else
9531 vty_out(vty, " %s",
9532 sockunion2str(&peer->su, buf1,
9533 SU_ADDRSTRLEN));
9534 }
9535 }
784d3a42
PG
9536}
9537
dcc68b5e
MS
9538static void route_vty_out_tx_ids(struct vty *vty,
9539 struct bgp_addpath_info_data *d)
9540{
9541 int i;
9542
9543 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9544 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9545 d->addpath_tx_id[i],
9546 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9547 }
9548}
9549
5e4d4c8a 9550static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9551 struct bgp_path_info *pi,
9552 struct attr *attr,
9553 json_object *json_path)
5e4d4c8a
AK
9554{
9555 char esi_buf[ESI_STR_LEN];
9556 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9557 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9558 ATTR_ES_PEER_ROUTER);
9559 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9560 ATTR_ES_PEER_ACTIVE);
9561 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9562 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9563 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9564 if (json_path) {
9565 json_object *json_es_info = NULL;
9566
9567 json_object_string_add(
9568 json_path, "esi",
9569 esi_buf);
9570 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9571 json_es_info = json_object_new_object();
9572 if (es_local)
9573 json_object_boolean_true_add(
9574 json_es_info, "localEs");
9575 if (peer_active)
9576 json_object_boolean_true_add(
9577 json_es_info, "peerActive");
9578 if (peer_proxy)
9579 json_object_boolean_true_add(
9580 json_es_info, "peerProxy");
9581 if (peer_router)
9582 json_object_boolean_true_add(
9583 json_es_info, "peerRouter");
9584 if (attr->mm_sync_seqnum)
9585 json_object_int_add(
9586 json_es_info, "peerSeq",
9587 attr->mm_sync_seqnum);
9588 json_object_object_add(
9589 json_path, "es_info",
9590 json_es_info);
9591 }
9592 } else {
9593 if (bgp_evpn_attr_is_sync(attr))
9594 vty_out(vty,
9595 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9596 esi_buf,
9597 es_local ? "local-es":"",
9598 peer_proxy ? "proxy " : "",
9599 peer_active ? "active ":"",
9600 peer_router ? "router ":"",
9601 attr->mm_sync_seqnum);
9602 else
9603 vty_out(vty, " ESI %s %s\n",
9604 esi_buf,
9605 es_local ? "local-es":"");
9606 }
9607}
9608
4933eaaf
DS
9609void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9610 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9611 enum rpki_states rpki_curr_state,
9612 json_object *json_paths)
d62a17ae 9613{
9614 char buf[INET6_ADDRSTRLEN];
9615 char buf1[BUFSIZ];
515c2602 9616 struct attr *attr = path->attr;
d62a17ae 9617 int sockunion_vty_out(struct vty *, union sockunion *);
9618 time_t tbuf;
9619 json_object *json_bestpath = NULL;
9620 json_object *json_cluster_list = NULL;
9621 json_object *json_cluster_list_list = NULL;
9622 json_object *json_ext_community = NULL;
9623 json_object *json_last_update = NULL;
7fd077aa 9624 json_object *json_pmsi = NULL;
d62a17ae 9625 json_object *json_nexthop_global = NULL;
9626 json_object *json_nexthop_ll = NULL;
9627 json_object *json_nexthops = NULL;
9628 json_object *json_path = NULL;
9629 json_object *json_peer = NULL;
9630 json_object *json_string = NULL;
9631 json_object *json_adv_to = NULL;
9632 int first = 0;
9633 struct listnode *node, *nnode;
9634 struct peer *peer;
9635 int addpath_capable;
9636 int has_adj;
9637 unsigned int first_as;
1defdda8 9638 bool nexthop_self =
9b6d8fcf 9639 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9640 int i;
2ba93fd6
DA
9641 char *nexthop_hostname =
9642 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9643
9644 if (json_paths) {
9645 json_path = json_object_new_object();
9646 json_peer = json_object_new_object();
9647 json_nexthop_global = json_object_new_object();
9648 }
9649
44c69747 9650 if (path->extra) {
b57ba6d2 9651 char tag_buf[30];
d62a17ae 9652
d62a17ae 9653 tag_buf[0] = '\0';
9b6d8fcf
DS
9654 if (path->extra && path->extra->num_labels) {
9655 bgp_evpn_label2str(path->extra->label,
9656 path->extra->num_labels, tag_buf,
a4d82a8a 9657 sizeof(tag_buf));
d62a17ae 9658 }
d7325ee7 9659 if (safi == SAFI_EVPN) {
44c69747 9660 if (!json_paths) {
2dbe669b
DA
9661 vty_out(vty, " Route %pFX",
9662 (struct prefix_evpn *)
9663 bgp_dest_get_prefix(bn));
44c69747
LK
9664 if (tag_buf[0] != '\0')
9665 vty_out(vty, " VNI %s", tag_buf);
9666 vty_out(vty, "\n");
9667 } else {
9668 if (tag_buf[0])
9669 json_object_string_add(json_path, "VNI",
9670 tag_buf);
9671 }
d7325ee7
DD
9672 }
9673
44c69747 9674 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9675 struct bgp_path_info *parent_ri;
9bcb3eef 9676 struct bgp_dest *dest, *pdest;
d62a17ae 9677
9b6d8fcf 9678 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9679 dest = parent_ri->net;
9680 if (dest && dest->pdest) {
9681 pdest = dest->pdest;
9682 prefix_rd2str(
9683 (struct prefix_rd *)bgp_dest_get_prefix(
9684 pdest),
9685 buf1, sizeof(buf1));
d7325ee7 9686 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9687 vty_out(vty,
58bff4d1 9688 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9689 buf1,
9690 (struct prefix_evpn *)
9691 bgp_dest_get_prefix(
9692 dest),
9693 tag_buf);
58bff4d1
AK
9694 if (attr->es_flags & ATTR_ES_L3_NHG)
9695 vty_out(vty, ", L3NHG %s",
9696 (attr->es_flags
9697 & ATTR_ES_L3_NHG_ACTIVE)
9698 ? "active"
9699 : "inactive");
9700 vty_out(vty, "\n");
9701
d7325ee7 9702 } else
2dbe669b
DA
9703 vty_out(vty,
9704 " Imported from %s:%pFX\n",
9705 buf1,
9706 (struct prefix_evpn *)
9707 bgp_dest_get_prefix(
9708 dest));
d62a17ae 9709 }
9710 }
9711 }
d62a17ae 9712
05864da7
DS
9713 /* Line1 display AS-path, Aggregator */
9714 if (attr->aspath) {
9715 if (json_paths) {
9716 if (!attr->aspath->json)
9717 aspath_str_update(attr->aspath, true);
9718 json_object_lock(attr->aspath->json);
9719 json_object_object_add(json_path, "aspath",
9720 attr->aspath->json);
9721 } else {
9722 if (attr->aspath->segments)
9723 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9724 else
05864da7 9725 vty_out(vty, " Local");
d62a17ae 9726 }
05864da7 9727 }
d62a17ae 9728
05864da7
DS
9729 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9730 if (json_paths)
9731 json_object_boolean_true_add(json_path, "removed");
9732 else
9733 vty_out(vty, ", (removed)");
9734 }
d62a17ae 9735
05864da7
DS
9736 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9737 if (json_paths)
9738 json_object_boolean_true_add(json_path, "stale");
9739 else
9740 vty_out(vty, ", (stale)");
9741 }
d62a17ae 9742
05864da7
DS
9743 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9744 if (json_paths) {
23d0a753
DA
9745 char buf[BUFSIZ] = {0};
9746
05864da7
DS
9747 json_object_int_add(json_path, "aggregatorAs",
9748 attr->aggregator_as);
23d0a753
DA
9749 json_object_string_add(json_path, "aggregatorId",
9750 inet_ntop(AF_INET,
9751 &attr->aggregator_addr,
9752 buf, sizeof(buf)));
05864da7 9753 } else {
88d495a9
DA
9754 vty_out(vty, ", (aggregated by %u %pI4)",
9755 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9756 }
05864da7 9757 }
d62a17ae 9758
05864da7
DS
9759 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9760 PEER_FLAG_REFLECTOR_CLIENT)) {
9761 if (json_paths)
9762 json_object_boolean_true_add(json_path,
9763 "rxedFromRrClient");
9764 else
9765 vty_out(vty, ", (Received from a RR-client)");
9766 }
d62a17ae 9767
05864da7
DS
9768 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9769 PEER_FLAG_RSERVER_CLIENT)) {
9770 if (json_paths)
9771 json_object_boolean_true_add(json_path,
9772 "rxedFromRsClient");
9773 else
9774 vty_out(vty, ", (Received from a RS-client)");
9775 }
d62a17ae 9776
05864da7
DS
9777 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9778 if (json_paths)
9779 json_object_boolean_true_add(json_path,
9780 "dampeningHistoryEntry");
9781 else
9782 vty_out(vty, ", (history entry)");
9783 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9784 if (json_paths)
9785 json_object_boolean_true_add(json_path,
9786 "dampeningSuppressed");
9787 else
9788 vty_out(vty, ", (suppressed due to dampening)");
9789 }
d62a17ae 9790
05864da7
DS
9791 if (!json_paths)
9792 vty_out(vty, "\n");
d62a17ae 9793
05864da7
DS
9794 /* Line2 display Next-hop, Neighbor, Router-id */
9795 /* Display the nexthop */
9bcb3eef 9796 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9797
9798 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9799 || bn_p->family == AF_EVPN)
05864da7
DS
9800 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9801 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9802 char buf[BUFSIZ] = {0};
9803
05864da7
DS
9804 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9805 || safi == SAFI_EVPN) {
515c2602 9806 if (json_paths) {
d62a17ae 9807 json_object_string_add(
515c2602 9808 json_nexthop_global, "ip",
23d0a753
DA
9809 inet_ntop(AF_INET,
9810 &attr->mp_nexthop_global_in,
9811 buf, sizeof(buf)));
515c2602 9812
939a97f4 9813 if (path->peer->hostname)
515c2602
DA
9814 json_object_string_add(
9815 json_nexthop_global, "hostname",
939a97f4 9816 path->peer->hostname);
aef999a2
DA
9817 } else {
9818 if (nexthop_hostname)
9819 vty_out(vty, " %pI4(%s)",
9820 &attr->mp_nexthop_global_in,
9821 nexthop_hostname);
9822 else
9823 vty_out(vty, " %pI4",
9824 &attr->mp_nexthop_global_in);
9825 }
d62a17ae 9826 } else {
515c2602 9827 if (json_paths) {
05864da7 9828 json_object_string_add(
515c2602 9829 json_nexthop_global, "ip",
23d0a753
DA
9830 inet_ntop(AF_INET, &attr->nexthop, buf,
9831 sizeof(buf)));
515c2602 9832
939a97f4 9833 if (path->peer->hostname)
515c2602
DA
9834 json_object_string_add(
9835 json_nexthop_global, "hostname",
939a97f4 9836 path->peer->hostname);
aef999a2
DA
9837 } else {
9838 if (nexthop_hostname)
9839 vty_out(vty, " %pI4(%s)",
9840 &attr->nexthop,
9841 nexthop_hostname);
9842 else
9843 vty_out(vty, " %pI4",
9844 &attr->nexthop);
9845 }
d62a17ae 9846 }
9847
05864da7
DS
9848 if (json_paths)
9849 json_object_string_add(json_nexthop_global, "afi",
9850 "ipv4");
9851 } else {
9852 if (json_paths) {
9853 json_object_string_add(
515c2602
DA
9854 json_nexthop_global, "ip",
9855 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9856 buf, INET6_ADDRSTRLEN));
9857
939a97f4 9858 if (path->peer->hostname)
515c2602
DA
9859 json_object_string_add(json_nexthop_global,
9860 "hostname",
939a97f4 9861 path->peer->hostname);
515c2602 9862
05864da7
DS
9863 json_object_string_add(json_nexthop_global, "afi",
9864 "ipv6");
9865 json_object_string_add(json_nexthop_global, "scope",
9866 "global");
9867 } else {
aef999a2
DA
9868 if (nexthop_hostname)
9869 vty_out(vty, " %pI6(%s)",
9870 &attr->mp_nexthop_global,
9871 nexthop_hostname);
9872 else
9873 vty_out(vty, " %pI6",
9874 &attr->mp_nexthop_global);
d62a17ae 9875 }
05864da7 9876 }
d62a17ae 9877
05864da7
DS
9878 /* Display the IGP cost or 'inaccessible' */
9879 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9880 if (json_paths)
9881 json_object_boolean_false_add(json_nexthop_global,
9882 "accessible");
9883 else
9884 vty_out(vty, " (inaccessible)");
9885 } else {
9886 if (path->extra && path->extra->igpmetric) {
d62a17ae 9887 if (json_paths)
05864da7
DS
9888 json_object_int_add(json_nexthop_global,
9889 "metric",
9890 path->extra->igpmetric);
d62a17ae 9891 else
05864da7
DS
9892 vty_out(vty, " (metric %u)",
9893 path->extra->igpmetric);
d62a17ae 9894 }
9895
05864da7 9896 /* IGP cost is 0, display this only for json */
d62a17ae 9897 else {
d62a17ae 9898 if (json_paths)
05864da7
DS
9899 json_object_int_add(json_nexthop_global,
9900 "metric", 0);
d62a17ae 9901 }
d62a17ae 9902
05864da7
DS
9903 if (json_paths)
9904 json_object_boolean_true_add(json_nexthop_global,
9905 "accessible");
9906 }
d62a17ae 9907
05864da7
DS
9908 /* Display peer "from" output */
9909 /* This path was originated locally */
9910 if (path->peer == bgp->peer_self) {
d62a17ae 9911
05864da7 9912 if (safi == SAFI_EVPN
b54892e0 9913 || (bn_p->family == AF_INET
05864da7 9914 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9915 if (json_paths)
05864da7
DS
9916 json_object_string_add(json_peer, "peerId",
9917 "0.0.0.0");
d62a17ae 9918 else
05864da7
DS
9919 vty_out(vty, " from 0.0.0.0 ");
9920 } else {
d62a17ae 9921 if (json_paths)
05864da7
DS
9922 json_object_string_add(json_peer, "peerId",
9923 "::");
d62a17ae 9924 else
05864da7 9925 vty_out(vty, " from :: ");
d62a17ae 9926 }
d62a17ae 9927
23d0a753
DA
9928 if (json_paths) {
9929 char buf[BUFSIZ] = {0};
9930
05864da7 9931 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9932 inet_ntop(AF_INET,
9933 &bgp->router_id, buf,
9934 sizeof(buf)));
9935 } else {
9936 vty_out(vty, "(%pI4)", &bgp->router_id);
9937 }
05864da7 9938 }
d62a17ae 9939
05864da7
DS
9940 /* We RXed this path from one of our peers */
9941 else {
9942
9943 if (json_paths) {
9944 json_object_string_add(json_peer, "peerId",
9945 sockunion2str(&path->peer->su,
9946 buf,
9947 SU_ADDRSTRLEN));
9948 json_object_string_add(json_peer, "routerId",
9949 inet_ntop(AF_INET,
9950 &path->peer->remote_id,
9951 buf1, sizeof(buf1)));
9952
9953 if (path->peer->hostname)
9954 json_object_string_add(json_peer, "hostname",
9955 path->peer->hostname);
9956
9957 if (path->peer->domainname)
9958 json_object_string_add(json_peer, "domainname",
9959 path->peer->domainname);
9960
9961 if (path->peer->conf_if)
9962 json_object_string_add(json_peer, "interface",
9963 path->peer->conf_if);
9964 } else {
9965 if (path->peer->conf_if) {
9966 if (path->peer->hostname
892fedb6
DA
9967 && CHECK_FLAG(path->peer->bgp->flags,
9968 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9969 vty_out(vty, " from %s(%s)",
9970 path->peer->hostname,
9971 path->peer->conf_if);
d62a17ae 9972 else
05864da7 9973 vty_out(vty, " from %s",
9b6d8fcf 9974 path->peer->conf_if);
d62a17ae 9975 } else {
05864da7 9976 if (path->peer->hostname
892fedb6
DA
9977 && CHECK_FLAG(path->peer->bgp->flags,
9978 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9979 vty_out(vty, " from %s(%s)",
9980 path->peer->hostname,
9981 path->peer->host);
d62a17ae 9982 else
05864da7
DS
9983 vty_out(vty, " from %s",
9984 sockunion2str(&path->peer->su,
9985 buf,
9986 SU_ADDRSTRLEN));
d62a17ae 9987 }
d62a17ae 9988
05864da7 9989 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9990 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9991 else
9992 vty_out(vty, " (%s)",
9993 inet_ntop(AF_INET,
9994 &path->peer->remote_id, buf1,
9995 sizeof(buf1)));
d62a17ae 9996 }
05864da7 9997 }
9df8b37c 9998
05864da7
DS
9999 /*
10000 * Note when vrfid of nexthop is different from that of prefix
10001 */
10002 if (path->extra && path->extra->bgp_orig) {
10003 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10004
05864da7
DS
10005 if (json_paths) {
10006 const char *vn;
9df8b37c 10007
05864da7
DS
10008 if (path->extra->bgp_orig->inst_type
10009 == BGP_INSTANCE_TYPE_DEFAULT)
10010 vn = VRF_DEFAULT_NAME;
10011 else
10012 vn = path->extra->bgp_orig->name;
9df8b37c 10013
05864da7 10014 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10015
05864da7
DS
10016 if (nexthop_vrfid == VRF_UNKNOWN) {
10017 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10018 } else {
05864da7
DS
10019 json_object_int_add(json_path, "nhVrfId",
10020 (int)nexthop_vrfid);
9df8b37c 10021 }
05864da7
DS
10022 } else {
10023 if (nexthop_vrfid == VRF_UNKNOWN)
10024 vty_out(vty, " vrf ?");
137147c6
DS
10025 else {
10026 struct vrf *vrf;
10027
10028 vrf = vrf_lookup_by_id(nexthop_vrfid);
10029 vty_out(vty, " vrf %s(%u)",
10030 VRF_LOGNAME(vrf), nexthop_vrfid);
10031 }
9df8b37c 10032 }
05864da7 10033 }
9df8b37c 10034
05864da7
DS
10035 if (nexthop_self) {
10036 if (json_paths) {
10037 json_object_boolean_true_add(json_path,
10038 "announceNexthopSelf");
10039 } else {
10040 vty_out(vty, " announce-nh-self");
9df8b37c 10041 }
05864da7 10042 }
9df8b37c 10043
05864da7
DS
10044 if (!json_paths)
10045 vty_out(vty, "\n");
d62a17ae 10046
05864da7
DS
10047 /* display the link-local nexthop */
10048 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10049 if (json_paths) {
10050 json_nexthop_ll = json_object_new_object();
10051 json_object_string_add(
515c2602
DA
10052 json_nexthop_ll, "ip",
10053 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10054 buf, INET6_ADDRSTRLEN));
10055
939a97f4 10056 if (path->peer->hostname)
515c2602
DA
10057 json_object_string_add(json_nexthop_ll,
10058 "hostname",
939a97f4 10059 path->peer->hostname);
515c2602 10060
05864da7
DS
10061 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10062 json_object_string_add(json_nexthop_ll, "scope",
10063 "link-local");
d62a17ae 10064
05864da7
DS
10065 json_object_boolean_true_add(json_nexthop_ll,
10066 "accessible");
d62a17ae 10067
05864da7 10068 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10069 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10070 "used");
10071 else
10072 json_object_boolean_true_add(
10073 json_nexthop_global, "used");
10074 } else {
10075 vty_out(vty, " (%s) %s\n",
10076 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10077 buf, INET6_ADDRSTRLEN),
10078 attr->mp_nexthop_prefer_global
10079 ? "(prefer-global)"
10080 : "(used)");
d62a17ae 10081 }
05864da7
DS
10082 }
10083 /* If we do not have a link-local nexthop then we must flag the
10084 global as "used" */
10085 else {
10086 if (json_paths)
10087 json_object_boolean_true_add(json_nexthop_global,
10088 "used");
10089 }
d62a17ae 10090
b5e140c8 10091 if (safi == SAFI_EVPN &&
5e4d4c8a 10092 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10093 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10094 }
10095
05864da7
DS
10096 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10097 * Int/Ext/Local, Atomic, best */
10098 if (json_paths)
10099 json_object_string_add(json_path, "origin",
10100 bgp_origin_long_str[attr->origin]);
10101 else
10102 vty_out(vty, " Origin %s",
10103 bgp_origin_long_str[attr->origin]);
9df8b37c 10104
05864da7 10105 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10106 if (json_paths)
05864da7 10107 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10108 else
05864da7
DS
10109 vty_out(vty, ", metric %u", attr->med);
10110 }
9df8b37c 10111
05864da7
DS
10112 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10113 if (json_paths)
0fbac0b4 10114 json_object_int_add(json_path, "locPrf",
05864da7
DS
10115 attr->local_pref);
10116 else
10117 vty_out(vty, ", localpref %u", attr->local_pref);
10118 }
9df8b37c 10119
05864da7
DS
10120 if (attr->weight != 0) {
10121 if (json_paths)
10122 json_object_int_add(json_path, "weight", attr->weight);
10123 else
10124 vty_out(vty, ", weight %u", attr->weight);
10125 }
9df8b37c 10126
05864da7
DS
10127 if (attr->tag != 0) {
10128 if (json_paths)
10129 json_object_int_add(json_path, "tag", attr->tag);
10130 else
10131 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10132 }
9df8b37c 10133
05864da7
DS
10134 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10135 if (json_paths)
10136 json_object_boolean_false_add(json_path, "valid");
10137 else
10138 vty_out(vty, ", invalid");
10139 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10140 if (json_paths)
10141 json_object_boolean_true_add(json_path, "valid");
10142 else
10143 vty_out(vty, ", valid");
10144 }
9df8b37c 10145
7d3cae70
DA
10146 if (json_paths)
10147 json_object_int_add(json_path, "version", bn->version);
10148
05864da7
DS
10149 if (path->peer != bgp->peer_self) {
10150 if (path->peer->as == path->peer->local_as) {
10151 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10152 if (json_paths)
10153 json_object_string_add(
10154 json_peer, "type",
10155 "confed-internal");
d62a17ae 10156 else
05864da7 10157 vty_out(vty, ", confed-internal");
d62a17ae 10158 } else {
05864da7
DS
10159 if (json_paths)
10160 json_object_string_add(
10161 json_peer, "type", "internal");
10162 else
10163 vty_out(vty, ", internal");
9df8b37c 10164 }
05864da7
DS
10165 } else {
10166 if (bgp_confederation_peers_check(bgp,
10167 path->peer->as)) {
10168 if (json_paths)
10169 json_object_string_add(
10170 json_peer, "type",
10171 "confed-external");
d62a17ae 10172 else
05864da7 10173 vty_out(vty, ", confed-external");
d62a17ae 10174 } else {
05864da7
DS
10175 if (json_paths)
10176 json_object_string_add(
10177 json_peer, "type", "external");
10178 else
10179 vty_out(vty, ", external");
d62a17ae 10180 }
10181 }
05864da7
DS
10182 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10183 if (json_paths) {
10184 json_object_boolean_true_add(json_path, "aggregated");
10185 json_object_boolean_true_add(json_path, "local");
10186 } else {
10187 vty_out(vty, ", aggregated, local");
10188 }
10189 } else if (path->type != ZEBRA_ROUTE_BGP) {
10190 if (json_paths)
10191 json_object_boolean_true_add(json_path, "sourced");
10192 else
10193 vty_out(vty, ", sourced");
10194 } else {
10195 if (json_paths) {
10196 json_object_boolean_true_add(json_path, "sourced");
10197 json_object_boolean_true_add(json_path, "local");
10198 } else {
10199 vty_out(vty, ", sourced, local");
d62a17ae 10200 }
05864da7 10201 }
718e3744 10202
05864da7 10203 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10204 if (json_paths)
05864da7
DS
10205 json_object_boolean_true_add(json_path,
10206 "atomicAggregate");
d62a17ae 10207 else
05864da7
DS
10208 vty_out(vty, ", atomic-aggregate");
10209 }
d62a17ae 10210
05864da7
DS
10211 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10212 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10213 && bgp_path_info_mpath_count(path))) {
10214 if (json_paths)
10215 json_object_boolean_true_add(json_path, "multipath");
10216 else
10217 vty_out(vty, ", multipath");
10218 }
50e05855 10219
05864da7
DS
10220 // Mark the bestpath(s)
10221 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10222 first_as = aspath_get_first_as(attr->aspath);
718e3744 10223
05864da7
DS
10224 if (json_paths) {
10225 if (!json_bestpath)
10226 json_bestpath = json_object_new_object();
10227 json_object_int_add(json_bestpath, "bestpathFromAs",
10228 first_as);
10229 } else {
10230 if (first_as)
10231 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10232 else
05864da7 10233 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10234 }
05864da7 10235 }
718e3744 10236
05864da7
DS
10237 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10238 if (json_paths) {
10239 if (!json_bestpath)
10240 json_bestpath = json_object_new_object();
10241 json_object_boolean_true_add(json_bestpath, "overall");
10242 json_object_string_add(
10243 json_bestpath, "selectionReason",
10244 bgp_path_selection_reason2str(bn->reason));
10245 } else {
10246 vty_out(vty, ", best");
10247 vty_out(vty, " (%s)",
10248 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10249 }
05864da7 10250 }
718e3744 10251
4027d19b 10252 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10253 if (json_paths)
10254 json_object_string_add(
10255 json_path, "rpkiValidationState",
4027d19b 10256 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10257 else
1d327209 10258 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10259 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10260 }
10261
05864da7
DS
10262 if (json_bestpath)
10263 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10264
05864da7
DS
10265 if (!json_paths)
10266 vty_out(vty, "\n");
10267
10268 /* Line 4 display Community */
29e72930 10269 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10270 if (json_paths) {
10271 if (!attr->community->json)
10272 community_str(attr->community, true);
10273 json_object_lock(attr->community->json);
10274 json_object_object_add(json_path, "community",
10275 attr->community->json);
10276 } else {
10277 vty_out(vty, " Community: %s\n",
10278 attr->community->str);
d62a17ae 10279 }
05864da7 10280 }
718e3744 10281
05864da7
DS
10282 /* Line 5 display Extended-community */
10283 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10284 if (json_paths) {
10285 json_ext_community = json_object_new_object();
10286 json_object_string_add(json_ext_community, "string",
10287 attr->ecommunity->str);
10288 json_object_object_add(json_path, "extendedCommunity",
10289 json_ext_community);
d62a17ae 10290 } else {
05864da7
DS
10291 vty_out(vty, " Extended Community: %s\n",
10292 attr->ecommunity->str);
d62a17ae 10293 }
05864da7 10294 }
718e3744 10295
05864da7
DS
10296 /* Line 6 display Large community */
10297 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10298 if (json_paths) {
10299 if (!attr->lcommunity->json)
10300 lcommunity_str(attr->lcommunity, true);
10301 json_object_lock(attr->lcommunity->json);
10302 json_object_object_add(json_path, "largeCommunity",
10303 attr->lcommunity->json);
10304 } else {
10305 vty_out(vty, " Large Community: %s\n",
10306 attr->lcommunity->str);
d62a17ae 10307 }
05864da7 10308 }
718e3744 10309
05864da7
DS
10310 /* Line 7 display Originator, Cluster-id */
10311 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10312 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10313 char buf[BUFSIZ] = {0};
10314
05864da7 10315 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10316 if (json_paths)
05864da7
DS
10317 json_object_string_add(
10318 json_path, "originatorId",
23d0a753
DA
10319 inet_ntop(AF_INET, &attr->originator_id,
10320 buf, sizeof(buf)));
d62a17ae 10321 else
23d0a753
DA
10322 vty_out(vty, " Originator: %pI4",
10323 &attr->originator_id);
d62a17ae 10324 }
856ca177 10325
05864da7 10326 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10327 struct cluster_list *cluster =
10328 bgp_attr_get_cluster(attr);
05864da7 10329 int i;
d62a17ae 10330
10331 if (json_paths) {
05864da7
DS
10332 json_cluster_list = json_object_new_object();
10333 json_cluster_list_list =
10334 json_object_new_array();
10335
779fee93 10336 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10337 json_string = json_object_new_string(
779fee93
DS
10338 inet_ntop(AF_INET,
10339 &cluster->list[i],
10340 buf, sizeof(buf)));
05864da7
DS
10341 json_object_array_add(
10342 json_cluster_list_list,
10343 json_string);
10344 }
718e3744 10345
05864da7
DS
10346 /*
10347 * struct cluster_list does not have
10348 * "str" variable like aspath and community
10349 * do. Add this someday if someone asks
10350 * for it.
10351 * json_object_string_add(json_cluster_list,
779fee93 10352 * "string", cluster->str);
05864da7
DS
10353 */
10354 json_object_object_add(json_cluster_list,
10355 "list",
10356 json_cluster_list_list);
10357 json_object_object_add(json_path, "clusterList",
10358 json_cluster_list);
0dc8ee70 10359 } else {
05864da7
DS
10360 vty_out(vty, ", Cluster list: ");
10361
779fee93 10362 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10363 vty_out(vty, "%pI4 ",
779fee93 10364 &cluster->list[i]);
05864da7 10365 }
0dc8ee70 10366 }
d62a17ae 10367 }
718e3744 10368
d62a17ae 10369 if (!json_paths)
10370 vty_out(vty, "\n");
05864da7 10371 }
d62a17ae 10372
05864da7 10373 if (path->extra && path->extra->damp_info)
40ec3340 10374 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10375
05864da7
DS
10376 /* Remote Label */
10377 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10378 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10379 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10380
05864da7
DS
10381 if (json_paths)
10382 json_object_int_add(json_path, "remoteLabel", label);
10383 else
10384 vty_out(vty, " Remote label: %d\n", label);
10385 }
d62a17ae 10386
e496b420
HS
10387 /* Remote SID */
10388 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10389 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10390 if (json_paths)
10391 json_object_string_add(json_path, "remoteSid", buf);
10392 else
10393 vty_out(vty, " Remote SID: %s\n", buf);
10394 }
10395
05864da7
DS
10396 /* Label Index */
10397 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10398 if (json_paths)
10399 json_object_int_add(json_path, "labelIndex",
10400 attr->label_index);
10401 else
10402 vty_out(vty, " Label Index: %d\n",
10403 attr->label_index);
10404 }
d62a17ae 10405
05864da7
DS
10406 /* Line 8 display Addpath IDs */
10407 if (path->addpath_rx_id
10408 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10409 if (json_paths) {
10410 json_object_int_add(json_path, "addpathRxId",
10411 path->addpath_rx_id);
d62a17ae 10412
05864da7
DS
10413 /* Keep backwards compatibility with the old API
10414 * by putting TX All's ID in the old field
10415 */
10416 json_object_int_add(
10417 json_path, "addpathTxId",
10418 path->tx_addpath
10419 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10420
05864da7
DS
10421 /* ... but create a specific field for each
10422 * strategy
10423 */
10424 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10425 json_object_int_add(
10426 json_path,
10427 bgp_addpath_names(i)->id_json_name,
10428 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10429 }
05864da7
DS
10430 } else {
10431 vty_out(vty, " AddPath ID: RX %u, ",
10432 path->addpath_rx_id);
d62a17ae 10433
05864da7 10434 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10435 }
05864da7 10436 }
520d5d76 10437
05864da7
DS
10438 /* If we used addpath to TX a non-bestpath we need to display
10439 * "Advertised to" on a path-by-path basis
10440 */
10441 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10442 first = 1;
dcc68b5e 10443
05864da7
DS
10444 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10445 addpath_capable =
10446 bgp_addpath_encode_tx(peer, afi, safi);
10447 has_adj = bgp_adj_out_lookup(
10448 peer, path->net,
10449 bgp_addpath_id_for_peer(peer, afi, safi,
10450 &path->tx_addpath));
10451
10452 if ((addpath_capable && has_adj)
10453 || (!addpath_capable && has_adj
10454 && CHECK_FLAG(path->flags,
10455 BGP_PATH_SELECTED))) {
10456 if (json_path && !json_adv_to)
10457 json_adv_to = json_object_new_object();
dcc68b5e 10458
05864da7
DS
10459 route_vty_out_advertised_to(
10460 vty, peer, &first,
10461 " Advertised to:", json_adv_to);
d62a17ae 10462 }
10463 }
718e3744 10464
05864da7
DS
10465 if (json_path) {
10466 if (json_adv_to) {
10467 json_object_object_add(
10468 json_path, "advertisedTo", json_adv_to);
d62a17ae 10469 }
05864da7
DS
10470 } else {
10471 if (!first) {
10472 vty_out(vty, "\n");
d62a17ae 10473 }
10474 }
05864da7 10475 }
b05a1c8b 10476
05864da7
DS
10477 /* Line 9 display Uptime */
10478 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10479 if (json_paths) {
10480 json_last_update = json_object_new_object();
10481 json_object_int_add(json_last_update, "epoch", tbuf);
10482 json_object_string_add(json_last_update, "string",
10483 ctime(&tbuf));
10484 json_object_object_add(json_path, "lastUpdate",
10485 json_last_update);
10486 } else
10487 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10488
05864da7
DS
10489 /* Line 10 display PMSI tunnel attribute, if present */
10490 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10491 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10492 bgp_attr_get_pmsi_tnl_type(attr),
10493 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10494
05864da7
DS
10495 if (json_paths) {
10496 json_pmsi = json_object_new_object();
10497 json_object_string_add(json_pmsi, "tunnelType", str);
10498 json_object_int_add(json_pmsi, "label",
10499 label2vni(&attr->label));
10500 json_object_object_add(json_path, "pmsi", json_pmsi);
10501 } else
10502 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10503 str, label2vni(&attr->label));
d62a17ae 10504 }
f1aa5d8a 10505
92269aa2
DS
10506 /* Output some debug about internal state of the dest flags */
10507 if (json_paths) {
10508 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10509 json_object_boolean_true_add(json_path, "processScheduled");
10510 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10511 json_object_boolean_true_add(json_path, "userCleared");
10512 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10513 json_object_boolean_true_add(json_path, "labelChanged");
10514 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10515 json_object_boolean_true_add(json_path, "registeredForLabel");
10516 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10517 json_object_boolean_true_add(json_path, "selectDefered");
10518 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10519 json_object_boolean_true_add(json_path, "fibInstalled");
10520 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10521 json_object_boolean_true_add(json_path, "fibPending");
10522 }
10523
d62a17ae 10524 /* We've constructed the json object for this path, add it to the json
10525 * array of paths
10526 */
10527 if (json_paths) {
10528 if (json_nexthop_global || json_nexthop_ll) {
10529 json_nexthops = json_object_new_array();
f1aa5d8a 10530
d62a17ae 10531 if (json_nexthop_global)
10532 json_object_array_add(json_nexthops,
10533 json_nexthop_global);
f1aa5d8a 10534
d62a17ae 10535 if (json_nexthop_ll)
10536 json_object_array_add(json_nexthops,
10537 json_nexthop_ll);
f1aa5d8a 10538
d62a17ae 10539 json_object_object_add(json_path, "nexthops",
10540 json_nexthops);
10541 }
10542
10543 json_object_object_add(json_path, "peer", json_peer);
10544 json_object_array_add(json_paths, json_path);
05864da7 10545 }
b366b518
BB
10546}
10547
96ade3ed 10548#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10549#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10550#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10551
d62a17ae 10552static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10553 const char *prefix_list_str, afi_t afi,
10554 safi_t safi, enum bgp_show_type type);
10555static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10556 const char *filter, afi_t afi, safi_t safi,
10557 enum bgp_show_type type);
10558static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10559 const char *rmap_str, afi_t afi, safi_t safi,
10560 enum bgp_show_type type);
10561static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10562 const char *com, int exact, afi_t afi,
10563 safi_t safi);
10564static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10565 const char *prefix, afi_t afi, safi_t safi,
10566 enum bgp_show_type type);
a4d82a8a 10567static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10568 afi_t afi, safi_t safi, enum bgp_show_type type,
10569 bool use_json);
7f323236
DW
10570static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10571 const char *comstr, int exact, afi_t afi,
96f3485c 10572 safi_t safi, uint8_t show_flags);
d62a17ae 10573
1ae44dfc 10574static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10575 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10576 void *output_arg, char *rd, int is_last,
10577 unsigned long *output_cum, unsigned long *total_cum,
1e2ce4f1 10578 unsigned long *json_header_depth, uint8_t show_flags,
4027d19b 10579 enum rpki_states rpki_target_state)
d62a17ae 10580{
40381db7 10581 struct bgp_path_info *pi;
9bcb3eef 10582 struct bgp_dest *dest;
d62a17ae 10583 int header = 1;
10584 int display;
1ae44dfc
LB
10585 unsigned long output_count = 0;
10586 unsigned long total_count = 0;
d62a17ae 10587 struct prefix *p;
d62a17ae 10588 json_object *json_paths = NULL;
10589 int first = 1;
96f3485c
MK
10590 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10591 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10592 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10593
1ae44dfc
LB
10594 if (output_cum && *output_cum != 0)
10595 header = 0;
10596
9386b588 10597 if (use_json && !*json_header_depth) {
96f3485c
MK
10598 if (all)
10599 *json_header_depth = 1;
10600 else {
10601 vty_out(vty, "{\n");
10602 *json_header_depth = 2;
10603 }
10604
d62a17ae 10605 vty_out(vty,
23d0a753
DA
10606 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10607 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10608 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10609 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10610 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10611 ? VRF_DEFAULT_NAME
10612 : bgp->name,
10613 table->version, &bgp->router_id,
01eced22 10614 bgp->default_local_pref, bgp->as);
9386b588 10615 if (rd) {
445c2480 10616 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10617 ++*json_header_depth;
10618 }
d62a17ae 10619 }
718e3744 10620
445c2480
DS
10621 if (use_json && rd) {
10622 vty_out(vty, " \"%s\" : { ", rd);
10623 }
10624
d62a17ae 10625 /* Start processing of routes. */
9bcb3eef
DS
10626 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10627 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10628 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
b54892e0 10629
9bcb3eef 10630 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10631 if (pi == NULL)
98ce9a06 10632 continue;
d62a17ae 10633
98ce9a06 10634 display = 0;
98ce9a06
DS
10635 if (use_json)
10636 json_paths = json_object_new_array();
10637 else
10638 json_paths = NULL;
d62a17ae 10639
6f94b685 10640 for (; pi; pi = pi->next) {
98ce9a06 10641 total_count++;
1e2ce4f1 10642
7d3cae70
DA
10643 if (type == bgp_show_type_prefix_version) {
10644 uint32_t version =
10645 strtoul(output_arg, NULL, 10);
10646 if (dest->version < version)
10647 continue;
10648 }
10649
a70a28a5
DA
10650 if (type == bgp_show_type_community_alias) {
10651 char *alias = output_arg;
10652 char **communities;
10653 int num;
10654 bool found = false;
10655
10656 if (pi->attr->community) {
10657 frrstr_split(pi->attr->community->str,
10658 " ", &communities, &num);
10659 for (int i = 0; i < num; i++) {
10660 const char *com2alias =
10661 bgp_community2alias(
10662 communities[i]);
10663 if (strncmp(alias, com2alias,
10664 strlen(com2alias))
10665 == 0) {
10666 found = true;
10667 break;
10668 }
10669 }
10670 }
10671
10672 if (!found && pi->attr->lcommunity) {
10673 frrstr_split(pi->attr->lcommunity->str,
10674 " ", &communities, &num);
10675 for (int i = 0; i < num; i++) {
10676 const char *com2alias =
10677 bgp_community2alias(
10678 communities[i]);
10679 if (strncmp(alias, com2alias,
10680 strlen(com2alias))
10681 == 0) {
10682 found = true;
10683 break;
10684 }
10685 }
10686 }
10687
10688 if (!found)
10689 continue;
10690 }
10691
1e2ce4f1
DS
10692 if (type == bgp_show_type_rpki) {
10693 if (dest_p->family == AF_INET
10694 || dest_p->family == AF_INET6)
4027d19b 10695 rpki_curr_state = hook_call(
1e2ce4f1
DS
10696 bgp_rpki_prefix_status,
10697 pi->peer, pi->attr, dest_p);
4027d19b
DS
10698 if (rpki_target_state != RPKI_NOT_BEING_USED
10699 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10700 continue;
10701 }
10702
98ce9a06
DS
10703 if (type == bgp_show_type_flap_statistics
10704 || type == bgp_show_type_flap_neighbor
10705 || type == bgp_show_type_dampend_paths
10706 || type == bgp_show_type_damp_neighbor) {
40381db7 10707 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10708 continue;
10709 }
10710 if (type == bgp_show_type_regexp) {
10711 regex_t *regex = output_arg;
d62a17ae 10712
40381db7 10713 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10714 == REG_NOMATCH)
10715 continue;
10716 }
10717 if (type == bgp_show_type_prefix_list) {
10718 struct prefix_list *plist = output_arg;
d62a17ae 10719
9bcb3eef 10720 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10721 != PREFIX_PERMIT)
10722 continue;
10723 }
10724 if (type == bgp_show_type_filter_list) {
10725 struct as_list *as_list = output_arg;
d62a17ae 10726
40381db7 10727 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10728 != AS_FILTER_PERMIT)
10729 continue;
10730 }
10731 if (type == bgp_show_type_route_map) {
10732 struct route_map *rmap = output_arg;
9b6d8fcf 10733 struct bgp_path_info path;
98ce9a06 10734 struct attr dummy_attr;
b68885f9 10735 route_map_result_t ret;
d62a17ae 10736
6f4f49b2 10737 dummy_attr = *pi->attr;
d62a17ae 10738
40381db7 10739 path.peer = pi->peer;
9b6d8fcf 10740 path.attr = &dummy_attr;
d62a17ae 10741
1782514f 10742 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10743 if (ret == RMAP_DENYMATCH)
10744 continue;
10745 }
10746 if (type == bgp_show_type_neighbor
10747 || type == bgp_show_type_flap_neighbor
10748 || type == bgp_show_type_damp_neighbor) {
10749 union sockunion *su = output_arg;
10750
40381db7
DS
10751 if (pi->peer == NULL
10752 || pi->peer->su_remote == NULL
10753 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10754 continue;
10755 }
10756 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10757 uint32_t destination;
d62a17ae 10758
9bcb3eef 10759 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10760 if (IN_CLASSC(destination)
9bcb3eef 10761 && dest_p->prefixlen == 24)
98ce9a06
DS
10762 continue;
10763 if (IN_CLASSB(destination)
9bcb3eef 10764 && dest_p->prefixlen == 16)
98ce9a06
DS
10765 continue;
10766 if (IN_CLASSA(destination)
9bcb3eef 10767 && dest_p->prefixlen == 8)
98ce9a06
DS
10768 continue;
10769 }
10770 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10771 p = output_arg;
9bcb3eef 10772 if (!prefix_match(p, dest_p))
98ce9a06
DS
10773 continue;
10774 }
10775 if (type == bgp_show_type_community_all) {
40381db7 10776 if (!pi->attr->community)
98ce9a06
DS
10777 continue;
10778 }
10779 if (type == bgp_show_type_community) {
10780 struct community *com = output_arg;
d62a17ae 10781
40381db7
DS
10782 if (!pi->attr->community
10783 || !community_match(pi->attr->community,
98ce9a06
DS
10784 com))
10785 continue;
10786 }
10787 if (type == bgp_show_type_community_exact) {
10788 struct community *com = output_arg;
d62a17ae 10789
40381db7
DS
10790 if (!pi->attr->community
10791 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10792 continue;
10793 }
10794 if (type == bgp_show_type_community_list) {
10795 struct community_list *list = output_arg;
d62a17ae 10796
40381db7 10797 if (!community_list_match(pi->attr->community,
a4d82a8a 10798 list))
98ce9a06
DS
10799 continue;
10800 }
a4d82a8a 10801 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10802 struct community_list *list = output_arg;
d62a17ae 10803
98ce9a06 10804 if (!community_list_exact_match(
40381db7 10805 pi->attr->community, list))
98ce9a06
DS
10806 continue;
10807 }
10808 if (type == bgp_show_type_lcommunity) {
10809 struct lcommunity *lcom = output_arg;
d62a17ae 10810
40381db7
DS
10811 if (!pi->attr->lcommunity
10812 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10813 lcom))
10814 continue;
10815 }
36a206db 10816
10817 if (type == bgp_show_type_lcommunity_exact) {
10818 struct lcommunity *lcom = output_arg;
10819
10820 if (!pi->attr->lcommunity
10821 || !lcommunity_cmp(pi->attr->lcommunity,
10822 lcom))
10823 continue;
10824 }
98ce9a06
DS
10825 if (type == bgp_show_type_lcommunity_list) {
10826 struct community_list *list = output_arg;
d62a17ae 10827
40381db7 10828 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10829 list))
98ce9a06
DS
10830 continue;
10831 }
36a206db 10832 if (type
10833 == bgp_show_type_lcommunity_list_exact) {
10834 struct community_list *list = output_arg;
10835
10836 if (!lcommunity_list_exact_match(
10837 pi->attr->lcommunity, list))
10838 continue;
10839 }
98ce9a06 10840 if (type == bgp_show_type_lcommunity_all) {
40381db7 10841 if (!pi->attr->lcommunity)
98ce9a06
DS
10842 continue;
10843 }
10844 if (type == bgp_show_type_dampend_paths
10845 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10846 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10847 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10848 continue;
10849 }
10850
10851 if (!use_json && header) {
23d0a753
DA
10852 vty_out(vty,
10853 "BGP table version is %" PRIu64
10854 ", local router ID is %pI4, vrf id ",
10855 table->version, &bgp->router_id);
9df8b37c
PZ
10856 if (bgp->vrf_id == VRF_UNKNOWN)
10857 vty_out(vty, "%s", VRFID_NONE_STR);
10858 else
10859 vty_out(vty, "%u", bgp->vrf_id);
10860 vty_out(vty, "\n");
01eced22
AD
10861 vty_out(vty, "Default local pref %u, ",
10862 bgp->default_local_pref);
10863 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10864 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10865 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10866 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 10867 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 10868 if (type == bgp_show_type_dampend_paths
10869 || type == bgp_show_type_damp_neighbor)
98ce9a06 10870 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10871 else if (type == bgp_show_type_flap_statistics
10872 || type == bgp_show_type_flap_neighbor)
98ce9a06 10873 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10874 else
ae248832
MK
10875 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10876 : BGP_SHOW_HEADER));
98ce9a06 10877 header = 0;
d62a17ae 10878 }
98ce9a06
DS
10879 if (rd != NULL && !display && !output_count) {
10880 if (!use_json)
10881 vty_out(vty,
10882 "Route Distinguisher: %s\n",
10883 rd);
d62a17ae 10884 }
98ce9a06
DS
10885 if (type == bgp_show_type_dampend_paths
10886 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10887 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10888 AFI_IP, safi, use_json,
10889 json_paths);
98ce9a06
DS
10890 else if (type == bgp_show_type_flap_statistics
10891 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10892 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10893 AFI_IP, safi, use_json,
10894 json_paths);
f280c93b
DA
10895 else {
10896 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
10897 route_vty_out_detail(
10898 vty, bgp, dest, pi,
10899 family2afi(dest_p->family),
10900 safi, RPKI_NOT_BEING_USED,
10901 json_paths);
10902 else
10903 route_vty_out(vty, dest_p, pi, display,
10904 safi, json_paths, wide);
10905 }
98ce9a06 10906 display++;
d62a17ae 10907 }
10908
98ce9a06
DS
10909 if (display) {
10910 output_count++;
10911 if (!use_json)
10912 continue;
10913
625d2931 10914 /* encode prefix */
9bcb3eef 10915 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10916 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10917
1840384b 10918
b54892e0
DS
10919 bgp_fs_nlri_get_string(
10920 (unsigned char *)
9bcb3eef
DS
10921 dest_p->u.prefix_flowspec.ptr,
10922 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10923 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10924 family2afi(dest_p->u
10925 .prefix_flowspec.family));
625d2931 10926 if (first)
b54892e0 10927 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10928 dest_p->u.prefix_flowspec
b54892e0 10929 .prefixlen);
625d2931 10930 else
b54892e0 10931 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10932 dest_p->u.prefix_flowspec
b54892e0 10933 .prefixlen);
625d2931 10934 } else {
625d2931 10935 if (first)
1b78780b 10936 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10937 else
1b78780b 10938 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10939 }
98ce9a06 10940 vty_out(vty, "%s",
f4ec52f7
DA
10941 json_object_to_json_string_ext(
10942 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10943 json_object_free(json_paths);
449feb8e 10944 json_paths = NULL;
98ce9a06 10945 first = 0;
1f83ed02
DS
10946 } else
10947 json_object_free(json_paths);
98ce9a06
DS
10948 }
10949
1ae44dfc
LB
10950 if (output_cum) {
10951 output_count += *output_cum;
10952 *output_cum = output_count;
10953 }
10954 if (total_cum) {
10955 total_count += *total_cum;
10956 *total_cum = total_count;
10957 }
d62a17ae 10958 if (use_json) {
9386b588 10959 if (rd) {
a4d82a8a 10960 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10961 }
10962 if (is_last) {
a4d82a8a
PZ
10963 unsigned long i;
10964 for (i = 0; i < *json_header_depth; ++i)
10965 vty_out(vty, " } ");
96f3485c
MK
10966 if (!all)
10967 vty_out(vty, "\n");
9386b588 10968 }
d62a17ae 10969 } else {
1ae44dfc
LB
10970 if (is_last) {
10971 /* No route is displayed */
10972 if (output_count == 0) {
10973 if (type == bgp_show_type_normal)
10974 vty_out(vty,
10975 "No BGP prefixes displayed, %ld exist\n",
10976 total_count);
10977 } else
d62a17ae 10978 vty_out(vty,
1ae44dfc
LB
10979 "\nDisplayed %ld routes and %ld total paths\n",
10980 output_count, total_count);
10981 }
d62a17ae 10982 }
718e3744 10983
d62a17ae 10984 return CMD_SUCCESS;
718e3744 10985}
10986
1ae44dfc
LB
10987int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10988 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10989 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10990{
9bcb3eef 10991 struct bgp_dest *dest, *next;
1ae44dfc
LB
10992 unsigned long output_cum = 0;
10993 unsigned long total_cum = 0;
9386b588 10994 unsigned long json_header_depth = 0;
67009e22 10995 struct bgp_table *itable;
0136788c 10996 bool show_msg;
96f3485c 10997 uint8_t show_flags = 0;
0136788c
LB
10998
10999 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11000
96f3485c
MK
11001 if (use_json)
11002 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11003
9bcb3eef
DS
11004 for (dest = bgp_table_top(table); dest; dest = next) {
11005 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11006
9bcb3eef
DS
11007 next = bgp_route_next(dest);
11008 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11009 continue;
67009e22 11010
9bcb3eef 11011 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11012 if (itable != NULL) {
1ae44dfc 11013 struct prefix_rd prd;
06b9f471 11014 char rd[RD_ADDRSTRLEN];
1ae44dfc 11015
9bcb3eef 11016 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11017 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11018 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11019 rd, next == NULL, &output_cum,
11020 &total_cum, &json_header_depth,
1e2ce4f1 11021 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11022 if (next == NULL)
11023 show_msg = false;
1ae44dfc
LB
11024 }
11025 }
0136788c
LB
11026 if (show_msg) {
11027 if (output_cum == 0)
11028 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11029 total_cum);
11030 else
11031 vty_out(vty,
11032 "\nDisplayed %ld routes and %ld total paths\n",
11033 output_cum, total_cum);
11034 }
1ae44dfc
LB
11035 return CMD_SUCCESS;
11036}
d62a17ae 11037static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11038 enum bgp_show_type type, void *output_arg,
4027d19b 11039 uint8_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11040{
d62a17ae 11041 struct bgp_table *table;
9386b588 11042 unsigned long json_header_depth = 0;
96f3485c 11043 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11044
d62a17ae 11045 if (bgp == NULL) {
11046 bgp = bgp_get_default();
11047 }
fee0f4c6 11048
d62a17ae 11049 if (bgp == NULL) {
11050 if (!use_json)
11051 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11052 else
11053 vty_out(vty, "{}\n");
d62a17ae 11054 return CMD_WARNING;
11055 }
4dd6177e 11056
1ae44dfc 11057 table = bgp->rib[afi][safi];
d62a17ae 11058 /* use MPLS and ENCAP specific shows until they are merged */
11059 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11060 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11061 output_arg, use_json);
d62a17ae 11062 }
dba3c1d3
PG
11063
11064 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11065 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11066 output_arg, use_json,
11067 1, NULL, NULL);
11068 }
d62a17ae 11069 /* labeled-unicast routes live in the unicast table */
11070 else if (safi == SAFI_LABELED_UNICAST)
11071 safi = SAFI_UNICAST;
fee0f4c6 11072
96f3485c 11073 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11074 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11075 rpki_target_state);
fee0f4c6 11076}
11077
d62a17ae 11078static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 11079 safi_t safi, uint8_t show_flags)
f186de26 11080{
d62a17ae 11081 struct listnode *node, *nnode;
11082 struct bgp *bgp;
11083 int is_first = 1;
9f049418 11084 bool route_output = false;
96f3485c 11085 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11086
d62a17ae 11087 if (use_json)
11088 vty_out(vty, "{\n");
9f689658 11089
d62a17ae 11090 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11091 route_output = true;
d62a17ae 11092 if (use_json) {
11093 if (!is_first)
11094 vty_out(vty, ",\n");
11095 else
11096 is_first = 0;
11097
11098 vty_out(vty, "\"%s\":",
11099 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11100 ? VRF_DEFAULT_NAME
d62a17ae 11101 : bgp->name);
11102 } else {
11103 vty_out(vty, "\nInstance %s:\n",
11104 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11105 ? VRF_DEFAULT_NAME
d62a17ae 11106 : bgp->name);
11107 }
11108 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11109 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11110 }
9f689658 11111
d62a17ae 11112 if (use_json)
11113 vty_out(vty, "}\n");
9f049418
DS
11114 else if (!route_output)
11115 vty_out(vty, "%% BGP instance not found\n");
f186de26 11116}
11117
718e3744 11118/* Header of detailed BGP route information */
d62a17ae 11119void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 11120 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 11121 afi_t afi, safi_t safi, json_object *json)
11122{
40381db7 11123 struct bgp_path_info *pi;
b54892e0 11124 const struct prefix *p;
d62a17ae 11125 struct peer *peer;
11126 struct listnode *node, *nnode;
06b9f471 11127 char buf1[RD_ADDRSTRLEN];
0291c246 11128 char prefix_str[BUFSIZ];
d62a17ae 11129 int count = 0;
11130 int best = 0;
11131 int suppress = 0;
c5f1e1b2
C
11132 int accept_own = 0;
11133 int route_filter_translated_v4 = 0;
11134 int route_filter_v4 = 0;
11135 int route_filter_translated_v6 = 0;
11136 int route_filter_v6 = 0;
11137 int llgr_stale = 0;
11138 int no_llgr = 0;
11139 int accept_own_nexthop = 0;
11140 int blackhole = 0;
d62a17ae 11141 int no_export = 0;
11142 int no_advertise = 0;
11143 int local_as = 0;
c5f1e1b2 11144 int no_peer = 0;
d62a17ae 11145 int first = 1;
11146 int has_valid_label = 0;
11147 mpls_label_t label = 0;
11148 json_object *json_adv_to = NULL;
9bedbb1e 11149
9bcb3eef
DS
11150 p = bgp_dest_get_prefix(dest);
11151 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11152
11153 if (has_valid_label)
9bcb3eef 11154 label = label_pton(&dest->local_label);
d62a17ae 11155
44c69747 11156 if (safi == SAFI_EVPN) {
d62a17ae 11157
44c69747 11158 if (!json) {
2dbe669b 11159 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11160 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11161 : "",
2dbe669b 11162 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11163 } else {
11164 json_object_string_add(json, "rd",
11165 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11166 "");
11167 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11168 }
11169 } else {
11170 if (!json) {
9119ef3a
DA
11171 vty_out(vty,
11172 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11173 "\n",
d62a17ae 11174 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11175 ? prefix_rd2str(prd, buf1,
11176 sizeof(buf1))
11177 : ""),
9119ef3a
DA
11178 safi == SAFI_MPLS_VPN ? ":" : "", p,
11179 dest->version);
cd1964ff 11180
9119ef3a 11181 } else {
44c69747
LK
11182 json_object_string_add(json, "prefix",
11183 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11184 json_object_int_add(json, "version", dest->version);
11185
11186 }
44c69747
LK
11187 }
11188
11189 if (has_valid_label) {
11190 if (json)
11191 json_object_int_add(json, "localLabel", label);
11192 else
d62a17ae 11193 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11194 }
11195
11196 if (!json)
d62a17ae 11197 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11198 vty_out(vty, "not allocated\n");
718e3744 11199
9bcb3eef 11200 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11201 count++;
40381db7 11202 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11203 best = count;
4056a5f6 11204 if (bgp_path_suppressed(pi))
d62a17ae 11205 suppress = 1;
cee9c031 11206
40381db7 11207 if (pi->attr->community == NULL)
cee9c031
QY
11208 continue;
11209
11210 no_advertise += community_include(
40381db7
DS
11211 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11212 no_export += community_include(pi->attr->community,
cee9c031 11213 COMMUNITY_NO_EXPORT);
40381db7 11214 local_as += community_include(pi->attr->community,
cee9c031 11215 COMMUNITY_LOCAL_AS);
40381db7 11216 accept_own += community_include(pi->attr->community,
cee9c031
QY
11217 COMMUNITY_ACCEPT_OWN);
11218 route_filter_translated_v4 += community_include(
40381db7 11219 pi->attr->community,
cee9c031
QY
11220 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11221 route_filter_translated_v6 += community_include(
40381db7 11222 pi->attr->community,
cee9c031
QY
11223 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11224 route_filter_v4 += community_include(
40381db7 11225 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11226 route_filter_v6 += community_include(
40381db7
DS
11227 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11228 llgr_stale += community_include(pi->attr->community,
cee9c031 11229 COMMUNITY_LLGR_STALE);
40381db7 11230 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11231 COMMUNITY_NO_LLGR);
11232 accept_own_nexthop +=
40381db7 11233 community_include(pi->attr->community,
cee9c031 11234 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11235 blackhole += community_include(pi->attr->community,
cee9c031 11236 COMMUNITY_BLACKHOLE);
40381db7 11237 no_peer += community_include(pi->attr->community,
cee9c031 11238 COMMUNITY_NO_PEER);
d62a17ae 11239 }
718e3744 11240 }
718e3744 11241
d62a17ae 11242 if (!json) {
11243 vty_out(vty, "Paths: (%d available", count);
11244 if (best) {
11245 vty_out(vty, ", best #%d", best);
b84060bb
PG
11246 if (safi == SAFI_UNICAST) {
11247 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11248 vty_out(vty, ", table %s",
11249 VRF_DEFAULT_NAME);
11250 else
11251 vty_out(vty, ", vrf %s",
11252 bgp->name);
11253 }
d62a17ae 11254 } else
11255 vty_out(vty, ", no best path");
11256
c5f1e1b2
C
11257 if (accept_own)
11258 vty_out(vty,
11259 ", accept own local route exported and imported in different VRF");
11260 else if (route_filter_translated_v4)
11261 vty_out(vty,
11262 ", mark translated RTs for VPNv4 route filtering");
11263 else if (route_filter_v4)
11264 vty_out(vty,
11265 ", attach RT as-is for VPNv4 route filtering");
11266 else if (route_filter_translated_v6)
11267 vty_out(vty,
11268 ", mark translated RTs for VPNv6 route filtering");
11269 else if (route_filter_v6)
11270 vty_out(vty,
11271 ", attach RT as-is for VPNv6 route filtering");
11272 else if (llgr_stale)
11273 vty_out(vty,
11274 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11275 else if (no_llgr)
11276 vty_out(vty,
11277 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11278 else if (accept_own_nexthop)
11279 vty_out(vty,
11280 ", accept local nexthop");
11281 else if (blackhole)
11282 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11283 else if (no_export)
11284 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11285 else if (no_advertise)
11286 vty_out(vty, ", not advertised to any peer");
d62a17ae 11287 else if (local_as)
11288 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11289 else if (no_peer)
11290 vty_out(vty,
11291 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11292
11293 if (suppress)
11294 vty_out(vty,
11295 ", Advertisements suppressed by an aggregate.");
11296 vty_out(vty, ")\n");
11297 }
718e3744 11298
d62a17ae 11299 /* If we are not using addpath then we can display Advertised to and
11300 * that will
11301 * show what peers we advertised the bestpath to. If we are using
11302 * addpath
11303 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11304 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11305 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11306 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11307 if (json && !json_adv_to)
11308 json_adv_to = json_object_new_object();
11309
11310 route_vty_out_advertised_to(
11311 vty, peer, &first,
11312 " Advertised to non peer-group peers:\n ",
11313 json_adv_to);
11314 }
11315 }
11316
11317 if (json) {
11318 if (json_adv_to) {
11319 json_object_object_add(json, "advertisedTo",
11320 json_adv_to);
11321 }
11322 } else {
11323 if (first)
11324 vty_out(vty, " Not advertised to any peer");
11325 vty_out(vty, "\n");
11326 }
11327 }
718e3744 11328}
11329
44c69747 11330static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11331 struct bgp_dest *bgp_node, struct vty *vty,
11332 struct bgp *bgp, afi_t afi, safi_t safi,
11333 json_object *json, enum bgp_path_type pathtype,
4027d19b 11334 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11335{
11336 struct bgp_path_info *pi;
11337 int header = 1;
11338 char rdbuf[RD_ADDRSTRLEN];
11339 json_object *json_header = NULL;
11340 json_object *json_paths = NULL;
4933eaaf 11341 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11342
9bcb3eef 11343 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11344 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11345
11346 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11347 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11348 pi->peer, pi->attr, p);
4933eaaf 11349
4027d19b
DS
11350 if (rpki_target_state != RPKI_NOT_BEING_USED
11351 && rpki_curr_state != rpki_target_state)
4933eaaf 11352 continue;
44c69747
LK
11353
11354 if (json && !json_paths) {
11355 /* Instantiate json_paths only if path is valid */
11356 json_paths = json_object_new_array();
11357 if (pfx_rd) {
11358 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11359 json_header = json_object_new_object();
11360 } else
11361 json_header = json;
11362 }
11363
11364 if (header) {
11365 route_vty_out_detail_header(
11366 vty, bgp, bgp_node, pfx_rd,
11367 AFI_IP, safi, json_header);
11368 header = 0;
11369 }
11370 (*display)++;
11371
11372 if (pathtype == BGP_PATH_SHOW_ALL
11373 || (pathtype == BGP_PATH_SHOW_BESTPATH
11374 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11375 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11376 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11377 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11378 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11379 safi, rpki_curr_state, json_paths);
44c69747
LK
11380 }
11381
11382 if (json && json_paths) {
11383 json_object_object_add(json_header, "paths", json_paths);
11384
11385 if (pfx_rd)
11386 json_object_object_add(json, rdbuf, json_header);
11387 }
11388}
11389
718e3744 11390/* Display specified route of BGP table. */
d62a17ae 11391static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11392 struct bgp_table *rib, const char *ip_str,
11393 afi_t afi, safi_t safi,
4027d19b 11394 enum rpki_states rpki_target_state,
d62a17ae 11395 struct prefix_rd *prd, int prefix_check,
9f049418 11396 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11397{
11398 int ret;
d62a17ae 11399 int display = 0;
11400 struct prefix match;
9bcb3eef
DS
11401 struct bgp_dest *dest;
11402 struct bgp_dest *rm;
d62a17ae 11403 struct bgp_table *table;
11404 json_object *json = NULL;
11405 json_object *json_paths = NULL;
11406
11407 /* Check IP address argument. */
11408 ret = str2prefix(ip_str, &match);
11409 if (!ret) {
11410 vty_out(vty, "address is malformed\n");
11411 return CMD_WARNING;
11412 }
718e3744 11413
d62a17ae 11414 match.family = afi2family(afi);
b05a1c8b 11415
44c69747 11416 if (use_json)
d62a17ae 11417 json = json_object_new_object();
718e3744 11418
44c69747 11419 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11420 for (dest = bgp_table_top(rib); dest;
11421 dest = bgp_route_next(dest)) {
11422 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11423
9bcb3eef 11424 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11425 continue;
9bcb3eef 11426 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11427 if (!table)
ea47320b 11428 continue;
d62a17ae 11429
ea47320b
DL
11430 if ((rm = bgp_node_match(table, &match)) == NULL)
11431 continue;
d62a17ae 11432
9bcb3eef 11433 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11434 if (prefix_check
b54892e0 11435 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11436 bgp_dest_unlock_node(rm);
ea47320b
DL
11437 continue;
11438 }
d62a17ae 11439
9bcb3eef 11440 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11441 bgp, afi, safi, json, pathtype,
4027d19b 11442 &display, rpki_target_state);
44c69747 11443
9bcb3eef 11444 bgp_dest_unlock_node(rm);
44c69747
LK
11445 }
11446 } else if (safi == SAFI_EVPN) {
9bcb3eef 11447 struct bgp_dest *longest_pfx;
cded3b72 11448 bool is_exact_pfxlen_match = false;
44c69747 11449
9bcb3eef
DS
11450 for (dest = bgp_table_top(rib); dest;
11451 dest = bgp_route_next(dest)) {
11452 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11453
9bcb3eef 11454 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11455 continue;
9bcb3eef 11456 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11457 if (!table)
11458 continue;
11459
11460 longest_pfx = NULL;
cded3b72 11461 is_exact_pfxlen_match = false;
44c69747
LK
11462 /*
11463 * Search through all the prefixes for a match. The
11464 * pfx's are enumerated in ascending order of pfxlens.
11465 * So, the last pfx match is the longest match. Set
11466 * is_exact_pfxlen_match when we get exact pfxlen match
11467 */
11468 for (rm = bgp_table_top(table); rm;
11469 rm = bgp_route_next(rm)) {
b54892e0 11470 const struct prefix *rm_p =
9bcb3eef 11471 bgp_dest_get_prefix(rm);
44c69747
LK
11472 /*
11473 * Get prefixlen of the ip-prefix within type5
11474 * evpn route
11475 */
b54892e0
DS
11476 if (evpn_type5_prefix_match(rm_p, &match)
11477 && rm->info) {
44c69747
LK
11478 longest_pfx = rm;
11479 int type5_pfxlen =
b54892e0
DS
11480 bgp_evpn_get_type5_prefixlen(
11481 rm_p);
44c69747 11482 if (type5_pfxlen == match.prefixlen) {
cded3b72 11483 is_exact_pfxlen_match = true;
9bcb3eef 11484 bgp_dest_unlock_node(rm);
44c69747
LK
11485 break;
11486 }
d62a17ae 11487 }
11488 }
ea47320b 11489
44c69747
LK
11490 if (!longest_pfx)
11491 continue;
11492
11493 if (prefix_check && !is_exact_pfxlen_match)
11494 continue;
11495
11496 rm = longest_pfx;
9bcb3eef 11497 bgp_dest_lock_node(rm);
44c69747 11498
9bcb3eef 11499 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11500 bgp, afi, safi, json, pathtype,
4027d19b 11501 &display, rpki_target_state);
44c69747 11502
9bcb3eef 11503 bgp_dest_unlock_node(rm);
d62a17ae 11504 }
98a9dbc7 11505 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11506 if (use_json)
11507 json_paths = json_object_new_array();
11508
63a0b7a9
PG
11509 display = bgp_flowspec_display_match_per_ip(afi, rib,
11510 &match, prefix_check,
11511 vty,
11512 use_json,
11513 json_paths);
d5f20468
SP
11514 if (use_json) {
11515 if (display)
11516 json_object_object_add(json, "paths",
11517 json_paths);
11518 else
11519 json_object_free(json_paths);
11520 }
d62a17ae 11521 } else {
9bcb3eef
DS
11522 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11523 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11524 if (!prefix_check
9bcb3eef
DS
11525 || dest_p->prefixlen == match.prefixlen) {
11526 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11527 safi, json, pathtype,
4027d19b 11528 &display, rpki_target_state);
d62a17ae 11529 }
11530
9bcb3eef 11531 bgp_dest_unlock_node(dest);
d62a17ae 11532 }
11533 }
e5eee9af 11534
d62a17ae 11535 if (use_json) {
996c9314 11536 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11537 json, JSON_C_TO_STRING_PRETTY |
11538 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11539 json_object_free(json);
11540 } else {
11541 if (!display) {
11542 vty_out(vty, "%% Network not in table\n");
11543 return CMD_WARNING;
11544 }
11545 }
b05a1c8b 11546
d62a17ae 11547 return CMD_SUCCESS;
718e3744 11548}
11549
fee0f4c6 11550/* Display specified route of Main RIB */
d62a17ae 11551static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11552 afi_t afi, safi_t safi, struct prefix_rd *prd,
11553 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11554 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11555{
9b86009a 11556 if (!bgp) {
d62a17ae 11557 bgp = bgp_get_default();
9b86009a
RW
11558 if (!bgp) {
11559 if (!use_json)
11560 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11561 else
11562 vty_out(vty, "{}\n");
9b86009a
RW
11563 return CMD_WARNING;
11564 }
11565 }
d62a17ae 11566
11567 /* labeled-unicast routes live in the unicast table */
11568 if (safi == SAFI_LABELED_UNICAST)
11569 safi = SAFI_UNICAST;
11570
11571 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11572 afi, safi, rpki_target_state, prd,
8aa22bbb 11573 prefix_check, pathtype, use_json);
d62a17ae 11574}
11575
11576static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11577 struct cmd_token **argv, bool exact, afi_t afi,
11578 safi_t safi, bool uj)
d62a17ae 11579{
11580 struct lcommunity *lcom;
11581 struct buffer *b;
11582 int i;
11583 char *str;
11584 int first = 0;
96f3485c 11585 uint8_t show_flags = 0;
4f28b2b5 11586 int ret;
96f3485c
MK
11587
11588 if (uj)
11589 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11590
11591 b = buffer_new(1024);
11592 for (i = 0; i < argc; i++) {
11593 if (first)
11594 buffer_putc(b, ' ');
11595 else {
11596 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11597 first = 1;
11598 buffer_putstr(b, argv[i]->arg);
11599 }
11600 }
11601 }
11602 buffer_putc(b, '\0');
57d187bc 11603
d62a17ae 11604 str = buffer_getstr(b);
11605 buffer_free(b);
57d187bc 11606
d62a17ae 11607 lcom = lcommunity_str2com(str);
11608 XFREE(MTYPE_TMP, str);
11609 if (!lcom) {
11610 vty_out(vty, "%% Large-community malformed\n");
11611 return CMD_WARNING;
11612 }
57d187bc 11613
4f28b2b5 11614 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11615 (exact ? bgp_show_type_lcommunity_exact
11616 : bgp_show_type_lcommunity),
11617 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11618
11619 lcommunity_free(&lcom);
11620 return ret;
57d187bc
JS
11621}
11622
d62a17ae 11623static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11624 const char *lcom, bool exact, afi_t afi,
11625 safi_t safi, bool uj)
57d187bc 11626{
d62a17ae 11627 struct community_list *list;
96f3485c
MK
11628 uint8_t show_flags = 0;
11629
11630 if (uj)
11631 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11632
57d187bc 11633
e237b0d2 11634 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11635 LARGE_COMMUNITY_LIST_MASTER);
11636 if (list == NULL) {
11637 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11638 lcom);
11639 return CMD_WARNING;
11640 }
57d187bc 11641
36a206db 11642 return bgp_show(vty, bgp, afi, safi,
11643 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11644 : bgp_show_type_lcommunity_list),
1e2ce4f1 11645 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11646}
11647
52951b63
DS
11648DEFUN (show_ip_bgp_large_community_list,
11649 show_ip_bgp_large_community_list_cmd,
36a206db 11650 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
52951b63
DS
11651 SHOW_STR
11652 IP_STR
11653 BGP_STR
11654 BGP_INSTANCE_HELP_STR
9bedbb1e 11655 BGP_AFI_HELP_STR
4dd6177e 11656 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11657 "Display routes matching the large-community-list\n"
11658 "large-community-list number\n"
11659 "large-community-list name\n"
36a206db 11660 "Exact match of the large-communities\n"
52951b63
DS
11661 JSON_STR)
11662{
d62a17ae 11663 afi_t afi = AFI_IP6;
11664 safi_t safi = SAFI_UNICAST;
11665 int idx = 0;
36a206db 11666 bool exact_match = 0;
4d678463 11667 struct bgp *bgp = NULL;
9f049418 11668 bool uj = use_json(argc, argv);
d62a17ae 11669
ef3364f0
DA
11670 if (uj)
11671 argc--;
4d678463 11672
ef3364f0
DA
11673 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11674 &bgp, uj);
11675 if (!idx)
11676 return CMD_WARNING;
d62a17ae 11677
11678 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11679
11680 const char *clist_number_or_name = argv[++idx]->arg;
11681
11682 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11683 exact_match = 1;
11684
11685 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11686 exact_match, afi, safi, uj);
52951b63
DS
11687}
11688DEFUN (show_ip_bgp_large_community,
11689 show_ip_bgp_large_community_cmd,
36a206db 11690 "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
11691 SHOW_STR
11692 IP_STR
11693 BGP_STR
11694 BGP_INSTANCE_HELP_STR
9bedbb1e 11695 BGP_AFI_HELP_STR
4dd6177e 11696 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11697 "Display routes matching the large-communities\n"
11698 "List of large-community numbers\n"
36a206db 11699 "Exact match of the large-communities\n"
52951b63
DS
11700 JSON_STR)
11701{
d62a17ae 11702 afi_t afi = AFI_IP6;
11703 safi_t safi = SAFI_UNICAST;
11704 int idx = 0;
36a206db 11705 bool exact_match = 0;
4d678463 11706 struct bgp *bgp = NULL;
9f049418 11707 bool uj = use_json(argc, argv);
96f3485c 11708 uint8_t show_flags = 0;
d62a17ae 11709
96f3485c
MK
11710 if (uj) {
11711 argc--;
11712 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11713 }
4d678463 11714
96f3485c
MK
11715 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11716 &bgp, uj);
11717 if (!idx)
11718 return CMD_WARNING;
d62a17ae 11719
36a206db 11720 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11721 if (argv_find(argv, argc, "exact-match", &idx))
11722 exact_match = 1;
11723 return bgp_show_lcommunity(vty, bgp, argc, argv,
11724 exact_match, afi, safi, uj);
11725 } else
d62a17ae 11726 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11727 bgp_show_type_lcommunity_all, NULL, show_flags,
11728 RPKI_NOT_BEING_USED);
52951b63
DS
11729}
11730
71f1613a
DA
11731static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11732 safi_t safi, struct json_object *json_array);
d62a17ae 11733static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11734 safi_t safi, struct json_object *json);
e01ca200 11735
7b2ff250 11736
9ab0cf58
PG
11737DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11738 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11739 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11740 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11741{
11742 bool uj = use_json(argc, argv);
11743 struct bgp *bgp = NULL;
ec76a1d1
DA
11744 safi_t safi = SAFI_UNICAST;
11745 afi_t afi = AFI_IP6;
4265b261 11746 int idx = 0;
6c9d22e2
PG
11747 struct json_object *json_all = NULL;
11748 struct json_object *json_afi_safi = NULL;
4265b261
PG
11749
11750 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11751 &bgp, false);
71f1613a 11752 if (!idx)
4265b261 11753 return CMD_WARNING;
6c9d22e2 11754
4265b261 11755 if (uj)
6c9d22e2 11756 json_all = json_object_new_object();
4265b261 11757
9ab0cf58
PG
11758 FOREACH_AFI_SAFI (afi, safi) {
11759 /*
11760 * So limit output to those afi/safi pairs that
11761 * actually have something interesting in them
11762 */
11763 if (strmatch(get_afi_safi_str(afi, safi, true),
11764 "Unknown")) {
11765 continue;
11766 }
11767 if (uj) {
11768 json_afi_safi = json_object_new_array();
11769 json_object_object_add(
11770 json_all,
11771 get_afi_safi_str(afi, safi, true),
11772 json_afi_safi);
11773 } else {
11774 json_afi_safi = NULL;
6c9d22e2 11775 }
9ab0cf58
PG
11776
11777 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11778 }
6c9d22e2
PG
11779
11780 if (uj) {
9ab0cf58
PG
11781 vty_out(vty, "%s",
11782 json_object_to_json_string_ext(
11783 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11784 json_object_free(json_all);
4265b261 11785 }
6c9d22e2 11786
4265b261
PG
11787 return CMD_SUCCESS;
11788}
11789
7b2ff250 11790/* BGP route print out function without JSON */
14718643
PG
11791DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11792 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11793 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11794 SHOW_STR
11795 IP_STR
11796 BGP_STR
11797 BGP_INSTANCE_HELP_STR
11798 L2VPN_HELP_STR
11799 EVPN_HELP_STR
11800 "BGP RIB advertisement statistics\n"
11801 JSON_STR)
11802{
ec76a1d1
DA
11803 afi_t afi = AFI_IP6;
11804 safi_t safi = SAFI_UNICAST;
14718643
PG
11805 struct bgp *bgp = NULL;
11806 int idx = 0, ret;
11807 bool uj = use_json(argc, argv);
11808 struct json_object *json_afi_safi = NULL, *json = NULL;
11809
11810 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11811 &bgp, false);
11812 if (!idx)
11813 return CMD_WARNING;
11814
11815 if (uj)
11816 json_afi_safi = json_object_new_array();
11817 else
11818 json_afi_safi = NULL;
11819
11820 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11821
11822 if (uj) {
11823 json = json_object_new_object();
11824 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11825 json_afi_safi);
11826 vty_out(vty, "%s", json_object_to_json_string_ext(
11827 json, JSON_C_TO_STRING_PRETTY));
11828 json_object_free(json);
11829 }
11830 return ret;
11831}
11832
893cccd0 11833/* BGP route print out function without JSON */
9ab0cf58
PG
11834DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11835 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11836 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11837 "]]\
893cccd0 11838 statistics [json]",
9ab0cf58
PG
11839 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11840 BGP_SAFI_WITH_LABEL_HELP_STR
11841 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11842{
ec76a1d1
DA
11843 afi_t afi = AFI_IP6;
11844 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11845 struct bgp *bgp = NULL;
11846 int idx = 0, ret;
11847 bool uj = use_json(argc, argv);
6c9d22e2 11848 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11849
11850 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11851 &bgp, false);
11852 if (!idx)
11853 return CMD_WARNING;
6c9d22e2 11854
893cccd0 11855 if (uj)
6c9d22e2
PG
11856 json_afi_safi = json_object_new_array();
11857 else
11858 json_afi_safi = NULL;
11859
11860 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11861
11862 if (uj) {
11863 json = json_object_new_object();
11864 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11865 json_afi_safi);
9ab0cf58
PG
11866 vty_out(vty, "%s",
11867 json_object_to_json_string_ext(
11868 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11869 json_object_free(json);
11870 }
11871 return ret;
893cccd0 11872}
7b2ff250
DW
11873
11874/* BGP route print out function without JSON */
96f3485c 11875DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11876 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11877 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11878 "]]\
96f3485c 11879 <[all$all] dampening <parameters>\
7b2ff250
DW
11880 |route-map WORD\
11881 |prefix-list WORD\
11882 |filter-list WORD\
7b2ff250
DW
11883 |community-list <(1-500)|WORD> [exact-match]\
11884 |A.B.C.D/M longer-prefixes\
11885 |X:X::X:X/M longer-prefixes\
893cccd0 11886 >",
9ab0cf58
PG
11887 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11888 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11889 "Display the entries for all address families\n"
9ab0cf58
PG
11890 "Display detailed information about dampening\n"
11891 "Display detail of configured dampening parameters\n"
11892 "Display routes matching the route-map\n"
11893 "A route-map to match on\n"
11894 "Display routes conforming to the prefix-list\n"
11895 "Prefix-list name\n"
11896 "Display routes conforming to the filter-list\n"
11897 "Regular expression access list name\n"
11898 "Display routes matching the community-list\n"
11899 "community-list number\n"
11900 "community-list name\n"
11901 "Exact match of the communities\n"
11902 "IPv4 prefix\n"
11903 "Display route and more specific routes\n"
11904 "IPv6 prefix\n"
11905 "Display route and more specific routes\n")
718e3744 11906{
d62a17ae 11907 afi_t afi = AFI_IP6;
11908 safi_t safi = SAFI_UNICAST;
11909 int exact_match = 0;
d62a17ae 11910 struct bgp *bgp = NULL;
11911 int idx = 0;
96f3485c
MK
11912 uint8_t show_flags = 0;
11913
11914 /* [<ipv4|ipv6> [all]] */
11915 if (all) {
11916 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11917 if (argv_find(argv, argc, "ipv4", &idx))
11918 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11919
11920 if (argv_find(argv, argc, "ipv6", &idx))
11921 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11922 }
d62a17ae 11923
11924 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11925 &bgp, false);
d62a17ae 11926 if (!idx)
11927 return CMD_WARNING;
11928
d62a17ae 11929 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11930 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11931 return bgp_show_dampening_parameters(vty, afi, safi,
11932 show_flags);
d62a17ae 11933 }
c016b6c7 11934
d62a17ae 11935 if (argv_find(argv, argc, "prefix-list", &idx))
11936 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11937 safi, bgp_show_type_prefix_list);
11938
11939 if (argv_find(argv, argc, "filter-list", &idx))
11940 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11941 safi, bgp_show_type_filter_list);
11942
d62a17ae 11943 if (argv_find(argv, argc, "route-map", &idx))
11944 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11945 safi, bgp_show_type_route_map);
11946
d62a17ae 11947 if (argv_find(argv, argc, "community-list", &idx)) {
11948 const char *clist_number_or_name = argv[++idx]->arg;
11949 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11950 exact_match = 1;
11951 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11952 exact_match, afi, safi);
11953 }
11954 /* prefix-longer */
11955 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11956 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11957 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11958 safi,
11959 bgp_show_type_prefix_longer);
11960
7b2ff250
DW
11961 return CMD_WARNING;
11962}
11963
11964/* BGP route print out function with JSON */
a70a28a5
DA
11965DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
11966 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11967 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11968 "]]\
96f3485c 11969 [all$all]\
cf4898bc
QY
11970 [cidr-only\
11971 |dampening <flap-statistics|dampened-paths>\
11972 |community [AA:NN|local-AS|no-advertise|no-export\
11973 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11974 |accept-own|accept-own-nexthop|route-filter-v6\
11975 |route-filter-v4|route-filter-translated-v6\
11976 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 11977 |rpki <invalid|valid|notfound>\
7d3cae70 11978 |version (1-4294967295)\
a70a28a5 11979 |alias WORD\
f280c93b 11980 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
11981 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11982 BGP_SAFI_WITH_LABEL_HELP_STR
11983 "Display the entries for all address families\n"
11984 "Display only routes with non-natural netmasks\n"
11985 "Display detailed information about dampening\n"
11986 "Display flap statistics of routes\n"
11987 "Display paths suppressed due to dampening\n"
11988 "Display routes matching the communities\n" COMMUNITY_AANN_STR
11989 "Do not send outside local AS (well-known community)\n"
11990 "Do not advertise to any peer (well-known community)\n"
11991 "Do not export to next AS (well-known community)\n"
11992 "Graceful shutdown (well-known community)\n"
11993 "Do not export to any peer (well-known community)\n"
11994 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11995 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11996 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11997 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11998 "Should accept VPN route with local nexthop (well-known community)\n"
11999 "RT VPNv6 route filtering (well-known community)\n"
12000 "RT VPNv4 route filtering (well-known community)\n"
12001 "RT translated VPNv6 route filtering (well-known community)\n"
12002 "RT translated VPNv4 route filtering (well-known community)\n"
12003 "Exact match of the communities\n"
12004 "RPKI route types\n"
12005 "A valid path as determined by rpki\n"
12006 "A invalid path as determined by rpki\n"
12007 "A path that has no rpki data\n"
12008 "Display prefixes with matching version numbers\n"
12009 "Version number and above\n"
12010 "Display prefixes with matching BGP community alias\n"
12011 "BGP community alias\n" JSON_STR
12012 "Display detailed version of JSON output\n"
12013 "Increase table width for longer prefixes\n")
7b2ff250
DW
12014{
12015 afi_t afi = AFI_IP6;
12016 safi_t safi = SAFI_UNICAST;
12017 enum bgp_show_type sh_type = bgp_show_type_normal;
12018 struct bgp *bgp = NULL;
12019 int idx = 0;
d0086e8e 12020 int exact_match = 0;
96f3485c 12021 char *community = NULL;
7d3cae70 12022 char *prefix_version = NULL;
a70a28a5 12023 char *bgp_community_alias = NULL;
96f3485c
MK
12024 bool first = true;
12025 uint8_t show_flags = 0;
4027d19b 12026 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12027
12028 if (uj) {
9f049418 12029 argc--;
96f3485c
MK
12030 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12031 }
12032
f280c93b
DA
12033 if (detail)
12034 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12035
96f3485c
MK
12036 /* [<ipv4|ipv6> [all]] */
12037 if (all) {
12038 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12039
12040 if (argv_find(argv, argc, "ipv4", &idx))
12041 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12042
12043 if (argv_find(argv, argc, "ipv6", &idx))
12044 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12045 }
12046
12047 if (wide)
12048 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12049
12050 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12051 &bgp, uj);
7b2ff250
DW
12052 if (!idx)
12053 return CMD_WARNING;
12054
7b2ff250 12055 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12056 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12057
12058 if (argv_find(argv, argc, "dampening", &idx)) {
12059 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12060 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12061 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12062 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12063 }
12064
12065 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12066 char *maybecomm = NULL;
d0086e8e 12067
79bc257a
RW
12068 if (idx + 1 < argc) {
12069 if (argv[idx + 1]->type == VARIABLE_TKN)
12070 maybecomm = argv[idx + 1]->arg;
12071 else
12072 maybecomm = argv[idx + 1]->text;
12073 }
12074
cf4898bc
QY
12075 if (maybecomm && !strmatch(maybecomm, "json")
12076 && !strmatch(maybecomm, "exact-match"))
12077 community = maybecomm;
d0086e8e 12078
cf4898bc
QY
12079 if (argv_find(argv, argc, "exact-match", &idx))
12080 exact_match = 1;
d0086e8e 12081
96f3485c
MK
12082 if (!community)
12083 sh_type = bgp_show_type_community_all;
12084 }
12085
1e2ce4f1
DS
12086 if (argv_find(argv, argc, "rpki", &idx)) {
12087 sh_type = bgp_show_type_rpki;
12088 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12089 rpki_target_state = RPKI_VALID;
1e2ce4f1 12090 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12091 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12092 }
12093
7d3cae70
DA
12094 /* Display prefixes with matching version numbers */
12095 if (argv_find(argv, argc, "version", &idx)) {
12096 sh_type = bgp_show_type_prefix_version;
12097 prefix_version = argv[idx + 1]->arg;
12098 }
12099
a70a28a5
DA
12100 /* Display prefixes with matching BGP community alias */
12101 if (argv_find(argv, argc, "alias", &idx)) {
12102 sh_type = bgp_show_type_community_alias;
12103 bgp_community_alias = argv[idx + 1]->arg;
12104 }
12105
96f3485c
MK
12106 if (!all) {
12107 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12108 if (community)
12109 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12110 exact_match, afi, safi,
12111 show_flags);
7d3cae70
DA
12112 else if (prefix_version)
12113 return bgp_show(vty, bgp, afi, safi, sh_type,
12114 prefix_version, show_flags,
12115 rpki_target_state);
a70a28a5
DA
12116 else if (bgp_community_alias)
12117 return bgp_show(vty, bgp, afi, safi, sh_type,
12118 bgp_community_alias, show_flags,
12119 rpki_target_state);
cf4898bc 12120 else
96f3485c 12121 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12122 show_flags, rpki_target_state);
96f3485c
MK
12123 } else {
12124 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12125 * AFI_IP6 */
12126
12127 if (uj)
12128 vty_out(vty, "{\n");
12129
12130 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12131 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12132 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12133 ? AFI_IP
12134 : AFI_IP6;
12135 FOREACH_SAFI (safi) {
96f3485c
MK
12136 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12137 continue;
12138
12139 if (uj) {
12140 if (first)
12141 first = false;
12142 else
12143 vty_out(vty, ",\n");
12144 vty_out(vty, "\"%s\":{\n",
12145 get_afi_safi_str(afi, safi,
12146 true));
12147 } else
12148 vty_out(vty,
12149 "\nFor address family: %s\n",
12150 get_afi_safi_str(afi, safi,
12151 false));
12152
12153 if (community)
12154 bgp_show_community(vty, bgp, community,
12155 exact_match, afi,
12156 safi, show_flags);
7d3cae70
DA
12157 else if (prefix_version)
12158 return bgp_show(vty, bgp, afi, safi,
12159 sh_type, prefix_version,
12160 show_flags,
12161 rpki_target_state);
a70a28a5
DA
12162 else if (bgp_community_alias)
12163 return bgp_show(
12164 vty, bgp, afi, safi, sh_type,
12165 bgp_community_alias, show_flags,
12166 rpki_target_state);
96f3485c
MK
12167 else
12168 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12169 NULL, show_flags,
4027d19b 12170 rpki_target_state);
96f3485c
MK
12171 if (uj)
12172 vty_out(vty, "}\n");
12173 }
12174 } else {
12175 /* show <ip> bgp all: for each AFI and SAFI*/
12176 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12177 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12178 continue;
12179
12180 if (uj) {
12181 if (first)
12182 first = false;
12183 else
12184 vty_out(vty, ",\n");
d0086e8e 12185
96f3485c
MK
12186 vty_out(vty, "\"%s\":{\n",
12187 get_afi_safi_str(afi, safi,
12188 true));
12189 } else
12190 vty_out(vty,
12191 "\nFor address family: %s\n",
12192 get_afi_safi_str(afi, safi,
12193 false));
12194
12195 if (community)
12196 bgp_show_community(vty, bgp, community,
12197 exact_match, afi,
12198 safi, show_flags);
7d3cae70
DA
12199 else if (prefix_version)
12200 return bgp_show(vty, bgp, afi, safi,
12201 sh_type, prefix_version,
12202 show_flags,
12203 rpki_target_state);
96f3485c
MK
12204 else
12205 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12206 NULL, show_flags,
4027d19b 12207 rpki_target_state);
96f3485c
MK
12208 if (uj)
12209 vty_out(vty, "}\n");
12210 }
12211 }
12212 if (uj)
12213 vty_out(vty, "}\n");
12214 }
12215 return CMD_SUCCESS;
a636c635 12216}
47fc97cc 12217
718e3744 12218DEFUN (show_ip_bgp_route,
12219 show_ip_bgp_route_cmd,
8aa22bbb 12220 "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 12221 SHOW_STR
12222 IP_STR
12223 BGP_STR
a636c635 12224 BGP_INSTANCE_HELP_STR
4f280b15 12225 BGP_AFI_HELP_STR
4dd6177e 12226 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12227 "Network in the BGP routing table to display\n"
0c7b1b01 12228 "IPv4 prefix\n"
8c3deaae 12229 "Network in the BGP routing table to display\n"
0c7b1b01 12230 "IPv6 prefix\n"
4092b06c 12231 "Display only the bestpath\n"
b05a1c8b 12232 "Display only multipaths\n"
8aa22bbb
DS
12233 "Display only paths that match the specified rpki state\n"
12234 "A valid path as determined by rpki\n"
12235 "A invalid path as determined by rpki\n"
12236 "A path that has no rpki data\n"
9973d184 12237 JSON_STR)
4092b06c 12238{
d62a17ae 12239 int prefix_check = 0;
ae19d7dd 12240
d62a17ae 12241 afi_t afi = AFI_IP6;
12242 safi_t safi = SAFI_UNICAST;
12243 char *prefix = NULL;
12244 struct bgp *bgp = NULL;
12245 enum bgp_path_type path_type;
9f049418 12246 bool uj = use_json(argc, argv);
b05a1c8b 12247
d62a17ae 12248 int idx = 0;
ae19d7dd 12249
d62a17ae 12250 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12251 &bgp, uj);
d62a17ae 12252 if (!idx)
12253 return CMD_WARNING;
c41247f5 12254
d62a17ae 12255 if (!bgp) {
12256 vty_out(vty,
12257 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12258 return CMD_WARNING;
12259 }
a636c635 12260
d62a17ae 12261 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12262 if (argv_find(argv, argc, "A.B.C.D", &idx)
12263 || argv_find(argv, argc, "X:X::X:X", &idx))
12264 prefix_check = 0;
12265 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12266 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12267 prefix_check = 1;
12268
12269 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12270 && afi != AFI_IP6) {
12271 vty_out(vty,
12272 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12273 return CMD_WARNING;
12274 }
12275 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12276 && afi != AFI_IP) {
12277 vty_out(vty,
12278 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12279 return CMD_WARNING;
12280 }
12281
12282 prefix = argv[idx]->arg;
12283
12284 /* [<bestpath|multipath>] */
12285 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12286 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12287 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12288 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12289 else
360660c6 12290 path_type = BGP_PATH_SHOW_ALL;
a636c635 12291
d62a17ae 12292 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12293 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12294}
12295
8c3deaae
QY
12296DEFUN (show_ip_bgp_regexp,
12297 show_ip_bgp_regexp_cmd,
3e5b31b3 12298 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12299 SHOW_STR
12300 IP_STR
12301 BGP_STR
b00b230a 12302 BGP_INSTANCE_HELP_STR
4f280b15 12303 BGP_AFI_HELP_STR
4dd6177e 12304 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12305 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12306 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12307 JSON_STR)
8c3deaae 12308{
d62a17ae 12309 afi_t afi = AFI_IP6;
12310 safi_t safi = SAFI_UNICAST;
12311 struct bgp *bgp = NULL;
3e5b31b3
DA
12312 bool uj = use_json(argc, argv);
12313 char *regstr = NULL;
8c3deaae 12314
d62a17ae 12315 int idx = 0;
12316 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12317 &bgp, false);
d62a17ae 12318 if (!idx)
12319 return CMD_WARNING;
8c3deaae 12320
d62a17ae 12321 // get index of regex
3e5b31b3
DA
12322 if (argv_find(argv, argc, "REGEX", &idx))
12323 regstr = argv[idx]->arg;
8c3deaae 12324
5f71d11c 12325 assert(regstr);
3e5b31b3
DA
12326 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12327 bgp_show_type_regexp, uj);
8c3deaae
QY
12328}
12329
ae248832 12330DEFPY (show_ip_bgp_instance_all,
a636c635 12331 show_ip_bgp_instance_all_cmd,
ae248832 12332 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12333 SHOW_STR
a636c635 12334 IP_STR
4092b06c 12335 BGP_STR
a636c635 12336 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12337 BGP_AFI_HELP_STR
4dd6177e 12338 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12339 JSON_STR
12340 "Increase table width for longer prefixes\n")
4092b06c 12341{
d62a17ae 12342 afi_t afi = AFI_IP;
12343 safi_t safi = SAFI_UNICAST;
12344 struct bgp *bgp = NULL;
d62a17ae 12345 int idx = 0;
96f3485c 12346 uint8_t show_flags = 0;
ae19d7dd 12347
96f3485c 12348 if (uj) {
d62a17ae 12349 argc--;
96f3485c
MK
12350 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12351 }
12352
12353 if (wide)
12354 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12355
9f049418
DS
12356 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12357 &bgp, uj);
12358 if (!idx)
12359 return CMD_WARNING;
12360
96f3485c 12361 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12362 return CMD_SUCCESS;
e3e29b32
LB
12363}
12364
a4d82a8a 12365static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12366 afi_t afi, safi_t safi, enum bgp_show_type type,
12367 bool use_json)
718e3744 12368{
d62a17ae 12369 regex_t *regex;
12370 int rc;
96f3485c
MK
12371 uint8_t show_flags = 0;
12372
12373 if (use_json)
12374 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12375
c3900853 12376 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12377 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12378 regstr);
12379 return CMD_WARNING_CONFIG_FAILED;
12380 }
12381
d62a17ae 12382 regex = bgp_regcomp(regstr);
12383 if (!regex) {
12384 vty_out(vty, "Can't compile regexp %s\n", regstr);
12385 return CMD_WARNING;
12386 }
a636c635 12387
1e2ce4f1
DS
12388 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12389 RPKI_NOT_BEING_USED);
d62a17ae 12390 bgp_regex_free(regex);
12391 return rc;
e3e29b32
LB
12392}
12393
d62a17ae 12394static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12395 const char *prefix_list_str, afi_t afi,
12396 safi_t safi, enum bgp_show_type type)
e3e29b32 12397{
d62a17ae 12398 struct prefix_list *plist;
96f3485c 12399 uint8_t show_flags = 0;
718e3744 12400
d62a17ae 12401 plist = prefix_list_lookup(afi, prefix_list_str);
12402 if (plist == NULL) {
12403 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12404 prefix_list_str);
12405 return CMD_WARNING;
12406 }
718e3744 12407
1e2ce4f1
DS
12408 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12409 RPKI_NOT_BEING_USED);
4092b06c
DS
12410}
12411
d62a17ae 12412static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12413 const char *filter, afi_t afi, safi_t safi,
12414 enum bgp_show_type type)
4092b06c 12415{
d62a17ae 12416 struct as_list *as_list;
96f3485c 12417 uint8_t show_flags = 0;
718e3744 12418
d62a17ae 12419 as_list = as_list_lookup(filter);
12420 if (as_list == NULL) {
12421 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12422 filter);
12423 return CMD_WARNING;
12424 }
a636c635 12425
1e2ce4f1
DS
12426 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12427 RPKI_NOT_BEING_USED);
718e3744 12428}
12429
d62a17ae 12430static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12431 const char *rmap_str, afi_t afi, safi_t safi,
12432 enum bgp_show_type type)
718e3744 12433{
d62a17ae 12434 struct route_map *rmap;
96f3485c 12435 uint8_t show_flags = 0;
bb46e94f 12436
d62a17ae 12437 rmap = route_map_lookup_by_name(rmap_str);
12438 if (!rmap) {
12439 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12440 return CMD_WARNING;
12441 }
12442
1e2ce4f1
DS
12443 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12444 RPKI_NOT_BEING_USED);
d62a17ae 12445}
12446
7f323236
DW
12447static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12448 const char *comstr, int exact, afi_t afi,
96f3485c 12449 safi_t safi, uint8_t show_flags)
d62a17ae 12450{
12451 struct community *com;
d62a17ae 12452 int ret = 0;
12453
7f323236 12454 com = community_str2com(comstr);
d62a17ae 12455 if (!com) {
7f323236 12456 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12457 return CMD_WARNING;
12458 }
12459
12460 ret = bgp_show(vty, bgp, afi, safi,
12461 (exact ? bgp_show_type_community_exact
12462 : bgp_show_type_community),
1e2ce4f1 12463 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12464 community_free(&com);
46c3ce83 12465
d62a17ae 12466 return ret;
718e3744 12467}
12468
d62a17ae 12469static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12470 const char *com, int exact, afi_t afi,
12471 safi_t safi)
50ef26d4 12472{
d62a17ae 12473 struct community_list *list;
96f3485c 12474 uint8_t show_flags = 0;
50ef26d4 12475
e237b0d2 12476 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12477 if (list == NULL) {
12478 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12479 return CMD_WARNING;
12480 }
718e3744 12481
d62a17ae 12482 return bgp_show(vty, bgp, afi, safi,
12483 (exact ? bgp_show_type_community_list_exact
12484 : bgp_show_type_community_list),
1e2ce4f1 12485 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12486}
12487
d62a17ae 12488static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12489 const char *prefix, afi_t afi, safi_t safi,
12490 enum bgp_show_type type)
718e3744 12491{
d62a17ae 12492 int ret;
12493 struct prefix *p;
96f3485c 12494 uint8_t show_flags = 0;
47fc97cc 12495
d62a17ae 12496 p = prefix_new();
95cbbd2a 12497
d62a17ae 12498 ret = str2prefix(prefix, p);
12499 if (!ret) {
12500 vty_out(vty, "%% Malformed Prefix\n");
12501 return CMD_WARNING;
12502 }
47e9b292 12503
1e2ce4f1
DS
12504 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12505 RPKI_NOT_BEING_USED);
63265b5c 12506 prefix_free(&p);
d62a17ae 12507 return ret;
12508}
12509
d62a17ae 12510enum bgp_stats {
12511 BGP_STATS_MAXBITLEN = 0,
12512 BGP_STATS_RIB,
12513 BGP_STATS_PREFIXES,
12514 BGP_STATS_TOTPLEN,
12515 BGP_STATS_UNAGGREGATEABLE,
12516 BGP_STATS_MAX_AGGREGATEABLE,
12517 BGP_STATS_AGGREGATES,
12518 BGP_STATS_SPACE,
12519 BGP_STATS_ASPATH_COUNT,
12520 BGP_STATS_ASPATH_MAXHOPS,
12521 BGP_STATS_ASPATH_TOTHOPS,
12522 BGP_STATS_ASPATH_MAXSIZE,
12523 BGP_STATS_ASPATH_TOTSIZE,
12524 BGP_STATS_ASN_HIGHEST,
12525 BGP_STATS_MAX,
a636c635 12526};
2815e61f 12527
9ab0cf58 12528#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12529#define TABLE_STATS_IDX_JSON 1
12530
12531static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12532 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12533 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12534 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12535 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12536 "unaggregateablePrefixes"},
12537 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12538 "maximumAggregateablePrefixes"},
12539 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12540 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12541 [BGP_STATS_SPACE] = {"Address space advertised",
12542 "addressSpaceAdvertised"},
9ab0cf58
PG
12543 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12544 "advertisementsWithPaths"},
12545 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12546 "longestAsPath"},
12547 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12548 "largestAsPath"},
12549 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12550 "averageAsPathLengthHops"},
12551 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12552 "averageAsPathSizeBytes"},
12553 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12554 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12555};
2815e61f 12556
d62a17ae 12557struct bgp_table_stats {
12558 struct bgp_table *table;
12559 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12560 double total_space;
ff7924f6
PJ
12561};
12562
9bcb3eef 12563static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12564 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12565{
9bcb3eef 12566 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12567 struct bgp_path_info *pi;
b54892e0 12568 const struct prefix *rn_p;
d62a17ae 12569
9bcb3eef 12570 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12571 return;
d62a17ae 12572
9bcb3eef 12573 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12574 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12575 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12576
9c14ec72 12577 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12578 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12579 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12580
9bcb3eef 12581 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12582 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12583 /* announced address space */
12584 if (space)
b54892e0 12585 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12586 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12587 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12588
9c14ec72 12589
9bcb3eef 12590 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12591 ts->counts[BGP_STATS_RIB]++;
12592
05864da7
DS
12593 if (CHECK_FLAG(pi->attr->flag,
12594 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12595 ts->counts[BGP_STATS_AGGREGATES]++;
12596
12597 /* as-path stats */
05864da7 12598 if (pi->attr->aspath) {
9c14ec72
RW
12599 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12600 unsigned int size = aspath_size(pi->attr->aspath);
12601 as_t highest = aspath_highest(pi->attr->aspath);
12602
12603 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12604
12605 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12606 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12607
12608 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12609 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12610
12611 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12612 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12613 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12614 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12615 }
12616 }
12617}
12618
12619static int bgp_table_stats_walker(struct thread *t)
12620{
9bcb3eef
DS
12621 struct bgp_dest *dest, *ndest;
12622 struct bgp_dest *top;
9c14ec72
RW
12623 struct bgp_table_stats *ts = THREAD_ARG(t);
12624 unsigned int space = 0;
12625
12626 if (!(top = bgp_table_top(ts->table)))
12627 return 0;
12628
12629 switch (ts->table->afi) {
12630 case AFI_IP:
12631 space = IPV4_MAX_BITLEN;
12632 break;
12633 case AFI_IP6:
12634 space = IPV6_MAX_BITLEN;
12635 break;
3ba7b4af
TA
12636 case AFI_L2VPN:
12637 space = EVPN_ROUTE_PREFIXLEN;
12638 break;
9c14ec72
RW
12639 default:
12640 return 0;
12641 }
12642
12643 ts->counts[BGP_STATS_MAXBITLEN] = space;
12644
9bcb3eef 12645 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12646 if (ts->table->safi == SAFI_MPLS_VPN
12647 || ts->table->safi == SAFI_ENCAP
12648 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12649 struct bgp_table *table;
12650
9bcb3eef 12651 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12652 if (!table)
12653 continue;
12654
12655 top = bgp_table_top(table);
9bcb3eef
DS
12656 for (ndest = bgp_table_top(table); ndest;
12657 ndest = bgp_route_next(ndest))
12658 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12659 } else {
9bcb3eef 12660 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12661 }
12662 }
9c14ec72 12663
d62a17ae 12664 return 0;
2815e61f 12665}
ff7924f6 12666
71f1613a
DA
12667static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12668 struct json_object *json_array)
12669{
12670 struct listnode *node, *nnode;
12671 struct bgp *bgp;
12672
12673 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12674 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12675}
12676
12677static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12678 safi_t safi, struct json_object *json_array)
2815e61f 12679{
d62a17ae 12680 struct bgp_table_stats ts;
12681 unsigned int i;
893cccd0
PG
12682 int ret = CMD_SUCCESS;
12683 char temp_buf[20];
6c9d22e2
PG
12684 struct json_object *json = NULL;
12685
12686 if (json_array)
12687 json = json_object_new_object();
019386c2 12688
d62a17ae 12689 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12690 char warning_msg[50];
12691
12692 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12693 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12694 safi);
6c9d22e2
PG
12695
12696 if (!json)
893cccd0
PG
12697 vty_out(vty, "%s\n", warning_msg);
12698 else
9ab0cf58 12699 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12700
893cccd0
PG
12701 ret = CMD_WARNING;
12702 goto end_table_stats;
d62a17ae 12703 }
019386c2 12704
893cccd0 12705 if (!json)
5290ceab
DA
12706 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12707 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12708 else
12709 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12710
d62a17ae 12711 /* labeled-unicast routes live in the unicast table */
12712 if (safi == SAFI_LABELED_UNICAST)
12713 safi = SAFI_UNICAST;
019386c2 12714
d62a17ae 12715 memset(&ts, 0, sizeof(ts));
12716 ts.table = bgp->rib[afi][safi];
12717 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12718
d62a17ae 12719 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12720 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12721 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12722 continue;
12723
12724 switch (i) {
d62a17ae 12725 case BGP_STATS_ASPATH_TOTHOPS:
12726 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12727 if (!json) {
9ab0cf58
PG
12728 snprintf(
12729 temp_buf, sizeof(temp_buf), "%12.2f",
12730 ts.counts[i]
12731 ? (float)ts.counts[i]
12732 / (float)ts.counts
12733 [BGP_STATS_ASPATH_COUNT]
12734 : 0);
893cccd0 12735 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12736 table_stats_strs[i]
12737 [TABLE_STATS_IDX_VTY],
893cccd0 12738 temp_buf);
9ab0cf58
PG
12739 } else {
12740 json_object_double_add(
12741 json,
12742 table_stats_strs[i]
12743 [TABLE_STATS_IDX_JSON],
12744 ts.counts[i]
12745 ? (double)ts.counts[i]
12746 / (double)ts.counts
d62a17ae 12747 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12748 : 0);
12749 }
d62a17ae 12750 break;
12751 case BGP_STATS_TOTPLEN:
6c9d22e2 12752 if (!json) {
9ab0cf58
PG
12753 snprintf(
12754 temp_buf, sizeof(temp_buf), "%12.2f",
12755 ts.counts[i]
12756 ? (float)ts.counts[i]
12757 / (float)ts.counts
12758 [BGP_STATS_PREFIXES]
12759 : 0);
893cccd0 12760 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12761 table_stats_strs[i]
12762 [TABLE_STATS_IDX_VTY],
893cccd0 12763 temp_buf);
9ab0cf58
PG
12764 } else {
12765 json_object_double_add(
12766 json,
12767 table_stats_strs[i]
12768 [TABLE_STATS_IDX_JSON],
12769 ts.counts[i]
12770 ? (double)ts.counts[i]
12771 / (double)ts.counts
d62a17ae 12772 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12773 : 0);
12774 }
d62a17ae 12775 break;
12776 case BGP_STATS_SPACE:
6c9d22e2
PG
12777 if (!json) {
12778 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12779 ts.total_space);
893cccd0 12780 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12781 table_stats_strs[i]
12782 [TABLE_STATS_IDX_VTY],
893cccd0 12783 temp_buf);
9ab0cf58
PG
12784 } else {
12785 json_object_double_add(
12786 json,
12787 table_stats_strs[i]
12788 [TABLE_STATS_IDX_JSON],
12789 (double)ts.total_space);
12790 }
8d0ab76d 12791 if (afi == AFI_IP6) {
6c9d22e2
PG
12792 if (!json) {
12793 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12794 "%12g",
12795 ts.total_space
12796 * pow(2.0, -128 + 32));
6c9d22e2
PG
12797 vty_out(vty, "%30s: %s\n",
12798 "/32 equivalent %s\n",
12799 temp_buf);
9ab0cf58
PG
12800 } else {
12801 json_object_double_add(
12802 json, "/32equivalent",
12803 (double)(ts.total_space
12804 * pow(2.0,
12805 -128 + 32)));
12806 }
6c9d22e2
PG
12807 if (!json) {
12808 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12809 "%12g",
12810 ts.total_space
12811 * pow(2.0, -128 + 48));
6c9d22e2
PG
12812 vty_out(vty, "%30s: %s\n",
12813 "/48 equivalent %s\n",
12814 temp_buf);
9ab0cf58
PG
12815 } else {
12816 json_object_double_add(
12817 json, "/48equivalent",
12818 (double)(ts.total_space
12819 * pow(2.0,
12820 -128 + 48)));
12821 }
8d0ab76d 12822 } else {
6c9d22e2
PG
12823 if (!json) {
12824 snprintf(temp_buf, sizeof(temp_buf),
12825 "%12.2f",
9ab0cf58
PG
12826 ts.total_space * 100.
12827 * pow(2.0, -32));
6c9d22e2 12828 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12829 "% announced ", temp_buf);
12830 } else {
12831 json_object_double_add(
12832 json, "%announced",
12833 (double)(ts.total_space * 100.
12834 * pow(2.0, -32)));
12835 }
6c9d22e2
PG
12836 if (!json) {
12837 snprintf(temp_buf, sizeof(temp_buf),
12838 "%12.2f",
9ab0cf58
PG
12839 ts.total_space
12840 * pow(2.0, -32 + 8));
6c9d22e2
PG
12841 vty_out(vty, "%30s: %s\n",
12842 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12843 } else {
12844 json_object_double_add(
12845 json, "/8equivalent",
12846 (double)(ts.total_space
12847 * pow(2.0, -32 + 8)));
12848 }
6c9d22e2
PG
12849 if (!json) {
12850 snprintf(temp_buf, sizeof(temp_buf),
12851 "%12.2f",
9ab0cf58
PG
12852 ts.total_space
12853 * pow(2.0, -32 + 24));
6c9d22e2 12854 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12855 "/24 equivalent ", temp_buf);
12856 } else {
12857 json_object_double_add(
12858 json, "/24equivalent",
12859 (double)(ts.total_space
12860 * pow(2.0, -32 + 24)));
12861 }
8d0ab76d 12862 }
d62a17ae 12863 break;
12864 default:
6c9d22e2
PG
12865 if (!json) {
12866 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12867 ts.counts[i]);
893cccd0 12868 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12869 table_stats_strs[i]
12870 [TABLE_STATS_IDX_VTY],
12871 temp_buf);
12872 } else {
12873 json_object_int_add(
12874 json,
12875 table_stats_strs[i]
12876 [TABLE_STATS_IDX_JSON],
12877 ts.counts[i]);
12878 }
d62a17ae 12879 }
893cccd0
PG
12880 if (!json)
12881 vty_out(vty, "\n");
d62a17ae 12882 }
9ab0cf58 12883end_table_stats:
6c9d22e2
PG
12884 if (json)
12885 json_object_array_add(json_array, json);
893cccd0 12886 return ret;
d62a17ae 12887}
12888
71f1613a
DA
12889static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12890 safi_t safi, struct json_object *json_array)
12891{
12892 if (!bgp) {
12893 bgp_table_stats_all(vty, afi, safi, json_array);
12894 return CMD_SUCCESS;
12895 }
12896
12897 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12898}
12899
d62a17ae 12900enum bgp_pcounts {
12901 PCOUNT_ADJ_IN = 0,
12902 PCOUNT_DAMPED,
12903 PCOUNT_REMOVED,
12904 PCOUNT_HISTORY,
12905 PCOUNT_STALE,
12906 PCOUNT_VALID,
12907 PCOUNT_ALL,
12908 PCOUNT_COUNTED,
7e3d9632 12909 PCOUNT_BPATH_SELECTED,
d62a17ae 12910 PCOUNT_PFCNT, /* the figure we display to users */
12911 PCOUNT_MAX,
a636c635 12912};
718e3744 12913
2b64873d 12914static const char *const pcount_strs[] = {
9d303b37
DL
12915 [PCOUNT_ADJ_IN] = "Adj-in",
12916 [PCOUNT_DAMPED] = "Damped",
12917 [PCOUNT_REMOVED] = "Removed",
12918 [PCOUNT_HISTORY] = "History",
12919 [PCOUNT_STALE] = "Stale",
12920 [PCOUNT_VALID] = "Valid",
12921 [PCOUNT_ALL] = "All RIB",
12922 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12923 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12924 [PCOUNT_PFCNT] = "Useable",
12925 [PCOUNT_MAX] = NULL,
a636c635 12926};
718e3744 12927
d62a17ae 12928struct peer_pcounts {
12929 unsigned int count[PCOUNT_MAX];
12930 const struct peer *peer;
12931 const struct bgp_table *table;
54317cba 12932 safi_t safi;
a636c635 12933};
47fc97cc 12934
9bcb3eef 12935static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12936{
54317cba
JW
12937 const struct bgp_adj_in *ain;
12938 const struct bgp_path_info *pi;
d62a17ae 12939 const struct peer *peer = pc->peer;
12940
54317cba
JW
12941 for (ain = rn->adj_in; ain; ain = ain->next)
12942 if (ain->peer == peer)
12943 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12944
9bcb3eef 12945 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12946
54317cba
JW
12947 if (pi->peer != peer)
12948 continue;
d62a17ae 12949
54317cba 12950 pc->count[PCOUNT_ALL]++;
d62a17ae 12951
54317cba
JW
12952 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12953 pc->count[PCOUNT_DAMPED]++;
12954 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12955 pc->count[PCOUNT_HISTORY]++;
12956 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12957 pc->count[PCOUNT_REMOVED]++;
12958 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12959 pc->count[PCOUNT_STALE]++;
12960 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12961 pc->count[PCOUNT_VALID]++;
12962 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12963 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12964 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12965 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12966
12967 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12968 pc->count[PCOUNT_COUNTED]++;
12969 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12970 flog_err(
12971 EC_LIB_DEVELOPMENT,
12972 "Attempting to count but flags say it is unusable");
12973 } else {
40381db7 12974 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12975 flog_err(
12976 EC_LIB_DEVELOPMENT,
12977 "Not counted but flags say we should");
d62a17ae 12978 }
12979 }
54317cba
JW
12980}
12981
12982static int bgp_peer_count_walker(struct thread *t)
12983{
9bcb3eef 12984 struct bgp_dest *rn, *rm;
54317cba
JW
12985 const struct bgp_table *table;
12986 struct peer_pcounts *pc = THREAD_ARG(t);
12987
12988 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12989 || pc->safi == SAFI_EVPN) {
12990 /* Special handling for 2-level routing tables. */
12991 for (rn = bgp_table_top(pc->table); rn;
12992 rn = bgp_route_next(rn)) {
9bcb3eef 12993 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12994 if (table != NULL)
12995 for (rm = bgp_table_top(table); rm;
12996 rm = bgp_route_next(rm))
12997 bgp_peer_count_proc(rm, pc);
12998 }
12999 } else
13000 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13001 bgp_peer_count_proc(rn, pc);
13002
d62a17ae 13003 return 0;
718e3744 13004}
13005
d62a17ae 13006static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13007 safi_t safi, bool use_json)
856ca177 13008{
d62a17ae 13009 struct peer_pcounts pcounts = {.peer = peer};
13010 unsigned int i;
13011 json_object *json = NULL;
13012 json_object *json_loop = NULL;
856ca177 13013
d62a17ae 13014 if (use_json) {
13015 json = json_object_new_object();
13016 json_loop = json_object_new_object();
13017 }
718e3744 13018
d62a17ae 13019 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13020 || !peer->bgp->rib[afi][safi]) {
13021 if (use_json) {
13022 json_object_string_add(
13023 json, "warning",
13024 "No such neighbor or address family");
13025 vty_out(vty, "%s\n", json_object_to_json_string(json));
13026 json_object_free(json);
d5f20468 13027 json_object_free(json_loop);
d62a17ae 13028 } else
13029 vty_out(vty, "%% No such neighbor or address family\n");
13030
13031 return CMD_WARNING;
13032 }
2a71e9ce 13033
d62a17ae 13034 memset(&pcounts, 0, sizeof(pcounts));
13035 pcounts.peer = peer;
13036 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13037 pcounts.safi = safi;
d62a17ae 13038
13039 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13040 * stats for the thread-walk (i.e. ensure this can't be blamed on
13041 * on just vty_read()).
13042 */
d62a17ae 13043 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13044
13045 if (use_json) {
13046 json_object_string_add(json, "prefixCountsFor", peer->host);
13047 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13048 get_afi_safi_str(afi, safi, true));
d62a17ae 13049 json_object_int_add(json, "pfxCounter",
13050 peer->pcount[afi][safi]);
13051
13052 for (i = 0; i < PCOUNT_MAX; i++)
13053 json_object_int_add(json_loop, pcount_strs[i],
13054 pcounts.count[i]);
13055
13056 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13057
13058 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13059 json_object_string_add(json, "pfxctDriftFor",
13060 peer->host);
13061 json_object_string_add(
13062 json, "recommended",
13063 "Please report this bug, with the above command output");
13064 }
996c9314
LB
13065 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13066 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 13067 json_object_free(json);
13068 } else {
13069
13070 if (peer->hostname
892fedb6 13071 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13072 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13073 peer->hostname, peer->host,
5cb5f4d0 13074 get_afi_safi_str(afi, safi, false));
d62a17ae 13075 } else {
13076 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13077 get_afi_safi_str(afi, safi, false));
d62a17ae 13078 }
13079
6cde4b45 13080 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13081 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13082
13083 for (i = 0; i < PCOUNT_MAX; i++)
13084 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13085 pcounts.count[i]);
13086
13087 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13088 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13089 vty_out(vty,
13090 "Please report this bug, with the above command output\n");
13091 }
13092 }
13093
13094 return CMD_SUCCESS;
718e3744 13095}
13096
a636c635
DW
13097DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13098 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13099 "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 13100 SHOW_STR
13101 IP_STR
13102 BGP_STR
8386ac43 13103 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13104 BGP_AFI_HELP_STR
13105 BGP_SAFI_HELP_STR
0b16f239
DS
13106 "Detailed information on TCP and BGP neighbor connections\n"
13107 "Neighbor to display information about\n"
13108 "Neighbor to display information about\n"
91d37724 13109 "Neighbor on BGP configured interface\n"
a636c635 13110 "Display detailed prefix count information\n"
9973d184 13111 JSON_STR)
0b16f239 13112{
d62a17ae 13113 afi_t afi = AFI_IP6;
13114 safi_t safi = SAFI_UNICAST;
13115 struct peer *peer;
13116 int idx = 0;
13117 struct bgp *bgp = NULL;
9f049418
DS
13118 bool uj = use_json(argc, argv);
13119
13120 if (uj)
13121 argc--;
856ca177 13122
d62a17ae 13123 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13124 &bgp, uj);
d62a17ae 13125 if (!idx)
13126 return CMD_WARNING;
0b16f239 13127
d62a17ae 13128 argv_find(argv, argc, "neighbors", &idx);
13129 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13130 if (!peer)
13131 return CMD_WARNING;
bb46e94f 13132
29c8d9da 13133 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13134}
0b16f239 13135
d6902373
PG
13136#ifdef KEEP_OLD_VPN_COMMANDS
13137DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13138 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13139 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13140 SHOW_STR
13141 IP_STR
13142 BGP_STR
d6902373 13143 BGP_VPNVX_HELP_STR
91d37724 13144 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13145 "Detailed information on TCP and BGP neighbor connections\n"
13146 "Neighbor to display information about\n"
13147 "Neighbor to display information about\n"
91d37724 13148 "Neighbor on BGP configured interface\n"
a636c635 13149 "Display detailed prefix count information\n"
9973d184 13150 JSON_STR)
a636c635 13151{
d62a17ae 13152 int idx_peer = 6;
13153 struct peer *peer;
9f049418 13154 bool uj = use_json(argc, argv);
a636c635 13155
d62a17ae 13156 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13157 if (!peer)
13158 return CMD_WARNING;
13159
13160 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13161}
13162
d6902373
PG
13163DEFUN (show_ip_bgp_vpn_all_route_prefix,
13164 show_ip_bgp_vpn_all_route_prefix_cmd,
13165 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13166 SHOW_STR
13167 IP_STR
13168 BGP_STR
d6902373 13169 BGP_VPNVX_HELP_STR
91d37724
QY
13170 "Display information about all VPNv4 NLRIs\n"
13171 "Network in the BGP routing table to display\n"
3a2d747c 13172 "Network in the BGP routing table to display\n"
9973d184 13173 JSON_STR)
91d37724 13174{
d62a17ae 13175 int idx = 0;
13176 char *network = NULL;
13177 struct bgp *bgp = bgp_get_default();
13178 if (!bgp) {
13179 vty_out(vty, "Can't find default instance\n");
13180 return CMD_WARNING;
13181 }
87e34b58 13182
d62a17ae 13183 if (argv_find(argv, argc, "A.B.C.D", &idx))
13184 network = argv[idx]->arg;
13185 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13186 network = argv[idx]->arg;
13187 else {
13188 vty_out(vty, "Unable to figure out Network\n");
13189 return CMD_WARNING;
13190 }
87e34b58 13191
d62a17ae 13192 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13193 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13194 use_json(argc, argv));
91d37724 13195}
d6902373 13196#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13197
44c69747
LK
13198DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13199 show_bgp_l2vpn_evpn_route_prefix_cmd,
13200 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13201 SHOW_STR
4c63a661
PG
13202 BGP_STR
13203 L2VPN_HELP_STR
13204 EVPN_HELP_STR
44c69747
LK
13205 "Network in the BGP routing table to display\n"
13206 "Network in the BGP routing table to display\n"
4c63a661
PG
13207 "Network in the BGP routing table to display\n"
13208 "Network in the BGP routing table to display\n"
13209 JSON_STR)
13210{
d62a17ae 13211 int idx = 0;
13212 char *network = NULL;
44c69747 13213 int prefix_check = 0;
a636c635 13214
44c69747
LK
13215 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13216 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13217 network = argv[idx]->arg;
44c69747 13218 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13219 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13220 network = argv[idx]->arg;
44c69747
LK
13221 prefix_check = 1;
13222 } else {
d62a17ae 13223 vty_out(vty, "Unable to figure out Network\n");
13224 return CMD_WARNING;
13225 }
44c69747
LK
13226 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13227 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13228 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13229}
13230
2f9bc755
DS
13231static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13232 struct bgp_table *table, int *header1,
13233 int *header2, json_object *json,
13234 json_object *json_scode,
13235 json_object *json_ocode, bool wide)
13236{
13237 uint64_t version = table ? table->version : 0;
23d0a753 13238 char buf[BUFSIZ] = {0};
2f9bc755
DS
13239
13240 if (*header1) {
13241 if (json) {
13242 json_object_int_add(json, "bgpTableVersion", version);
13243 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13244 inet_ntop(AF_INET,
13245 &bgp->router_id, buf,
13246 sizeof(buf)));
2f9bc755
DS
13247 json_object_int_add(json, "defaultLocPrf",
13248 bgp->default_local_pref);
13249 json_object_int_add(json, "localAS", bgp->as);
13250 json_object_object_add(json, "bgpStatusCodes",
13251 json_scode);
13252 json_object_object_add(json, "bgpOriginCodes",
13253 json_ocode);
13254 } else {
13255 vty_out(vty,
23d0a753
DA
13256 "BGP table version is %" PRIu64
13257 ", local router ID is %pI4, vrf id ",
13258 version, &bgp->router_id);
2f9bc755
DS
13259 if (bgp->vrf_id == VRF_UNKNOWN)
13260 vty_out(vty, "%s", VRFID_NONE_STR);
13261 else
13262 vty_out(vty, "%u", bgp->vrf_id);
13263 vty_out(vty, "\n");
13264 vty_out(vty, "Default local pref %u, ",
13265 bgp->default_local_pref);
13266 vty_out(vty, "local AS %u\n", bgp->as);
13267 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13268 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13269 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13270 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13271 }
13272 *header1 = 0;
13273 }
13274 if (*header2) {
13275 if (!json)
13276 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13277 : BGP_SHOW_HEADER));
13278 *header2 = 0;
13279 }
13280}
13281
d9478df0
TA
13282static void
13283show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13284 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13285 const char *rmap_name, json_object *json, json_object *json_ar,
13286 json_object *json_scode, json_object *json_ocode,
13287 uint8_t show_flags, int *header1, int *header2, char *rd_str,
13288 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13289{
d62a17ae 13290 struct bgp_adj_in *ain;
13291 struct bgp_adj_out *adj;
9bcb3eef 13292 struct bgp_dest *dest;
d62a17ae 13293 struct bgp *bgp;
d62a17ae 13294 struct attr attr;
13295 int ret;
13296 struct update_subgroup *subgrp;
d62a17ae 13297 struct peer_af *paf;
f99def61 13298 bool route_filtered;
96f3485c
MK
13299 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13300 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13301 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13302 || (safi == SAFI_EVPN))
13303 ? true
13304 : false;
a636c635 13305
d62a17ae 13306 bgp = peer->bgp;
a636c635 13307
d62a17ae 13308 if (!bgp) {
13309 if (use_json) {
13310 json_object_string_add(json, "alert", "no BGP");
13311 vty_out(vty, "%s\n", json_object_to_json_string(json));
13312 json_object_free(json);
13313 } else
13314 vty_out(vty, "%% No bgp\n");
13315 return;
13316 }
a636c635 13317
d62a17ae 13318 subgrp = peer_subgroup(peer, afi, safi);
13319
6392aaa6 13320 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13321 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13322 char buf[BUFSIZ] = {0};
13323
d62a17ae 13324 if (use_json) {
13325 json_object_int_add(json, "bgpTableVersion",
13326 table->version);
13327 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13328 inet_ntop(AF_INET,
13329 &bgp->router_id, buf,
13330 sizeof(buf)));
01eced22
AD
13331 json_object_int_add(json, "defaultLocPrf",
13332 bgp->default_local_pref);
13333 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13334 json_object_object_add(json, "bgpStatusCodes",
13335 json_scode);
13336 json_object_object_add(json, "bgpOriginCodes",
13337 json_ocode);
07d0c4ed
DA
13338 json_object_string_add(
13339 json, "bgpOriginatingDefaultNetwork",
13340 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13341 } else {
23d0a753
DA
13342 vty_out(vty,
13343 "BGP table version is %" PRIu64
13344 ", local router ID is %pI4, vrf id ",
13345 table->version, &bgp->router_id);
9df8b37c
PZ
13346 if (bgp->vrf_id == VRF_UNKNOWN)
13347 vty_out(vty, "%s", VRFID_NONE_STR);
13348 else
13349 vty_out(vty, "%u", bgp->vrf_id);
13350 vty_out(vty, "\n");
01eced22
AD
13351 vty_out(vty, "Default local pref %u, ",
13352 bgp->default_local_pref);
13353 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13354 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13355 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13356 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13357 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13358
07d0c4ed
DA
13359 vty_out(vty, "Originating default network %s\n\n",
13360 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13361 }
d9478df0 13362 *header1 = 0;
d62a17ae 13363 }
a636c635 13364
9bcb3eef 13365 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13366 if (type == bgp_show_adj_route_received
13367 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13368 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13369 if (ain->peer != peer)
ea47320b 13370 continue;
6392aaa6 13371
d9478df0
TA
13372 show_adj_route_header(vty, bgp, table, header1,
13373 header2, json, json_scode,
13374 json_ocode, wide);
13375
13376 if ((safi == SAFI_MPLS_VPN)
13377 || (safi == SAFI_ENCAP)
13378 || (safi == SAFI_EVPN)) {
13379 if (use_json)
13380 json_object_string_add(
13381 json_ar, "rd", rd_str);
13382 else if (show_rd && rd_str) {
13383 vty_out(vty,
13384 "Route Distinguisher: %s\n",
13385 rd_str);
13386 show_rd = false;
13387 }
13388 }
6392aaa6 13389
6f4f49b2 13390 attr = *ain->attr;
f99def61
AD
13391 route_filtered = false;
13392
13393 /* Filter prefix using distribute list,
13394 * filter list or prefix list
13395 */
b54892e0 13396 const struct prefix *rn_p =
9bcb3eef 13397 bgp_dest_get_prefix(dest);
b54892e0
DS
13398 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13399 safi))
13400 == FILTER_DENY)
f99def61
AD
13401 route_filtered = true;
13402
13403 /* Filter prefix using route-map */
b54892e0
DS
13404 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13405 safi, rmap_name, NULL,
13406 0, NULL);
6392aaa6 13407
13c8e163
AD
13408 if (type == bgp_show_adj_route_filtered &&
13409 !route_filtered && ret != RMAP_DENY) {
b755861b 13410 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13411 continue;
d62a17ae 13412 }
6392aaa6 13413
d9478df0
TA
13414 if (type == bgp_show_adj_route_received
13415 && (route_filtered || ret == RMAP_DENY))
13416 (*filtered_count)++;
6392aaa6 13417
7d3cae70 13418 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13419 use_json, json_ar, wide);
b755861b 13420 bgp_attr_undup(&attr, ain->attr);
d9478df0 13421 (*output_count)++;
d62a17ae 13422 }
6392aaa6 13423 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13424 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13425 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13426 if (paf->peer != peer || !adj->attr)
924c3f6a 13427 continue;
d62a17ae 13428
d9478df0
TA
13429 show_adj_route_header(vty, bgp, table,
13430 header1, header2,
13431 json, json_scode,
13432 json_ocode, wide);
d62a17ae 13433
b54892e0 13434 const struct prefix *rn_p =
9bcb3eef 13435 bgp_dest_get_prefix(dest);
b54892e0 13436
6f4f49b2 13437 attr = *adj->attr;
b755861b 13438 ret = bgp_output_modifier(
b54892e0 13439 peer, rn_p, &attr, afi, safi,
b755861b 13440 rmap_name);
f46d8e1e 13441
b755861b 13442 if (ret != RMAP_DENY) {
d9478df0
TA
13443 if ((safi == SAFI_MPLS_VPN)
13444 || (safi == SAFI_ENCAP)
13445 || (safi == SAFI_EVPN)) {
13446 if (use_json)
13447 json_object_string_add(
13448 json_ar,
13449 "rd",
13450 rd_str);
13451 else if (show_rd
13452 && rd_str) {
13453 vty_out(vty,
13454 "Route Distinguisher: %s\n",
13455 rd_str);
13456 show_rd = false;
13457 }
13458 }
b54892e0 13459 route_vty_out_tmp(
7d3cae70
DA
13460 vty, dest, rn_p, &attr,
13461 safi, use_json, json_ar,
ae248832 13462 wide);
d9478df0 13463 (*output_count)++;
b755861b 13464 } else {
d9478df0 13465 (*filtered_count)++;
a2addae8 13466 }
b755861b
PM
13467
13468 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13469 }
f20ce998
DS
13470 } else if (type == bgp_show_adj_route_bestpath) {
13471 struct bgp_path_info *pi;
13472
d9478df0
TA
13473 show_adj_route_header(vty, bgp, table, header1, header2,
13474 json, json_scode, json_ocode,
13475 wide);
f20ce998
DS
13476
13477 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13478 pi = pi->next) {
13479 if (pi->peer != peer)
13480 continue;
13481
13482 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13483 continue;
13484
7d3cae70 13485 route_vty_out_tmp(vty, dest,
f20ce998
DS
13486 bgp_dest_get_prefix(dest),
13487 pi->attr, safi, use_json,
13488 json_ar, wide);
d9478df0 13489 (*output_count)++;
f20ce998 13490 }
d62a17ae 13491 }
13492 }
a636c635 13493}
2a71e9ce 13494
d62a17ae 13495static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13496 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13497 const char *rmap_name, uint8_t show_flags)
0b16f239 13498{
d9478df0
TA
13499 struct bgp *bgp;
13500 struct bgp_table *table;
d62a17ae 13501 json_object *json = NULL;
d9478df0
TA
13502 json_object *json_scode = NULL;
13503 json_object *json_ocode = NULL;
13504 json_object *json_ar = NULL;
96f3485c 13505 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13506
d9478df0
TA
13507 /* Init BGP headers here so they're only displayed once
13508 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13509 */
13510 int header1 = 1;
13511 int header2 = 1;
13512
13513 /*
13514 * Initialize variables for each RD
13515 * All prefixes under an RD is aggregated within "json_routes"
13516 */
13517 char rd_str[BUFSIZ] = {0};
13518 json_object *json_routes = NULL;
13519
13520
13521 /* For 2-tier tables, prefix counts need to be
13522 * maintained across multiple runs of show_adj_route()
13523 */
13524 unsigned long output_count_per_rd;
13525 unsigned long filtered_count_per_rd;
13526 unsigned long output_count = 0;
13527 unsigned long filtered_count = 0;
13528
13529 if (use_json) {
d62a17ae 13530 json = json_object_new_object();
d9478df0
TA
13531 json_ar = json_object_new_object();
13532 json_scode = json_object_new_object();
13533 json_ocode = json_object_new_object();
13534
13535 json_object_string_add(json_scode, "suppressed", "s");
13536 json_object_string_add(json_scode, "damped", "d");
13537 json_object_string_add(json_scode, "history", "h");
13538 json_object_string_add(json_scode, "valid", "*");
13539 json_object_string_add(json_scode, "best", ">");
13540 json_object_string_add(json_scode, "multipath", "=");
13541 json_object_string_add(json_scode, "internal", "i");
13542 json_object_string_add(json_scode, "ribFailure", "r");
13543 json_object_string_add(json_scode, "stale", "S");
13544 json_object_string_add(json_scode, "removed", "R");
13545
13546 json_object_string_add(json_ocode, "igp", "i");
13547 json_object_string_add(json_ocode, "egp", "e");
13548 json_object_string_add(json_ocode, "incomplete", "?");
13549 }
0b16f239 13550
d62a17ae 13551 if (!peer || !peer->afc[afi][safi]) {
13552 if (use_json) {
13553 json_object_string_add(
13554 json, "warning",
13555 "No such neighbor or address family");
13556 vty_out(vty, "%s\n", json_object_to_json_string(json));
13557 json_object_free(json);
13558 } else
13559 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13560
d62a17ae 13561 return CMD_WARNING;
13562 }
13563
6392aaa6
PM
13564 if ((type == bgp_show_adj_route_received
13565 || type == bgp_show_adj_route_filtered)
d62a17ae 13566 && !CHECK_FLAG(peer->af_flags[afi][safi],
13567 PEER_FLAG_SOFT_RECONFIG)) {
13568 if (use_json) {
13569 json_object_string_add(
13570 json, "warning",
13571 "Inbound soft reconfiguration not enabled");
13572 vty_out(vty, "%s\n", json_object_to_json_string(json));
13573 json_object_free(json);
13574 } else
13575 vty_out(vty,
13576 "%% Inbound soft reconfiguration not enabled\n");
13577
13578 return CMD_WARNING;
13579 }
0b16f239 13580
d9478df0
TA
13581 bgp = peer->bgp;
13582
13583 /* labeled-unicast routes live in the unicast table */
13584 if (safi == SAFI_LABELED_UNICAST)
13585 table = bgp->rib[afi][SAFI_UNICAST];
13586 else
13587 table = bgp->rib[afi][safi];
13588
13589 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13590 || (safi == SAFI_EVPN)) {
13591
13592 struct bgp_dest *dest;
13593
13594 for (dest = bgp_table_top(table); dest;
13595 dest = bgp_route_next(dest)) {
13596 table = bgp_dest_get_bgp_table_info(dest);
13597 if (!table)
13598 continue;
13599
13600 output_count_per_rd = 0;
13601 filtered_count_per_rd = 0;
13602
13603 if (use_json)
13604 json_routes = json_object_new_object();
13605
13606 const struct prefix_rd *prd;
13607 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13608 dest);
13609
13610 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13611
13612 show_adj_route(vty, peer, table, afi, safi, type,
13613 rmap_name, json, json_routes, json_scode,
13614 json_ocode, show_flags, &header1,
13615 &header2, rd_str, &output_count_per_rd,
13616 &filtered_count_per_rd);
13617
13618 /* Don't include an empty RD in the output! */
13619 if (json_routes && (output_count_per_rd > 0))
13620 json_object_object_add(json_ar, rd_str,
13621 json_routes);
13622
13623 output_count += output_count_per_rd;
13624 filtered_count += filtered_count_per_rd;
13625 }
13626 } else
13627 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13628 json, json_ar, json_scode, json_ocode,
13629 show_flags, &header1, &header2, rd_str,
13630 &output_count, &filtered_count);
13631
13632 if (use_json) {
13633 json_object_object_add(json, "advertisedRoutes", json_ar);
13634 json_object_int_add(json, "totalPrefixCounter", output_count);
13635 json_object_int_add(json, "filteredPrefixCounter",
13636 filtered_count);
13637
13638 vty_out(vty, "%s\n",
13639 json_object_to_json_string_ext(
13640 json, JSON_C_TO_STRING_PRETTY));
13641
13642 if (!output_count && !filtered_count) {
13643 json_object_free(json_scode);
13644 json_object_free(json_ocode);
13645 }
13646
13647 if (json)
13648 json_object_free(json);
13649
13650 } else if (output_count > 0) {
13651 if (filtered_count > 0)
13652 vty_out(vty,
13653 "\nTotal number of prefixes %ld (%ld filtered)\n",
13654 output_count, filtered_count);
13655 else
13656 vty_out(vty, "\nTotal number of prefixes %ld\n",
13657 output_count);
13658 }
0b16f239 13659
d62a17ae 13660 return CMD_SUCCESS;
a636c635 13661}
50ef26d4 13662
f20ce998
DS
13663DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13664 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13665 "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]",
13666 SHOW_STR
13667 IP_STR
13668 BGP_STR
13669 BGP_INSTANCE_HELP_STR
13670 BGP_AFI_HELP_STR
13671 BGP_SAFI_WITH_LABEL_HELP_STR
13672 "Detailed information on TCP and BGP neighbor connections\n"
13673 "Neighbor to display information about\n"
13674 "Neighbor to display information about\n"
13675 "Neighbor on BGP configured interface\n"
13676 "Display the routes selected by best path\n"
13677 JSON_STR
13678 "Increase table width for longer prefixes\n")
13679{
13680 afi_t afi = AFI_IP6;
13681 safi_t safi = SAFI_UNICAST;
13682 char *rmap_name = NULL;
13683 char *peerstr = NULL;
13684 struct bgp *bgp = NULL;
13685 struct peer *peer;
13686 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13687 int idx = 0;
96f3485c
MK
13688 uint8_t show_flags = 0;
13689
13690 if (uj)
13691 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13692
13693 if (wide)
13694 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13695
13696 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13697 &bgp, uj);
13698
13699 if (!idx)
13700 return CMD_WARNING;
13701
13702 argv_find(argv, argc, "neighbors", &idx);
13703 peerstr = argv[++idx]->arg;
13704
13705 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13706 if (!peer)
13707 return CMD_WARNING;
13708
96f3485c
MK
13709 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13710 show_flags);
f20ce998
DS
13711}
13712
ae248832 13713DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13714 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13715 "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 13716 SHOW_STR
13717 IP_STR
13718 BGP_STR
a636c635 13719 BGP_INSTANCE_HELP_STR
7395a2c9 13720 BGP_AFI_HELP_STR
4dd6177e 13721 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13722 "Display the entries for all address families\n"
718e3744 13723 "Detailed information on TCP and BGP neighbor connections\n"
13724 "Neighbor to display information about\n"
13725 "Neighbor to display information about\n"
91d37724 13726 "Neighbor on BGP configured interface\n"
a636c635 13727 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13728 "Display the received routes from neighbor\n"
13729 "Display the filtered routes received from neighbor\n"
a636c635
DW
13730 "Route-map to modify the attributes\n"
13731 "Name of the route map\n"
ae248832
MK
13732 JSON_STR
13733 "Increase table width for longer prefixes\n")
718e3744 13734{
d62a17ae 13735 afi_t afi = AFI_IP6;
13736 safi_t safi = SAFI_UNICAST;
13737 char *rmap_name = NULL;
13738 char *peerstr = NULL;
d62a17ae 13739 struct bgp *bgp = NULL;
13740 struct peer *peer;
6392aaa6 13741 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13742 int idx = 0;
96f3485c
MK
13743 bool first = true;
13744 uint8_t show_flags = 0;
6392aaa6 13745
96f3485c 13746 if (uj) {
d62a17ae 13747 argc--;
96f3485c
MK
13748 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13749 }
13750
13751 if (all) {
13752 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13753 if (argv_find(argv, argc, "ipv4", &idx))
13754 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13755
13756 if (argv_find(argv, argc, "ipv6", &idx))
13757 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13758 }
13759
13760 if (wide)
13761 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13762
9f049418
DS
13763 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13764 &bgp, uj);
13765 if (!idx)
13766 return CMD_WARNING;
13767
d62a17ae 13768 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13769 argv_find(argv, argc, "neighbors", &idx);
13770 peerstr = argv[++idx]->arg;
8c3deaae 13771
d62a17ae 13772 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13773 if (!peer)
13774 return CMD_WARNING;
856ca177 13775
d62a17ae 13776 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13777 type = bgp_show_adj_route_advertised;
13778 else if (argv_find(argv, argc, "received-routes", &idx))
13779 type = bgp_show_adj_route_received;
13780 else if (argv_find(argv, argc, "filtered-routes", &idx))
13781 type = bgp_show_adj_route_filtered;
13782
d62a17ae 13783 if (argv_find(argv, argc, "route-map", &idx))
13784 rmap_name = argv[++idx]->arg;
95cbbd2a 13785
96f3485c
MK
13786 if (!all)
13787 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13788 show_flags);
13789 if (uj)
13790 vty_out(vty, "{\n");
13791
13792 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13793 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13794 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13795 : AFI_IP6;
13796 FOREACH_SAFI (safi) {
96f3485c
MK
13797 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13798 continue;
13799
13800 if (uj) {
13801 if (first)
13802 first = false;
13803 else
13804 vty_out(vty, ",\n");
13805 vty_out(vty, "\"%s\":",
13806 get_afi_safi_str(afi, safi, true));
13807 } else
13808 vty_out(vty, "\nFor address family: %s\n",
13809 get_afi_safi_str(afi, safi, false));
13810
13811 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13812 show_flags);
13813 }
13814 } else {
13815 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13816 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13817 continue;
13818
13819 if (uj) {
13820 if (first)
13821 first = false;
13822 else
13823 vty_out(vty, ",\n");
13824 vty_out(vty, "\"%s\":",
13825 get_afi_safi_str(afi, safi, true));
13826 } else
13827 vty_out(vty, "\nFor address family: %s\n",
13828 get_afi_safi_str(afi, safi, false));
13829
13830 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13831 show_flags);
13832 }
13833 }
13834 if (uj)
13835 vty_out(vty, "}\n");
13836
13837 return CMD_SUCCESS;
95cbbd2a
ML
13838}
13839
718e3744 13840DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13841 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13842 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13843 SHOW_STR
13844 IP_STR
13845 BGP_STR
8c3deaae
QY
13846 "Address Family\n"
13847 "Address Family\n"
718e3744 13848 "Address Family modifier\n"
13849 "Detailed information on TCP and BGP neighbor connections\n"
13850 "Neighbor to display information about\n"
13851 "Neighbor to display information about\n"
91d37724 13852 "Neighbor on BGP configured interface\n"
718e3744 13853 "Display information received from a BGP neighbor\n"
856ca177 13854 "Display the prefixlist filter\n"
9973d184 13855 JSON_STR)
718e3744 13856{
d62a17ae 13857 afi_t afi = AFI_IP6;
13858 safi_t safi = SAFI_UNICAST;
13859 char *peerstr = NULL;
13860
13861 char name[BUFSIZ];
13862 union sockunion su;
13863 struct peer *peer;
13864 int count, ret;
13865
13866 int idx = 0;
13867
13868 /* show [ip] bgp */
13869 if (argv_find(argv, argc, "ip", &idx))
13870 afi = AFI_IP;
13871 /* [<ipv4|ipv6> [unicast]] */
13872 if (argv_find(argv, argc, "ipv4", &idx))
13873 afi = AFI_IP;
13874 if (argv_find(argv, argc, "ipv6", &idx))
13875 afi = AFI_IP6;
13876 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13877 argv_find(argv, argc, "neighbors", &idx);
13878 peerstr = argv[++idx]->arg;
13879
9f049418 13880 bool uj = use_json(argc, argv);
d62a17ae 13881
13882 ret = str2sockunion(peerstr, &su);
13883 if (ret < 0) {
13884 peer = peer_lookup_by_conf_if(NULL, peerstr);
13885 if (!peer) {
13886 if (uj)
13887 vty_out(vty, "{}\n");
13888 else
13889 vty_out(vty,
13890 "%% Malformed address or name: %s\n",
13891 peerstr);
13892 return CMD_WARNING;
13893 }
13894 } else {
13895 peer = peer_lookup(NULL, &su);
13896 if (!peer) {
13897 if (uj)
13898 vty_out(vty, "{}\n");
13899 else
13900 vty_out(vty, "No peer\n");
13901 return CMD_WARNING;
13902 }
13903 }
718e3744 13904
4ced1a2c 13905 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13906 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13907 if (count) {
13908 if (!uj)
13909 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13910 get_afi_safi_str(afi, safi, false));
d62a17ae 13911 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13912 } else {
13913 if (uj)
13914 vty_out(vty, "{}\n");
13915 else
13916 vty_out(vty, "No functional output\n");
13917 }
718e3744 13918
d62a17ae 13919 return CMD_SUCCESS;
13920}
13921
13922static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13923 afi_t afi, safi_t safi,
9f049418 13924 enum bgp_show_type type, bool use_json)
d62a17ae 13925{
96f3485c
MK
13926 uint8_t show_flags = 0;
13927
13928 if (use_json)
13929 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13930
d62a17ae 13931 if (!peer || !peer->afc[afi][safi]) {
13932 if (use_json) {
13933 json_object *json_no = NULL;
13934 json_no = json_object_new_object();
13935 json_object_string_add(
13936 json_no, "warning",
13937 "No such neighbor or address family");
13938 vty_out(vty, "%s\n",
13939 json_object_to_json_string(json_no));
13940 json_object_free(json_no);
13941 } else
13942 vty_out(vty, "%% No such neighbor or address family\n");
13943 return CMD_WARNING;
13944 }
47fc97cc 13945
7daf25a3
TA
13946 /* labeled-unicast routes live in the unicast table */
13947 if (safi == SAFI_LABELED_UNICAST)
13948 safi = SAFI_UNICAST;
13949
1e2ce4f1
DS
13950 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
13951 RPKI_NOT_BEING_USED);
718e3744 13952}
13953
dba3c1d3
PG
13954DEFUN (show_ip_bgp_flowspec_routes_detailed,
13955 show_ip_bgp_flowspec_routes_detailed_cmd,
13956 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13957 SHOW_STR
13958 IP_STR
13959 BGP_STR
13960 BGP_INSTANCE_HELP_STR
13961 BGP_AFI_HELP_STR
13962 "SAFI Flowspec\n"
13963 "Detailed information on flowspec entries\n"
13964 JSON_STR)
13965{
13966 afi_t afi = AFI_IP;
13967 safi_t safi = SAFI_UNICAST;
13968 struct bgp *bgp = NULL;
13969 int idx = 0;
9f049418 13970 bool uj = use_json(argc, argv);
96f3485c 13971 uint8_t show_flags = 0;
9f049418 13972
96f3485c 13973 if (uj) {
9f049418 13974 argc--;
96f3485c
MK
13975 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13976 }
dba3c1d3
PG
13977
13978 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13979 &bgp, uj);
dba3c1d3
PG
13980 if (!idx)
13981 return CMD_WARNING;
13982
96f3485c 13983 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 13984 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
13985}
13986
718e3744 13987DEFUN (show_ip_bgp_neighbor_routes,
13988 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13989 "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 13990 SHOW_STR
13991 IP_STR
13992 BGP_STR
8386ac43 13993 BGP_INSTANCE_HELP_STR
4f280b15 13994 BGP_AFI_HELP_STR
4dd6177e 13995 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13996 "Detailed information on TCP and BGP neighbor connections\n"
13997 "Neighbor to display information about\n"
13998 "Neighbor to display information about\n"
91d37724 13999 "Neighbor on BGP configured interface\n"
2525cf39 14000 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14001 "Display the dampened routes received from neighbor\n"
14002 "Display routes learned from neighbor\n"
9973d184 14003 JSON_STR)
718e3744 14004{
d62a17ae 14005 char *peerstr = NULL;
14006 struct bgp *bgp = NULL;
14007 afi_t afi = AFI_IP6;
14008 safi_t safi = SAFI_UNICAST;
14009 struct peer *peer;
14010 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14011 int idx = 0;
9f049418
DS
14012 bool uj = use_json(argc, argv);
14013
14014 if (uj)
14015 argc--;
bb46e94f 14016
d62a17ae 14017 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14018 &bgp, uj);
d62a17ae 14019 if (!idx)
14020 return CMD_WARNING;
c493f2d8 14021
d62a17ae 14022 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14023 argv_find(argv, argc, "neighbors", &idx);
14024 peerstr = argv[++idx]->arg;
8c3deaae 14025
d62a17ae 14026 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14027 if (!peer)
d62a17ae 14028 return CMD_WARNING;
bb46e94f 14029
d62a17ae 14030 if (argv_find(argv, argc, "flap-statistics", &idx))
14031 sh_type = bgp_show_type_flap_neighbor;
14032 else if (argv_find(argv, argc, "dampened-routes", &idx))
14033 sh_type = bgp_show_type_damp_neighbor;
14034 else if (argv_find(argv, argc, "routes", &idx))
14035 sh_type = bgp_show_type_neighbor;
2525cf39 14036
d62a17ae 14037 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14038}
6b0655a2 14039
734b349e 14040struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14041
d62a17ae 14042struct bgp_distance {
14043 /* Distance value for the IP source prefix. */
d7c0a89a 14044 uint8_t distance;
718e3744 14045
d62a17ae 14046 /* Name of the access-list to be matched. */
14047 char *access_list;
718e3744 14048};
14049
4f280b15
LB
14050DEFUN (show_bgp_afi_vpn_rd_route,
14051 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14052 "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
14053 SHOW_STR
14054 BGP_STR
14055 BGP_AFI_HELP_STR
14056 "Address Family modifier\n"
14057 "Display information for a route distinguisher\n"
14058 "Route Distinguisher\n"
a111dd97 14059 "All Route Distinguishers\n"
7395a2c9
DS
14060 "Network in the BGP routing table to display\n"
14061 "Network in the BGP routing table to display\n"
14062 JSON_STR)
4f280b15 14063{
d62a17ae 14064 int ret;
14065 struct prefix_rd prd;
14066 afi_t afi = AFI_MAX;
14067 int idx = 0;
4f280b15 14068
ff6566f3
DS
14069 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14070 vty_out(vty, "%% Malformed Address Family\n");
14071 return CMD_WARNING;
14072 }
14073
a111dd97
TA
14074 if (!strcmp(argv[5]->arg, "all"))
14075 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14076 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14077 RPKI_NOT_BEING_USED,
14078 use_json(argc, argv));
14079
d62a17ae 14080 ret = str2prefix_rd(argv[5]->arg, &prd);
14081 if (!ret) {
14082 vty_out(vty, "%% Malformed Route Distinguisher\n");
14083 return CMD_WARNING;
14084 }
ff6566f3 14085
d62a17ae 14086 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14087 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14088 use_json(argc, argv));
4f280b15
LB
14089}
14090
d62a17ae 14091static struct bgp_distance *bgp_distance_new(void)
718e3744 14092{
d62a17ae 14093 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14094}
14095
d62a17ae 14096static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14097{
d62a17ae 14098 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14099}
14100
37a87b8f
CS
14101int bgp_distance_set(uint8_t distance, const char *ip_str,
14102 const char *access_list_str, afi_t afi, safi_t safi,
14103 char *errmsg, size_t errmsg_len)
718e3744 14104{
d62a17ae 14105 int ret;
d62a17ae 14106 struct prefix p;
9bcb3eef 14107 struct bgp_dest *dest;
d62a17ae 14108 struct bgp_distance *bdistance;
718e3744 14109
d62a17ae 14110 ret = str2prefix(ip_str, &p);
14111 if (ret == 0) {
37a87b8f 14112 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14113 return CMD_WARNING_CONFIG_FAILED;
14114 }
718e3744 14115
d62a17ae 14116 /* Get BGP distance node. */
9bcb3eef
DS
14117 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14118 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14119 if (bdistance)
9bcb3eef 14120 bgp_dest_unlock_node(dest);
ca2e160d 14121 else {
d62a17ae 14122 bdistance = bgp_distance_new();
9bcb3eef 14123 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14124 }
718e3744 14125
d62a17ae 14126 /* Set distance value. */
14127 bdistance->distance = distance;
718e3744 14128
d62a17ae 14129 /* Reset access-list configuration. */
e1b36e13 14130 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14131 if (access_list_str)
14132 bdistance->access_list =
14133 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14134
d62a17ae 14135 return CMD_SUCCESS;
718e3744 14136}
14137
37a87b8f
CS
14138int bgp_distance_unset(uint8_t distance, const char *ip_str,
14139 const char *access_list_str, afi_t afi, safi_t safi,
14140 char *errmsg, size_t errmsg_len)
718e3744 14141{
d62a17ae 14142 int ret;
d62a17ae 14143 struct prefix p;
9bcb3eef 14144 struct bgp_dest *dest;
d62a17ae 14145 struct bgp_distance *bdistance;
718e3744 14146
d62a17ae 14147 ret = str2prefix(ip_str, &p);
14148 if (ret == 0) {
37a87b8f 14149 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14150 return CMD_WARNING_CONFIG_FAILED;
14151 }
718e3744 14152
9bcb3eef
DS
14153 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14154 if (!dest) {
37a87b8f 14155 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 14156 return CMD_WARNING_CONFIG_FAILED;
14157 }
718e3744 14158
9bcb3eef 14159 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 14160
d62a17ae 14161 if (bdistance->distance != distance) {
37a87b8f
CS
14162 snprintf(errmsg, errmsg_len,
14163 "Distance does not match configured\n");
d62a17ae 14164 return CMD_WARNING_CONFIG_FAILED;
14165 }
718e3744 14166
0a22ddfb 14167 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14168 bgp_distance_free(bdistance);
718e3744 14169
9bcb3eef
DS
14170 bgp_dest_set_bgp_path_info(dest, NULL);
14171 bgp_dest_unlock_node(dest);
14172 bgp_dest_unlock_node(dest);
718e3744 14173
d62a17ae 14174 return CMD_SUCCESS;
718e3744 14175}
14176
718e3744 14177/* Apply BGP information to distance method. */
b8685f9b 14178uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14179 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14180{
9bcb3eef 14181 struct bgp_dest *dest;
801bb996 14182 struct prefix q = {0};
d62a17ae 14183 struct peer *peer;
14184 struct bgp_distance *bdistance;
14185 struct access_list *alist;
14186 struct bgp_static *bgp_static;
14187
14188 if (!bgp)
14189 return 0;
14190
40381db7 14191 peer = pinfo->peer;
d62a17ae 14192
7b7d48e5
DS
14193 if (pinfo->attr->distance)
14194 return pinfo->attr->distance;
14195
801bb996
CS
14196 /* Check source address.
14197 * Note: for aggregate route, peer can have unspec af type.
14198 */
14199 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14200 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14201 return 0;
14202
9bcb3eef
DS
14203 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14204 if (dest) {
14205 bdistance = bgp_dest_get_bgp_distance_info(dest);
14206 bgp_dest_unlock_node(dest);
d62a17ae 14207
14208 if (bdistance->access_list) {
14209 alist = access_list_lookup(afi, bdistance->access_list);
14210 if (alist
14211 && access_list_apply(alist, p) == FILTER_PERMIT)
14212 return bdistance->distance;
14213 } else
14214 return bdistance->distance;
718e3744 14215 }
718e3744 14216
d62a17ae 14217 /* Backdoor check. */
9bcb3eef
DS
14218 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14219 if (dest) {
14220 bgp_static = bgp_dest_get_bgp_static_info(dest);
14221 bgp_dest_unlock_node(dest);
718e3744 14222
d62a17ae 14223 if (bgp_static->backdoor) {
14224 if (bgp->distance_local[afi][safi])
14225 return bgp->distance_local[afi][safi];
14226 else
14227 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14228 }
718e3744 14229 }
718e3744 14230
d62a17ae 14231 if (peer->sort == BGP_PEER_EBGP) {
14232 if (bgp->distance_ebgp[afi][safi])
14233 return bgp->distance_ebgp[afi][safi];
14234 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14235 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14236 if (bgp->distance_ibgp[afi][safi])
14237 return bgp->distance_ibgp[afi][safi];
14238 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14239 } else {
14240 if (bgp->distance_local[afi][safi])
14241 return bgp->distance_local[afi][safi];
14242 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14243 }
718e3744 14244}
14245
a612fb77
DA
14246/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14247 * we should tell ZEBRA update the routes for a specific
14248 * AFI/SAFI to reflect changes in RIB.
14249 */
37a87b8f
CS
14250void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14251 safi_t update_safi)
a612fb77
DA
14252{
14253 afi_t afi;
14254 safi_t safi;
14255
14256 FOREACH_AFI_SAFI (afi, safi) {
14257 if (!bgp_fibupd_safi(safi))
14258 continue;
14259
8b54bc30
DA
14260 if (afi != update_afi && safi != update_safi)
14261 continue;
14262
14263 if (BGP_DEBUG(zebra, ZEBRA))
14264 zlog_debug(
14265 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14266 __func__, afi, safi);
14267 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14268 }
14269}
14270
37a87b8f
CS
14271DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14272 "distance bgp (1-255) (1-255) (1-255)",
14273 "Define an administrative distance\n"
14274 "BGP distance\n"
14275 "Distance for routes external to the AS\n"
14276 "Distance for routes internal to the AS\n"
14277 "Distance for local routes\n")
718e3744 14278{
d62a17ae 14279 int idx_number = 2;
14280 int idx_number_2 = 3;
14281 int idx_number_3 = 4;
14282 afi_t afi;
14283 safi_t safi;
37a87b8f 14284 char xpath[XPATH_MAXLEN];
718e3744 14285
d62a17ae 14286 afi = bgp_node_afi(vty);
14287 safi = bgp_node_safi(vty);
718e3744 14288
37a87b8f
CS
14289 snprintf(
14290 xpath, sizeof(xpath),
14291 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14292 yang_afi_safi_value2identity(afi, safi),
14293 bgp_afi_safi_get_container_str(afi, safi));
14294 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14295 snprintf(
14296 xpath, sizeof(xpath),
14297 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14298 yang_afi_safi_value2identity(afi, safi),
14299 bgp_afi_safi_get_container_str(afi, safi));
14300 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14301 argv[idx_number_2]->arg);
14302 snprintf(
14303 xpath, sizeof(xpath),
14304 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14305 yang_afi_safi_value2identity(afi, safi),
14306 bgp_afi_safi_get_container_str(afi, safi));
14307
14308 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14309 argv[idx_number_3]->arg);
14310
14311 return nb_cli_apply_changes(vty, NULL);
14312}
14313
14314DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14315 "no distance bgp [(1-255) (1-255) (1-255)]",
14316 NO_STR
14317 "Define an administrative distance\n"
14318 "BGP distance\n"
14319 "Distance for routes external to the AS\n"
14320 "Distance for routes internal to the AS\n"
14321 "Distance for local routes\n")
14322{
14323 afi_t afi;
14324 safi_t safi;
14325 char xpath[XPATH_MAXLEN];
14326
14327 afi = bgp_node_afi(vty);
14328 safi = bgp_node_safi(vty);
14329
14330 snprintf(
14331 xpath, sizeof(xpath),
14332 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14333 yang_afi_safi_value2identity(afi, safi),
14334 bgp_afi_safi_get_container_str(afi, safi));
14335 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14336 snprintf(
14337 xpath, sizeof(xpath),
14338 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14339 yang_afi_safi_value2identity(afi, safi),
14340 bgp_afi_safi_get_container_str(afi, safi));
14341 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14342 snprintf(
14343 xpath, sizeof(xpath),
14344 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14345 yang_afi_safi_value2identity(afi, safi),
14346 bgp_afi_safi_get_container_str(afi, safi));
14347
14348 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14349
14350 return nb_cli_apply_changes(vty, NULL);
718e3744 14351}
14352
37a87b8f
CS
14353void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14354 struct lyd_node *dnode,
14355 bool show_defaults)
718e3744 14356{
37a87b8f
CS
14357 uint8_t distance_ebgp, distance_ibgp, distance_local;
14358
14359 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14360 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14361 distance_local = yang_dnode_get_uint8(dnode, "./local");
14362
14363 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14364 distance_local);
14365}
14366
8cc7152a
CS
14367DEFPY_YANG(bgp_distance_source,
14368 bgp_distance_source_cmd,
14369 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14370 NO_STR
14371 "Define an administrative distance\n"
8cc7152a 14372 "Distance value\n"
e12affc1
SW
14373 "IPv4 source prefix\n"
14374 "IPv6 source prefix\n"
37a87b8f 14375 "Access list name\n")
718e3744 14376{
37a87b8f
CS
14377 afi_t afi;
14378 safi_t safi;
14379 char xpath[XPATH_MAXLEN];
14380
14381 afi = bgp_node_afi(vty);
14382 safi = bgp_node_safi(vty);
14383
8cc7152a
CS
14384 if (!no) {
14385 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14386 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14387 distance_str);
14388 if (acl)
14389 nb_cli_enqueue_change(vty,
14390 "./access-list-policy-export",
14391 NB_OP_CREATE, acl);
14392 else
14393 nb_cli_enqueue_change(vty,
14394 "./access-list-policy-export",
14395 NB_OP_DESTROY, NULL);
14396 } else {
14397 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14398 }
37a87b8f
CS
14399
14400 snprintf(
14401 xpath, sizeof(xpath),
14402 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14403 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14404 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14405
14406 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14407}
14408
37a87b8f
CS
14409void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14410 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14411{
14412 vty_out(vty, " distance %d %s %s\n",
14413 yang_dnode_get_uint8(dnode, "./distance"),
14414 yang_dnode_get_string(dnode, "./prefix"),
14415 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14416 ? yang_dnode_get_string(dnode,
14417 "./access-list-policy-export")
14418 : "");
14419}
14420
7c98d487
DA
14421DEFPY_YANG(
14422 bgp_dampening, bgp_dampening_cmd,
14423 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14424 NO_STR
14425 "BGP Specific commands\n"
14426 "Enable route-flap dampening\n"
14427 "Half-life time for the penalty\n"
14428 "Value to start reusing a route\n"
14429 "Value to start suppressing a route\n"
14430 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14431{
14432 afi_t afi;
14433 safi_t safi;
14434 char xpath[XPATH_MAXLEN];
718e3744 14435
37a87b8f
CS
14436 afi = bgp_node_afi(vty);
14437 safi = bgp_node_safi(vty);
14438
d9ce5113
CS
14439 if (!no) {
14440 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14441 if (argc == 6) {
14442 nb_cli_enqueue_change(vty, "./reach-decay",
14443 NB_OP_MODIFY, halflife_str);
14444 nb_cli_enqueue_change(vty, "./reuse-above",
14445 NB_OP_MODIFY, reuse_str);
14446 nb_cli_enqueue_change(vty, "./suppress-above",
14447 NB_OP_MODIFY, suppress_str);
14448 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14449 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14450 } if (argc == 3) {
14451 nb_cli_enqueue_change(vty, "./reach-decay",
14452 NB_OP_MODIFY, halflife_str);
14453 }
14454 } else {
14455 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14456 }
7ebe9748 14457
37a87b8f
CS
14458 snprintf(
14459 xpath, sizeof(xpath),
14460 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14461 yang_afi_safi_value2identity(afi, safi),
14462 bgp_afi_safi_get_container_str(afi, safi));
14463
14464 return nb_cli_apply_changes(vty, xpath);
718e3744 14465}
14466
37a87b8f
CS
14467void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14468 struct lyd_node *dnode,
14469 bool show_defaults)
718e3744 14470{
37a87b8f
CS
14471 if (!yang_dnode_get_bool(dnode, "./enable"))
14472 return;
14473
14474 int half = DEFAULT_HALF_LIFE * 60;
14475 int reuse = DEFAULT_REUSE;
14476 int suppress = DEFAULT_SUPPRESS;
14477 int max;
14478
14479 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14480 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14481 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14482 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14483
14484 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14485 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14486 vty_out(vty, " bgp dampening\n");
14487 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14488 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14489 vty_out(vty, " bgp dampening %u\n", half);
14490 else
14491 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14492 suppress, max);
718e3744 14493}
14494
718e3744 14495/* Display specified route of BGP table. */
d62a17ae 14496static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14497 const char *ip_str, afi_t afi, safi_t safi,
14498 struct prefix_rd *prd, int prefix_check)
14499{
14500 int ret;
14501 struct prefix match;
9bcb3eef
DS
14502 struct bgp_dest *dest;
14503 struct bgp_dest *rm;
40381db7
DS
14504 struct bgp_path_info *pi;
14505 struct bgp_path_info *pi_temp;
d62a17ae 14506 struct bgp *bgp;
14507 struct bgp_table *table;
14508
14509 /* BGP structure lookup. */
14510 if (view_name) {
14511 bgp = bgp_lookup_by_name(view_name);
14512 if (bgp == NULL) {
14513 vty_out(vty, "%% Can't find BGP instance %s\n",
14514 view_name);
14515 return CMD_WARNING;
14516 }
14517 } else {
14518 bgp = bgp_get_default();
14519 if (bgp == NULL) {
14520 vty_out(vty, "%% No BGP process is configured\n");
14521 return CMD_WARNING;
14522 }
718e3744 14523 }
718e3744 14524
d62a17ae 14525 /* Check IP address argument. */
14526 ret = str2prefix(ip_str, &match);
14527 if (!ret) {
14528 vty_out(vty, "%% address is malformed\n");
14529 return CMD_WARNING;
14530 }
718e3744 14531
d62a17ae 14532 match.family = afi2family(afi);
14533
14534 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14535 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14536 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14537 dest = bgp_route_next(dest)) {
14538 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14539
9bcb3eef 14540 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14541 continue;
9bcb3eef 14542 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14543 if (!table)
ea47320b
DL
14544 continue;
14545 if ((rm = bgp_node_match(table, &match)) == NULL)
14546 continue;
d62a17ae 14547
9bcb3eef 14548 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14549
ea47320b 14550 if (!prefix_check
b54892e0 14551 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14552 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14553 while (pi) {
14554 if (pi->extra && pi->extra->damp_info) {
14555 pi_temp = pi->next;
ea47320b 14556 bgp_damp_info_free(
40ec3340
DS
14557 &pi->extra->damp_info,
14558 &bgp->damp[afi][safi],
a935f597 14559 1, afi, safi);
40381db7 14560 pi = pi_temp;
ea47320b 14561 } else
40381db7 14562 pi = pi->next;
d62a17ae 14563 }
ea47320b
DL
14564 }
14565
9bcb3eef 14566 bgp_dest_unlock_node(rm);
d62a17ae 14567 }
14568 } else {
9bcb3eef 14569 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14570 != NULL) {
9bcb3eef 14571 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14572
d62a17ae 14573 if (!prefix_check
9bcb3eef
DS
14574 || dest_p->prefixlen == match.prefixlen) {
14575 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14576 while (pi) {
14577 if (pi->extra && pi->extra->damp_info) {
14578 pi_temp = pi->next;
c8ddbd48 14579 struct bgp_damp_info *bdi =
14580 pi->extra->damp_info;
14581 if (bdi->lastrecord
14582 == BGP_RECORD_UPDATE) {
14583 bgp_aggregate_increment(
14584 bgp,
14585 &bdi->dest->p,
14586 bdi->path,
14587 bdi->afi,
14588 bdi->safi);
14589 bgp_process(bgp,
14590 bdi->dest,
14591 bdi->afi,
14592 bdi->safi);
14593 }
d62a17ae 14594 bgp_damp_info_free(
40ec3340
DS
14595 &pi->extra->damp_info,
14596 &bgp->damp[afi][safi],
a935f597 14597 1, afi, safi);
40381db7 14598 pi = pi_temp;
d62a17ae 14599 } else
40381db7 14600 pi = pi->next;
d62a17ae 14601 }
14602 }
14603
9bcb3eef 14604 bgp_dest_unlock_node(dest);
d62a17ae 14605 }
14606 }
718e3744 14607
d62a17ae 14608 return CMD_SUCCESS;
718e3744 14609}
14610
14611DEFUN (clear_ip_bgp_dampening,
14612 clear_ip_bgp_dampening_cmd,
14613 "clear ip bgp dampening",
14614 CLEAR_STR
14615 IP_STR
14616 BGP_STR
14617 "Clear route flap dampening information\n")
14618{
40ec3340 14619 VTY_DECLVAR_CONTEXT(bgp, bgp);
c8ddbd48 14620 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
40ec3340 14621 SAFI_UNICAST);
d62a17ae 14622 return CMD_SUCCESS;
718e3744 14623}
14624
14625DEFUN (clear_ip_bgp_dampening_prefix,
14626 clear_ip_bgp_dampening_prefix_cmd,
14627 "clear ip bgp dampening A.B.C.D/M",
14628 CLEAR_STR
14629 IP_STR
14630 BGP_STR
14631 "Clear route flap dampening information\n"
0c7b1b01 14632 "IPv4 prefix\n")
718e3744 14633{
d62a17ae 14634 int idx_ipv4_prefixlen = 4;
14635 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14636 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14637}
14638
14639DEFUN (clear_ip_bgp_dampening_address,
14640 clear_ip_bgp_dampening_address_cmd,
14641 "clear ip bgp dampening A.B.C.D",
14642 CLEAR_STR
14643 IP_STR
14644 BGP_STR
14645 "Clear route flap dampening information\n"
14646 "Network to clear damping information\n")
14647{
d62a17ae 14648 int idx_ipv4 = 4;
14649 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14650 SAFI_UNICAST, NULL, 0);
718e3744 14651}
14652
14653DEFUN (clear_ip_bgp_dampening_address_mask,
14654 clear_ip_bgp_dampening_address_mask_cmd,
14655 "clear ip bgp dampening A.B.C.D A.B.C.D",
14656 CLEAR_STR
14657 IP_STR
14658 BGP_STR
14659 "Clear route flap dampening information\n"
14660 "Network to clear damping information\n"
14661 "Network mask\n")
14662{
d62a17ae 14663 int idx_ipv4 = 4;
14664 int idx_ipv4_2 = 5;
14665 int ret;
14666 char prefix_str[BUFSIZ];
718e3744 14667
d62a17ae 14668 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14669 prefix_str, sizeof(prefix_str));
d62a17ae 14670 if (!ret) {
14671 vty_out(vty, "%% Inconsistent address and mask\n");
14672 return CMD_WARNING;
14673 }
718e3744 14674
d62a17ae 14675 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14676 NULL, 0);
718e3744 14677}
6b0655a2 14678
e3b78da8 14679static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14680{
14681 struct vty *vty = arg;
e3b78da8 14682 struct peer *peer = bucket->data;
825d9834
DS
14683 char buf[SU_ADDRSTRLEN];
14684
14685 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14686 sockunion2str(&peer->su, buf, sizeof(buf)));
14687}
14688
2a0e69ae
DS
14689DEFUN (show_bgp_listeners,
14690 show_bgp_listeners_cmd,
14691 "show bgp listeners",
14692 SHOW_STR
14693 BGP_STR
14694 "Display Listen Sockets and who created them\n")
14695{
14696 bgp_dump_listener_info(vty);
14697
14698 return CMD_SUCCESS;
14699}
14700
825d9834
DS
14701DEFUN (show_bgp_peerhash,
14702 show_bgp_peerhash_cmd,
14703 "show bgp peerhash",
14704 SHOW_STR
14705 BGP_STR
14706 "Display information about the BGP peerhash\n")
14707{
14708 struct list *instances = bm->bgp;
14709 struct listnode *node;
14710 struct bgp *bgp;
14711
14712 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14713 vty_out(vty, "BGP: %s\n", bgp->name);
14714 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14715 vty);
14716 }
14717
14718 return CMD_SUCCESS;
14719}
14720
587ff0fd 14721/* also used for encap safi */
2b791107
DL
14722static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14723 afi_t afi, safi_t safi)
d62a17ae 14724{
9bcb3eef
DS
14725 struct bgp_dest *pdest;
14726 struct bgp_dest *dest;
d62a17ae 14727 struct bgp_table *table;
b54892e0
DS
14728 const struct prefix *p;
14729 const struct prefix_rd *prd;
d62a17ae 14730 struct bgp_static *bgp_static;
14731 mpls_label_t label;
d62a17ae 14732 char rdbuf[RD_ADDRSTRLEN];
14733
14734 /* Network configuration. */
9bcb3eef
DS
14735 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14736 pdest = bgp_route_next(pdest)) {
14737 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14738 if (!table)
ea47320b 14739 continue;
d62a17ae 14740
9bcb3eef
DS
14741 for (dest = bgp_table_top(table); dest;
14742 dest = bgp_route_next(dest)) {
14743 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14744 if (bgp_static == NULL)
ea47320b 14745 continue;
d62a17ae 14746
9bcb3eef
DS
14747 p = bgp_dest_get_prefix(dest);
14748 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14749 pdest);
d62a17ae 14750
ea47320b 14751 /* "network" configuration display. */
06b9f471 14752 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14753 label = decode_label(&bgp_static->label);
14754
8228a9a7 14755 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14756 if (safi == SAFI_MPLS_VPN)
14757 vty_out(vty, " label %u", label);
14758
14759 if (bgp_static->rmap.name)
14760 vty_out(vty, " route-map %s",
14761 bgp_static->rmap.name);
e2a86ad9
DS
14762
14763 if (bgp_static->backdoor)
14764 vty_out(vty, " backdoor");
14765
ea47320b
DL
14766 vty_out(vty, "\n");
14767 }
14768 }
d62a17ae 14769}
14770
2b791107
DL
14771static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14772 afi_t afi, safi_t safi)
d62a17ae 14773{
9bcb3eef
DS
14774 struct bgp_dest *pdest;
14775 struct bgp_dest *dest;
d62a17ae 14776 struct bgp_table *table;
b54892e0
DS
14777 const struct prefix *p;
14778 const struct prefix_rd *prd;
d62a17ae 14779 struct bgp_static *bgp_static;
ff44f570 14780 char buf[PREFIX_STRLEN * 2];
d62a17ae 14781 char buf2[SU_ADDRSTRLEN];
14782 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14783 char esi_buf[ESI_BYTES];
d62a17ae 14784
14785 /* Network configuration. */
9bcb3eef
DS
14786 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14787 pdest = bgp_route_next(pdest)) {
14788 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14789 if (!table)
ea47320b 14790 continue;
d62a17ae 14791
9bcb3eef
DS
14792 for (dest = bgp_table_top(table); dest;
14793 dest = bgp_route_next(dest)) {
14794 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14795 if (bgp_static == NULL)
ea47320b 14796 continue;
d62a17ae 14797
ea47320b 14798 char *macrouter = NULL;
d62a17ae 14799
ea47320b
DL
14800 if (bgp_static->router_mac)
14801 macrouter = prefix_mac2str(
14802 bgp_static->router_mac, NULL, 0);
14803 if (bgp_static->eth_s_id)
0a50c248
AK
14804 esi_to_str(bgp_static->eth_s_id,
14805 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14806 p = bgp_dest_get_prefix(dest);
14807 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14808
ea47320b 14809 /* "network" configuration display. */
06b9f471 14810 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14811 if (p->u.prefix_evpn.route_type == 5) {
14812 char local_buf[PREFIX_STRLEN];
3714a385 14813 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14814 struct prefix_evpn *)p)
14815 ? AF_INET
14816 : AF_INET6;
3714a385 14817 inet_ntop(family,
14818 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14819 local_buf, PREFIX_STRLEN);
772270f3
QY
14820 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14821 p->u.prefix_evpn.prefix_addr
14822 .ip_prefix_length);
197cb530
PG
14823 } else {
14824 prefix2str(p, buf, sizeof(buf));
14825 }
ea47320b 14826
a4d82a8a
PZ
14827 if (bgp_static->gatewayIp.family == AF_INET
14828 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14829 inet_ntop(bgp_static->gatewayIp.family,
14830 &bgp_static->gatewayIp.u.prefix, buf2,
14831 sizeof(buf2));
ea47320b 14832 vty_out(vty,
7bcc8dac 14833 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14834 buf, rdbuf,
14835 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14836 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14837 macrouter);
14838
0a22ddfb 14839 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14840 }
14841 }
3da6fcd5
PG
14842}
14843
718e3744 14844/* Configuration of static route announcement and aggregate
14845 information. */
2b791107
DL
14846void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14847 safi_t safi)
d62a17ae 14848{
9bcb3eef 14849 struct bgp_dest *dest;
b54892e0 14850 const struct prefix *p;
d62a17ae 14851 struct bgp_static *bgp_static;
14852 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14853
2b791107
DL
14854 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14855 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14856 return;
14857 }
d62a17ae 14858
2b791107
DL
14859 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14860 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14861 return;
14862 }
d62a17ae 14863
14864 /* Network configuration. */
9bcb3eef
DS
14865 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14866 dest = bgp_route_next(dest)) {
14867 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14868 if (bgp_static == NULL)
ea47320b 14869 continue;
d62a17ae 14870
9bcb3eef 14871 p = bgp_dest_get_prefix(dest);
d62a17ae 14872
8228a9a7 14873 vty_out(vty, " network %pFX", p);
d62a17ae 14874
ea47320b
DL
14875 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14876 vty_out(vty, " label-index %u",
14877 bgp_static->label_index);
d62a17ae 14878
ea47320b
DL
14879 if (bgp_static->rmap.name)
14880 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14881
14882 if (bgp_static->backdoor)
14883 vty_out(vty, " backdoor");
718e3744 14884
ea47320b
DL
14885 vty_out(vty, "\n");
14886 }
14887
d62a17ae 14888 /* Aggregate-address configuration. */
9bcb3eef
DS
14889 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14890 dest = bgp_route_next(dest)) {
14891 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14892 if (bgp_aggregate == NULL)
ea47320b 14893 continue;
d62a17ae 14894
9bcb3eef 14895 p = bgp_dest_get_prefix(dest);
d62a17ae 14896
8228a9a7 14897 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14898
ea47320b
DL
14899 if (bgp_aggregate->as_set)
14900 vty_out(vty, " as-set");
d62a17ae 14901
ea47320b
DL
14902 if (bgp_aggregate->summary_only)
14903 vty_out(vty, " summary-only");
718e3744 14904
20894f50
DA
14905 if (bgp_aggregate->rmap.name)
14906 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14907
229757f1
DA
14908 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14909 vty_out(vty, " origin %s",
14910 bgp_origin2str(bgp_aggregate->origin));
14911
6aabb15d
RZ
14912 if (bgp_aggregate->match_med)
14913 vty_out(vty, " matching-MED-only");
14914
365ab2e7
RZ
14915 if (bgp_aggregate->suppress_map_name)
14916 vty_out(vty, " suppress-map %s",
14917 bgp_aggregate->suppress_map_name);
14918
ea47320b
DL
14919 vty_out(vty, "\n");
14920 }
d62a17ae 14921}
734b349e 14922
2b791107 14923void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14924 safi_t safi)
d62a17ae 14925{
9bcb3eef 14926 struct bgp_dest *dest;
d62a17ae 14927 struct bgp_distance *bdistance;
14928
14929 /* Distance configuration. */
14930 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14931 && bgp->distance_local[afi][safi]
14932 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14933 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14934 || bgp->distance_local[afi][safi]
14935 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14936 vty_out(vty, " distance bgp %d %d %d\n",
14937 bgp->distance_ebgp[afi][safi],
14938 bgp->distance_ibgp[afi][safi],
14939 bgp->distance_local[afi][safi]);
14940 }
734b349e 14941
9bcb3eef
DS
14942 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14943 dest = bgp_route_next(dest)) {
14944 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14945 if (bdistance != NULL)
56ca3b5b 14946 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14947 bdistance->distance, dest,
d62a17ae 14948 bdistance->access_list ? bdistance->access_list
14949 : "");
ca2e160d 14950 }
718e3744 14951}
14952
14953/* Allocate routing table structure and install commands. */
d62a17ae 14954void bgp_route_init(void)
14955{
14956 afi_t afi;
14957 safi_t safi;
14958
14959 /* Init BGP distance table. */
05c7a1cc 14960 FOREACH_AFI_SAFI (afi, safi)
960035b2 14961 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14962
14963 /* IPv4 BGP commands. */
14964 install_element(BGP_NODE, &bgp_table_map_cmd);
14965 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14966 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14967
554b3b10 14968 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14969
14970 /* IPv4 unicast configuration. */
14971 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14972 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14973 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14974
554b3b10 14975 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14976
14977 /* IPv4 multicast configuration. */
14978 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14979 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14980 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14981 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14982
14983 /* IPv4 labeled-unicast configuration. */
fb985e0c 14984 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14985 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14986
d62a17ae 14987 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14988 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14989 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14990 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14991 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14992 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14993 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14994 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14995
14996 install_element(VIEW_NODE,
14997 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14998 install_element(VIEW_NODE,
14999 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15000 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15001 install_element(VIEW_NODE,
15002 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15003#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15004 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15005#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15006 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15007 install_element(VIEW_NODE,
44c69747 15008 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15009
d62a17ae 15010 /* BGP dampening clear commands */
15011 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15012 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15013
d62a17ae 15014 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15015 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15016
15017 /* prefix count */
15018 install_element(ENABLE_NODE,
15019 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15020#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15021 install_element(ENABLE_NODE,
15022 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15023#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15024
d62a17ae 15025 /* New config IPv6 BGP commands. */
15026 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15027 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15028 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15029
554b3b10 15030 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15031
15032 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15033
fb985e0c
DA
15034 /* IPv6 labeled unicast address family. */
15035 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15036 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15037
d62a17ae 15038 install_element(BGP_NODE, &bgp_distance_cmd);
15039 install_element(BGP_NODE, &no_bgp_distance_cmd);
15040 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 15041 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15042 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15043 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 15044 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15045 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15046 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 15047 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15048 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 15049 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 15050 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15051 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 15052 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 15053
ef5f4b23 15054 /* BGP dampening */
d9ce5113
CS
15055 install_element(BGP_NODE, &bgp_dampening_cmd);
15056 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
15057 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
15058 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
15059 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
15060 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
15061 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 15062
15063 /* Large Communities */
15064 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15065 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15066
15067 /* show bgp ipv4 flowspec detailed */
15068 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15069
2a0e69ae 15070 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15071 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15072}
15073
15074void bgp_route_finish(void)
15075{
15076 afi_t afi;
15077 safi_t safi;
15078
05c7a1cc
QY
15079 FOREACH_AFI_SAFI (afi, safi) {
15080 bgp_table_unlock(bgp_distance_table[afi][safi]);
15081 bgp_distance_table[afi][safi] = NULL;
15082 }
228da428 15083}