]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
topotests: add bgp vpnv4 over gre test
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
7fd28dd2
PR
96DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 98 (rn, pi, added));
7fd28dd2 99
b5b99af8
DS
100DEFINE_HOOK(bgp_rpki_prefix_status,
101 (struct peer *peer, struct attr *attr,
102 const struct prefix *prefix),
8451921b 103 (peer, attr, prefix));
b5b99af8 104
2aad8c42
MS
105/* Render dest to prefix_rd based on safi */
106static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
107 safi_t safi);
108
718e3744 109/* Extern from bgp_dump.c */
dde72586
SH
110extern const char *bgp_origin_str[];
111extern const char *bgp_origin_long_str[];
3742de8d 112
b7d08f5a 113/* PMSI strings. */
114#define PMSI_TNLTYPE_STR_NO_INFO "No info"
115#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116static const struct message bgp_pmsi_tnltype_str[] = {
117 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 125 {0}
126};
b7d08f5a 127
9df8b37c 128#define VRFID_NONE_STR "-"
46aeabed 129#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 130
4a11bf2c 131DEFINE_HOOK(bgp_process,
9bcb3eef
DS
132 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
133 struct peer *peer, bool withdraw),
8451921b 134 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 135
4056a5f6
RZ
136/** Test if path is suppressed. */
137static bool bgp_path_suppressed(struct bgp_path_info *pi)
138{
139 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
140 return false;
141
142 return listcount(pi->extra->aggr_suppressors) > 0;
143}
4a11bf2c 144
9bcb3eef 145struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 146 safi_t safi, const struct prefix *p,
d62a17ae 147 struct prefix_rd *prd)
148{
9bcb3eef
DS
149 struct bgp_dest *dest;
150 struct bgp_dest *pdest = NULL;
d62a17ae 151
152 assert(table);
d62a17ae 153
154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN)) {
9bcb3eef 156 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 157
9bcb3eef
DS
158 if (!bgp_dest_has_bgp_path_info_data(pdest))
159 bgp_dest_set_bgp_table_info(
160 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 161 else
9bcb3eef
DS
162 bgp_dest_unlock_node(pdest);
163 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 164 }
718e3744 165
9bcb3eef 166 dest = bgp_node_get(table, p);
718e3744 167
d62a17ae 168 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
169 || (safi == SAFI_EVPN))
9bcb3eef 170 dest->pdest = pdest;
718e3744 171
9bcb3eef 172 return dest;
718e3744 173}
6b0655a2 174
9bcb3eef 175struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 176 safi_t safi, const struct prefix *p,
d62a17ae 177 struct prefix_rd *prd)
128ea8ab 178{
9bcb3eef
DS
179 struct bgp_dest *dest;
180 struct bgp_dest *pdest = NULL;
128ea8ab 181
d62a17ae 182 if (!table)
183 return NULL;
128ea8ab 184
d62a17ae 185 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
186 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
187 pdest = bgp_node_lookup(table, (struct prefix *)prd);
188 if (!pdest)
d62a17ae 189 return NULL;
128ea8ab 190
9bcb3eef
DS
191 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
192 bgp_dest_unlock_node(pdest);
d62a17ae 193 return NULL;
194 }
128ea8ab 195
9bcb3eef 196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 197 }
128ea8ab 198
9bcb3eef 199 dest = bgp_node_lookup(table, p);
128ea8ab 200
9bcb3eef 201 return dest;
128ea8ab 202}
203
18ee8310
DS
204/* Allocate bgp_path_info_extra */
205static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 206{
4b7e6066
DS
207 struct bgp_path_info_extra *new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
209 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
210 new->label[0] = MPLS_INVALID_LABEL;
211 new->num_labels = 0;
3e3708cb
PG
212 new->bgp_fs_pbr = NULL;
213 new->bgp_fs_iprule = NULL;
d62a17ae 214 return new;
fb982c25
PJ
215}
216
a2e219fe 217void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 218{
4b7e6066 219 struct bgp_path_info_extra *e;
d62a17ae 220
c93a3b77
DS
221 if (!extra || !*extra)
222 return;
d62a17ae 223
c93a3b77 224 e = *extra;
4538f895 225 if (e->damp_info)
b4f7f45b
IR
226 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
227 e->damp_info->safi);
4538f895 228
c93a3b77
DS
229 e->damp_info = NULL;
230 if (e->parent) {
40381db7 231 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 232
40381db7 233 if (bpi->net) {
0e70e6c8
DL
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
237 *
40381db7
DS
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
0e70e6c8
DL
241 */
242 unsigned refcount;
243
40381db7 244 bpi = bgp_path_info_lock(bpi);
c10e14e9 245 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 246 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 247 if (!refcount)
40381db7
DS
248 bpi->net = NULL;
249 bgp_path_info_unlock(bpi);
0e70e6c8 250 }
18ee8310 251 bgp_path_info_unlock(e->parent);
c93a3b77 252 e->parent = NULL;
d62a17ae 253 }
c93a3b77
DS
254
255 if (e->bgp_orig)
256 bgp_unlock(e->bgp_orig);
c26edcda 257
ff3bf9a4
DS
258 if (e->aggr_suppressors)
259 list_delete(&e->aggr_suppressors);
260
60605cbc
AK
261 if (e->mh_info)
262 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 263
ce3c0614
PG
264 if ((*extra)->bgp_fs_iprule)
265 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 266 if ((*extra)->bgp_fs_pbr)
6a154c88 267 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 268 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
269}
270
18ee8310
DS
271/* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
fb982c25 273 */
40381db7 274struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 275{
40381db7
DS
276 if (!pi->extra)
277 pi->extra = bgp_path_info_extra_new();
278 return pi->extra;
fb982c25
PJ
279}
280
718e3744 281/* Free bgp route information. */
9b6d8fcf 282static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 283{
05864da7 284 bgp_attr_unintern(&path->attr);
fb018d25 285
9b6d8fcf
DS
286 bgp_unlink_nexthop(path);
287 bgp_path_info_extra_free(&path->extra);
288 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
289 if (path->net)
290 bgp_addpath_free_info_data(&path->tx_addpath,
291 &path->net->tx_addpath);
718e3744 292
9b6d8fcf 293 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 294
9b6d8fcf 295 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 296}
297
9b6d8fcf 298struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 299{
9b6d8fcf
DS
300 path->lock++;
301 return path;
200df115 302}
303
9b6d8fcf 304struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 305{
9b6d8fcf
DS
306 assert(path && path->lock > 0);
307 path->lock--;
d62a17ae 308
9b6d8fcf 309 if (path->lock == 0) {
9b6d8fcf 310 bgp_path_info_free(path);
d62a17ae 311 return NULL;
312 }
200df115 313
9b6d8fcf 314 return path;
200df115 315}
316
f009ff26 317/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 318static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 319{
320 struct peer *peer;
321 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 322 bool set_flag = false;
f009ff26 323 struct bgp *bgp = NULL;
324 struct bgp_table *table = NULL;
325 afi_t afi = 0;
326 safi_t safi = 0;
f009ff26 327
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
330 */
9bcb3eef 331 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 332 return 0;
333
9bcb3eef 334 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 335 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 336 zlog_debug(
56ca3b5b
DL
337 "Route %pBD is in workqueue and being processed, not deferred.",
338 dest);
b54892e0 339
5f9c1aa2 340 return 0;
341 }
342
9bcb3eef 343 table = bgp_dest_table(dest);
f009ff26 344 if (table) {
345 bgp = table->bgp;
346 afi = table->afi;
347 safi = table->safi;
348 }
349
9bcb3eef 350 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 351 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
352 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
353 continue;
354
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
357 */
36235319
QY
358 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
359 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 360 set_flag = true;
f009ff26 361 } else {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
364 */
365 peer = old_pi->peer;
36235319
QY
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
367 && BGP_PEER_RESTARTING_MODE(peer)
368 && (old_pi
369 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 370 set_flag = true;
f009ff26 371 }
372 }
373 if (set_flag)
374 break;
375 }
376
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
378 * is active
379 */
2ba1fe69 380 if (set_flag && table) {
f009ff26 381 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
382 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
383 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 384 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 385 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
386 zlog_debug("DEFER route %pBD, dest %p", dest,
387 dest);
f009ff26 388 return 0;
389 }
390 }
391 return -1;
392}
393
9bcb3eef 394void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 395{
4b7e6066 396 struct bgp_path_info *top;
718e3744 397
9bcb3eef 398 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 399
6f94b685 400 pi->next = top;
40381db7 401 pi->prev = NULL;
d62a17ae 402 if (top)
40381db7 403 top->prev = pi;
9bcb3eef 404 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 405
40381db7 406 bgp_path_info_lock(pi);
9bcb3eef 407 bgp_dest_lock_node(dest);
40381db7 408 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 409 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 410 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 411}
412
d62a17ae 413/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 414 completion callback *only* */
9bcb3eef 415void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 416{
40381db7
DS
417 if (pi->next)
418 pi->next->prev = pi->prev;
419 if (pi->prev)
420 pi->prev->next = pi->next;
d62a17ae 421 else
9bcb3eef 422 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 423
40381db7
DS
424 bgp_path_info_mpath_dequeue(pi);
425 bgp_path_info_unlock(pi);
7fd28dd2 426 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 427 bgp_dest_unlock_node(dest);
718e3744 428}
429
9bcb3eef 430void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 431{
9bcb3eef 432 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 433 /* set of previous already took care of pcount */
40381db7 434 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 435}
436
18ee8310 437/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
438 called when a route is deleted and then quickly re-added before the
439 deletion has been processed */
9bcb3eef 440void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 441{
9bcb3eef 442 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 443 /* unset of previous already took care of pcount */
40381db7 444 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
445}
446
d62a17ae 447/* Adjust pcount as required */
9bcb3eef 448static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 449{
d62a17ae 450 struct bgp_table *table;
67174041 451
9bcb3eef 452 assert(dest && bgp_dest_table(dest));
40381db7 453 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 454
9bcb3eef 455 table = bgp_dest_table(dest);
67174041 456
40381db7 457 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 458 return;
459
40381db7
DS
460 if (!BGP_PATH_COUNTABLE(pi)
461 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 462
40381db7 463 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 464
465 /* slight hack, but more robust against errors. */
40381db7
DS
466 if (pi->peer->pcount[table->afi][table->safi])
467 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 468 else
450971aa 469 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 470 "Asked to decrement 0 prefix count for peer");
40381db7
DS
471 } else if (BGP_PATH_COUNTABLE(pi)
472 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
473 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
474 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 475 }
1a392d46
PJ
476}
477
40381db7
DS
478static int bgp_label_index_differs(struct bgp_path_info *pi1,
479 struct bgp_path_info *pi2)
28d58fd7 480{
40381db7 481 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 482}
1a392d46 483
18ee8310 484/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
485 * This is here primarily to keep prefix-count in check.
486 */
9bcb3eef 487void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 488 uint32_t flag)
1a392d46 489{
40381db7 490 SET_FLAG(pi->flags, flag);
d62a17ae 491
492 /* early bath if we know it's not a flag that changes countability state
493 */
494 if (!CHECK_FLAG(flag,
1defdda8 495 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 496 return;
497
9bcb3eef 498 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
499}
500
9bcb3eef 501void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 502 uint32_t flag)
1a392d46 503{
40381db7 504 UNSET_FLAG(pi->flags, flag);
d62a17ae 505
506 /* early bath if we know it's not a flag that changes countability state
507 */
508 if (!CHECK_FLAG(flag,
1defdda8 509 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 510 return;
511
9bcb3eef 512 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
513}
514
718e3744 515/* Get MED value. If MED value is missing and "bgp bestpath
516 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 517static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 518{
519 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
520 return attr->med;
521 else {
892fedb6 522 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 523 return BGP_MED_MAX;
524 else
525 return 0;
526 }
718e3744 527}
528
7533cad7
QY
529void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
530 size_t buf_len)
2ec1e66f 531{
40381db7 532 if (pi->addpath_rx_id)
7533cad7
QY
533 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
534 pi->peer->host, pi->addpath_rx_id);
d62a17ae 535 else
7533cad7 536 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 537}
9fbdd100 538
da0c0ef7
KM
539
540/*
541 * Get the ultimate path info.
542 */
543struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
544{
545 struct bgp_path_info *bpi_ultimate;
546
547 if (info->sub_type != BGP_ROUTE_IMPORTED)
548 return info;
549
550 for (bpi_ultimate = info;
551 bpi_ultimate->extra && bpi_ultimate->extra->parent;
552 bpi_ultimate = bpi_ultimate->extra->parent)
553 ;
554
555 return bpi_ultimate;
556}
557
d62a17ae 558/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 */
18ee8310
DS
560static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
561 struct bgp_path_info *exist, int *paths_eq,
562 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
563 char *pfx_buf, afi_t afi, safi_t safi,
564 enum bgp_path_selection_reason *reason)
d62a17ae 565{
5df26422 566 const struct prefix *new_p;
d62a17ae 567 struct attr *newattr, *existattr;
3061acc2
DA
568 enum bgp_peer_sort new_sort;
569 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
570 uint32_t new_pref;
571 uint32_t exist_pref;
572 uint32_t new_med;
573 uint32_t exist_med;
574 uint32_t new_weight;
575 uint32_t exist_weight;
d62a17ae 576 uint32_t newm, existm;
577 struct in_addr new_id;
578 struct in_addr exist_id;
579 int new_cluster;
580 int exist_cluster;
581 int internal_as_route;
582 int confed_as_route;
04d14c8b 583 int ret = 0;
ee88563a
JM
584 int igp_metric_ret = 0;
585 int peer_sort_ret = -1;
d62a17ae 586 char new_buf[PATH_ADDPATH_STR_BUFFER];
587 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
588 uint32_t new_mm_seq;
589 uint32_t exist_mm_seq;
6d8c603a 590 int nh_cmp;
d071f237
AK
591 esi_t *exist_esi;
592 esi_t *new_esi;
593 bool same_esi;
594 bool old_proxy;
595 bool new_proxy;
33c6e933 596 bool new_origin, exist_origin;
da0c0ef7 597 struct bgp_path_info *bpi_ultimate;
d62a17ae 598
599 *paths_eq = 0;
600
601 /* 0. Null check. */
602 if (new == NULL) {
fdf81fa0 603 *reason = bgp_path_selection_none;
d62a17ae 604 if (debug)
605 zlog_debug("%s: new is NULL", pfx_buf);
606 return 0;
607 }
2ec1e66f 608
da0c0ef7
KM
609 if (debug) {
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 612 sizeof(new_buf));
da0c0ef7 613 }
718e3744 614
d62a17ae 615 if (exist == NULL) {
fdf81fa0 616 *reason = bgp_path_selection_first;
d62a17ae 617 if (debug)
4378495a
DS
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 620 return 1;
621 }
2ec1e66f 622
d62a17ae 623 if (debug) {
da0c0ef7
KM
624 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 626 sizeof(exist_buf));
4378495a
DS
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf, bgp->name_pretty, new_buf, new->flags,
629 exist_buf, exist->flags);
d62a17ae 630 }
8ff56318 631
d62a17ae 632 newattr = new->attr;
633 existattr = exist->attr;
634
1479ed2f
DA
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
639 *
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
643 */
9a706b42
DA
644 if (bgp_attr_get_community(newattr) &&
645 community_include(bgp_attr_get_community(newattr),
646 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
647 if (debug)
648 zlog_debug(
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf, new_buf, exist_buf);
651 return 0;
652 }
653
9a706b42
DA
654 if (bgp_attr_get_community(existattr) &&
655 community_include(bgp_attr_get_community(existattr),
656 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
657 if (debug)
658 zlog_debug(
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf, new_buf, exist_buf);
661 return 1;
662 }
663
5df26422
NS
664 new_p = bgp_dest_get_prefix(new->net);
665
d62a17ae 666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
668 */
5df26422
NS
669 if ((safi == SAFI_EVPN)
670 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 671 /* This is an error condition described in RFC 7432 Section
672 * 15.2. The RFC
673 * states that in this scenario "the PE MUST alert the operator"
674 * but it
675 * does not state what other action to take. In order to provide
676 * some
677 * consistency in this scenario we are going to prefer the path
678 * with the
679 * sticky flag.
680 */
681 if (newattr->sticky != existattr->sticky) {
682 if (!debug) {
5df26422
NS
683 prefix2str(new_p, pfx_buf,
684 sizeof(*pfx_buf)
685 * PREFIX2STR_BUFFER);
18ee8310 686 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
687 new, new_buf, sizeof(new_buf));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist, exist_buf, sizeof(exist_buf));
d62a17ae 690 }
691
692 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 693 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
694 if (debug)
695 zlog_debug(
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf, new_buf, exist_buf);
d62a17ae 698 return 1;
699 }
700
701 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 702 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
703 if (debug)
704 zlog_debug(
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf, new_buf, exist_buf);
d62a17ae 707 return 0;
708 }
709 }
128ea8ab 710
d071f237
AK
711 new_esi = bgp_evpn_attr_get_esi(newattr);
712 exist_esi = bgp_evpn_attr_get_esi(existattr);
713 if (bgp_evpn_is_esi_valid(new_esi) &&
714 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
715 same_esi = true;
716 } else {
717 same_esi = false;
718 }
719
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
726 */
727 if (same_esi) {
728 char esi_buf[ESI_STR_LEN];
729
730 if (bgp_evpn_is_path_local(bgp, new)) {
731 *reason = bgp_path_selection_evpn_local_path;
732 if (debug)
733 zlog_debug(
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf, new_buf, exist_buf,
736 esi_to_str(new_esi, esi_buf,
737 sizeof(esi_buf)));
738 return 1;
739 }
740 if (bgp_evpn_is_path_local(bgp, exist)) {
741 *reason = bgp_path_selection_evpn_local_path;
742 if (debug)
743 zlog_debug(
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf, new_buf, exist_buf,
746 esi_to_str(new_esi, esi_buf,
747 sizeof(esi_buf)));
748 return 0;
749 }
750 }
751
d62a17ae 752 new_mm_seq = mac_mobility_seqnum(newattr);
753 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 754
d62a17ae 755 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 756 *reason = bgp_path_selection_evpn_seq;
d62a17ae 757 if (debug)
758 zlog_debug(
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf, new_buf, exist_buf, new_mm_seq,
761 exist_mm_seq);
762 return 1;
763 }
8ff56318 764
d62a17ae 765 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 766 *reason = bgp_path_selection_evpn_seq;
d62a17ae 767 if (debug)
768 zlog_debug(
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf, new_buf, exist_buf, new_mm_seq,
771 exist_mm_seq);
772 return 0;
773 }
6d8c603a 774
d071f237
AK
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
777 */
778 new_proxy = bgp_evpn_attr_is_proxy(newattr);
779 old_proxy = bgp_evpn_attr_is_proxy(existattr);
780 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
781 old_proxy != new_proxy) {
782 if (!new_proxy) {
783 *reason = bgp_path_selection_evpn_non_proxy;
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf, new_buf, exist_buf);
788 return 1;
789 }
790
791 *reason = bgp_path_selection_evpn_non_proxy;
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf, new_buf, exist_buf);
796 return 0;
797 }
798
6d8c603a
AK
799 /*
800 * if sequence numbers are the same path with the lowest IP
801 * wins
802 */
803 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
804 if (nh_cmp < 0) {
fdf81fa0 805 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
806 if (debug)
807 zlog_debug(
23d0a753 808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 809 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 810 &new->attr->nexthop);
6d8c603a
AK
811 return 1;
812 }
813 if (nh_cmp > 0) {
fdf81fa0 814 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
815 if (debug)
816 zlog_debug(
23d0a753 817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 818 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 819 &new->attr->nexthop);
6d8c603a
AK
820 return 0;
821 }
d62a17ae 822 }
9fbdd100 823
d62a17ae 824 /* 1. Weight check. */
d62a17ae 825 new_weight = newattr->weight;
826 exist_weight = existattr->weight;
8ff56318 827
d62a17ae 828 if (new_weight > exist_weight) {
fdf81fa0 829 *reason = bgp_path_selection_weight;
d62a17ae 830 if (debug)
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf, new_buf, exist_buf, new_weight,
833 exist_weight);
834 return 1;
835 }
718e3744 836
d62a17ae 837 if (new_weight < exist_weight) {
fdf81fa0 838 *reason = bgp_path_selection_weight;
d62a17ae 839 if (debug)
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf, new_buf, exist_buf, new_weight,
842 exist_weight);
843 return 0;
844 }
9fbdd100 845
d62a17ae 846 /* 2. Local preference check. */
847 new_pref = exist_pref = bgp->default_local_pref;
848
849 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 new_pref = newattr->local_pref;
851 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
852 exist_pref = existattr->local_pref;
853
854 if (new_pref > exist_pref) {
fdf81fa0 855 *reason = bgp_path_selection_local_pref;
d62a17ae 856 if (debug)
857 zlog_debug(
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf, new_buf, exist_buf, new_pref,
860 exist_pref);
861 return 1;
862 }
718e3744 863
d62a17ae 864 if (new_pref < exist_pref) {
fdf81fa0 865 *reason = bgp_path_selection_local_pref;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf, new_buf, exist_buf, new_pref,
870 exist_pref);
871 return 0;
872 }
9fbdd100 873
d62a17ae 874 /* 3. Local route check. We prefer:
875 * - BGP_ROUTE_STATIC
876 * - BGP_ROUTE_AGGREGATE
877 * - BGP_ROUTE_REDISTRIBUTE
878 */
33c6e933
DS
879 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
880 new->sub_type == BGP_ROUTE_IMPORTED);
881 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
882 exist->sub_type == BGP_ROUTE_IMPORTED);
883
884 if (new_origin && !exist_origin) {
fdf81fa0 885 *reason = bgp_path_selection_local_route;
d62a17ae 886 if (debug)
887 zlog_debug(
888 "%s: %s wins over %s due to preferred BGP_ROUTE type",
889 pfx_buf, new_buf, exist_buf);
890 return 1;
891 }
718e3744 892
33c6e933 893 if (!new_origin && exist_origin) {
fdf81fa0 894 *reason = bgp_path_selection_local_route;
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s loses to %s due to preferred BGP_ROUTE type",
898 pfx_buf, new_buf, exist_buf);
899 return 0;
6811845b 900 }
718e3744 901
da0c0ef7
KM
902 /* Here if these are imported routes then get ultimate pi for
903 * path compare.
904 */
905 new = bgp_get_imported_bpi_ultimate(new);
906 exist = bgp_get_imported_bpi_ultimate(exist);
907 newattr = new->attr;
908 existattr = exist->attr;
909
d62a17ae 910 /* 4. AS path length check. */
892fedb6 911 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 912 int exist_hops = aspath_count_hops(existattr->aspath);
913 int exist_confeds = aspath_count_confeds(existattr->aspath);
914
892fedb6 915 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 916 int aspath_hops;
917
918 aspath_hops = aspath_count_hops(newattr->aspath);
919 aspath_hops += aspath_count_confeds(newattr->aspath);
920
921 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 922 *reason = bgp_path_selection_confed_as_path;
d62a17ae 923 if (debug)
924 zlog_debug(
925 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
926 pfx_buf, new_buf, exist_buf,
927 aspath_hops,
928 (exist_hops + exist_confeds));
929 return 1;
930 }
931
932 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 933 *reason = bgp_path_selection_confed_as_path;
d62a17ae 934 if (debug)
935 zlog_debug(
936 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
937 pfx_buf, new_buf, exist_buf,
938 aspath_hops,
939 (exist_hops + exist_confeds));
940 return 0;
941 }
942 } else {
943 int newhops = aspath_count_hops(newattr->aspath);
944
945 if (newhops < exist_hops) {
fdf81fa0 946 *reason = bgp_path_selection_as_path;
d62a17ae 947 if (debug)
948 zlog_debug(
949 "%s: %s wins over %s due to aspath hopcount %d < %d",
950 pfx_buf, new_buf, exist_buf,
951 newhops, exist_hops);
952 return 1;
953 }
954
955 if (newhops > exist_hops) {
fdf81fa0 956 *reason = bgp_path_selection_as_path;
d62a17ae 957 if (debug)
958 zlog_debug(
959 "%s: %s loses to %s due to aspath hopcount %d > %d",
960 pfx_buf, new_buf, exist_buf,
961 newhops, exist_hops);
962 return 0;
963 }
964 }
965 }
9fbdd100 966
d62a17ae 967 /* 5. Origin check. */
968 if (newattr->origin < existattr->origin) {
fdf81fa0 969 *reason = bgp_path_selection_origin;
d62a17ae 970 if (debug)
971 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
972 pfx_buf, new_buf, exist_buf,
973 bgp_origin_long_str[newattr->origin],
974 bgp_origin_long_str[existattr->origin]);
975 return 1;
976 }
718e3744 977
d62a17ae 978 if (newattr->origin > existattr->origin) {
fdf81fa0 979 *reason = bgp_path_selection_origin;
d62a17ae 980 if (debug)
981 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
982 pfx_buf, new_buf, exist_buf,
983 bgp_origin_long_str[newattr->origin],
984 bgp_origin_long_str[existattr->origin]);
985 return 0;
986 }
718e3744 987
d62a17ae 988 /* 6. MED check. */
989 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
990 && aspath_count_hops(existattr->aspath) == 0);
991 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
992 && aspath_count_confeds(existattr->aspath) > 0
993 && aspath_count_hops(newattr->aspath) == 0
994 && aspath_count_hops(existattr->aspath) == 0);
995
892fedb6
DA
996 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
997 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 998 || aspath_cmp_left(newattr->aspath, existattr->aspath)
999 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1000 || internal_as_route) {
1001 new_med = bgp_med_value(new->attr, bgp);
1002 exist_med = bgp_med_value(exist->attr, bgp);
1003
1004 if (new_med < exist_med) {
fdf81fa0 1005 *reason = bgp_path_selection_med;
d62a17ae 1006 if (debug)
1007 zlog_debug(
1008 "%s: %s wins over %s due to MED %d < %d",
1009 pfx_buf, new_buf, exist_buf, new_med,
1010 exist_med);
1011 return 1;
1012 }
8ff56318 1013
d62a17ae 1014 if (new_med > exist_med) {
fdf81fa0 1015 *reason = bgp_path_selection_med;
d62a17ae 1016 if (debug)
1017 zlog_debug(
1018 "%s: %s loses to %s due to MED %d > %d",
1019 pfx_buf, new_buf, exist_buf, new_med,
1020 exist_med);
1021 return 0;
1022 }
1023 }
9fbdd100 1024
d62a17ae 1025 /* 7. Peer type check. */
1026 new_sort = new->peer->sort;
1027 exist_sort = exist->peer->sort;
1028
1029 if (new_sort == BGP_PEER_EBGP
1030 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1031 *reason = bgp_path_selection_peer;
d62a17ae 1032 if (debug)
1033 zlog_debug(
1034 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1035 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1036 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1037 return 1;
1038 peer_sort_ret = 1;
d62a17ae 1039 }
718e3744 1040
d62a17ae 1041 if (exist_sort == BGP_PEER_EBGP
1042 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1043 *reason = bgp_path_selection_peer;
d62a17ae 1044 if (debug)
1045 zlog_debug(
1046 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1047 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1048 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1049 return 0;
1050 peer_sort_ret = 0;
d62a17ae 1051 }
8ff56318 1052
d62a17ae 1053 /* 8. IGP metric check. */
1054 newm = existm = 0;
8ff56318 1055
d62a17ae 1056 if (new->extra)
1057 newm = new->extra->igpmetric;
1058 if (exist->extra)
1059 existm = exist->extra->igpmetric;
9fbdd100 1060
d62a17ae 1061 if (newm < existm) {
ee88563a 1062 if (debug && peer_sort_ret < 0)
d62a17ae 1063 zlog_debug(
d588b995 1064 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1065 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1066 igp_metric_ret = 1;
d62a17ae 1067 }
718e3744 1068
d62a17ae 1069 if (newm > existm) {
ee88563a 1070 if (debug && peer_sort_ret < 0)
d62a17ae 1071 zlog_debug(
d588b995 1072 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1073 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1074 igp_metric_ret = 0;
5e242b0d 1075 }
5e242b0d 1076
d62a17ae 1077 /* 9. Same IGP metric. Compare the cluster list length as
1078 representative of IGP hops metric. Rewrite the metric value
1079 pair (newm, existm) with the cluster list length. Prefer the
1080 path with smaller cluster list length. */
1081 if (newm == existm) {
aa53c036
DS
1082 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1083 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1084 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1085 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1086 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1087
1088 if (newm < existm) {
ee88563a 1089 if (debug && peer_sort_ret < 0)
d62a17ae 1090 zlog_debug(
d588b995 1091 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1092 pfx_buf, new_buf, exist_buf,
1093 newm, existm);
ee88563a 1094 igp_metric_ret = 1;
d62a17ae 1095 }
1096
1097 if (newm > existm) {
ee88563a 1098 if (debug && peer_sort_ret < 0)
d62a17ae 1099 zlog_debug(
d588b995 1100 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1101 pfx_buf, new_buf, exist_buf,
1102 newm, existm);
ee88563a 1103 igp_metric_ret = 0;
d62a17ae 1104 }
1105 }
1106 }
31a4638f 1107
d62a17ae 1108 /* 10. confed-external vs. confed-internal */
1109 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1110 if (new_sort == BGP_PEER_CONFED
1111 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1112 *reason = bgp_path_selection_confed;
d62a17ae 1113 if (debug)
1114 zlog_debug(
1115 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1116 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1117 if (!CHECK_FLAG(bgp->flags,
1118 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1119 return 1;
1120 peer_sort_ret = 1;
d62a17ae 1121 }
718e3744 1122
d62a17ae 1123 if (exist_sort == BGP_PEER_CONFED
1124 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1125 *reason = bgp_path_selection_confed;
d62a17ae 1126 if (debug)
1127 zlog_debug(
1128 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1129 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1130 if (!CHECK_FLAG(bgp->flags,
1131 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1132 return 0;
1133 peer_sort_ret = 0;
d62a17ae 1134 }
1135 }
718e3744 1136
d62a17ae 1137 /* 11. Maximum path check. */
1138 if (newm == existm) {
1139 /* If one path has a label but the other does not, do not treat
1140 * them as equals for multipath
1141 */
a4d82a8a 1142 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1143 != (exist->extra
b57ba6d2 1144 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1145 if (debug)
1146 zlog_debug(
1147 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1148 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1149 } else if (CHECK_FLAG(bgp->flags,
1150 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1151
1152 /*
1153 * For the two paths, all comparison steps till IGP
1154 * metric
1155 * have succeeded - including AS_PATH hop count. Since
1156 * 'bgp
1157 * bestpath as-path multipath-relax' knob is on, we
1158 * don't need
1159 * an exact match of AS_PATH. Thus, mark the paths are
1160 * equal.
1161 * That will trigger both these paths to get into the
1162 * multipath
1163 * array.
1164 */
1165 *paths_eq = 1;
1166
1167 if (debug)
1168 zlog_debug(
1169 "%s: %s and %s are equal via multipath-relax",
1170 pfx_buf, new_buf, exist_buf);
1171 } else if (new->peer->sort == BGP_PEER_IBGP) {
1172 if (aspath_cmp(new->attr->aspath,
1173 exist->attr->aspath)) {
1174 *paths_eq = 1;
1175
1176 if (debug)
1177 zlog_debug(
1178 "%s: %s and %s are equal via matching aspaths",
1179 pfx_buf, new_buf, exist_buf);
1180 }
1181 } else if (new->peer->as == exist->peer->as) {
1182 *paths_eq = 1;
1183
1184 if (debug)
1185 zlog_debug(
1186 "%s: %s and %s are equal via same remote-as",
1187 pfx_buf, new_buf, exist_buf);
1188 }
1189 } else {
1190 /*
1191 * TODO: If unequal cost ibgp multipath is enabled we can
1192 * mark the paths as equal here instead of returning
1193 */
ee88563a
JM
1194
1195 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1196 * if either step 7 or 10 (peer type checks) yielded a winner,
1197 * that result was returned immediately. Returning from step 10
1198 * ignored the return value computed in steps 8 and 9 (IGP
1199 * metric checks). In order to preserve that behavior, if
1200 * peer_sort_ret is set, return that rather than igp_metric_ret.
1201 */
1202 ret = peer_sort_ret;
1203 if (peer_sort_ret < 0) {
1204 ret = igp_metric_ret;
1205 if (debug) {
1206 if (ret == 1)
1207 zlog_debug(
1208 "%s: %s wins over %s after IGP metric comparison",
1209 pfx_buf, new_buf, exist_buf);
1210 else
1211 zlog_debug(
1212 "%s: %s loses to %s after IGP metric comparison",
1213 pfx_buf, new_buf, exist_buf);
1214 }
1215 *reason = bgp_path_selection_igp_metric;
d62a17ae 1216 }
1217 return ret;
1218 }
718e3744 1219
ee88563a
JM
1220 /*
1221 * At this point, the decision whether to set *paths_eq = 1 has been
1222 * completed. If we deferred returning because of bestpath peer-type
1223 * relax configuration, return now.
1224 */
1225 if (peer_sort_ret >= 0)
1226 return peer_sort_ret;
1227
d62a17ae 1228 /* 12. If both paths are external, prefer the path that was received
1229 first (the oldest one). This step minimizes route-flap, since a
1230 newer path won't displace an older one, even if it was the
1231 preferred route based on the additional decision criteria below. */
892fedb6 1232 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1233 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1234 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1235 *reason = bgp_path_selection_older;
d62a17ae 1236 if (debug)
1237 zlog_debug(
1238 "%s: %s wins over %s due to oldest external",
1239 pfx_buf, new_buf, exist_buf);
1240 return 1;
1241 }
9fbdd100 1242
1defdda8 1243 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1244 *reason = bgp_path_selection_older;
d62a17ae 1245 if (debug)
1246 zlog_debug(
1247 "%s: %s loses to %s due to oldest external",
1248 pfx_buf, new_buf, exist_buf);
1249 return 0;
1250 }
1251 }
718e3744 1252
ce5002c6 1253 /* 13. Router-ID comparison. */
d62a17ae 1254 /* If one of the paths is "stale", the corresponding peer router-id will
1255 * be 0 and would always win over the other path. If originator id is
ce5002c6 1256 * used for the comparison, it will decide which path is better.
d62a17ae 1257 */
1258 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1259 new_id.s_addr = newattr->originator_id.s_addr;
1260 else
1261 new_id.s_addr = new->peer->remote_id.s_addr;
1262 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1263 exist_id.s_addr = existattr->originator_id.s_addr;
1264 else
1265 exist_id.s_addr = exist->peer->remote_id.s_addr;
1266
1267 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1268 *reason = bgp_path_selection_router_id;
d62a17ae 1269 if (debug)
1270 zlog_debug(
1271 "%s: %s wins over %s due to Router-ID comparison",
1272 pfx_buf, new_buf, exist_buf);
1273 return 1;
1274 }
718e3744 1275
d62a17ae 1276 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1277 *reason = bgp_path_selection_router_id;
d62a17ae 1278 if (debug)
1279 zlog_debug(
1280 "%s: %s loses to %s due to Router-ID comparison",
1281 pfx_buf, new_buf, exist_buf);
1282 return 0;
1283 }
9fbdd100 1284
ce5002c6 1285 /* 14. Cluster length comparison. */
d62a17ae 1286 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1287 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1288
1289 if (new_cluster < exist_cluster) {
fdf81fa0 1290 *reason = bgp_path_selection_cluster_length;
d62a17ae 1291 if (debug)
1292 zlog_debug(
1293 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1294 pfx_buf, new_buf, exist_buf, new_cluster,
1295 exist_cluster);
1296 return 1;
1297 }
718e3744 1298
d62a17ae 1299 if (new_cluster > exist_cluster) {
fdf81fa0 1300 *reason = bgp_path_selection_cluster_length;
d62a17ae 1301 if (debug)
1302 zlog_debug(
1303 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1304 pfx_buf, new_buf, exist_buf, new_cluster,
1305 exist_cluster);
1306 return 0;
1307 }
9fbdd100 1308
ce5002c6 1309 /* 15. Neighbor address comparison. */
d62a17ae 1310 /* Do this only if neither path is "stale" as stale paths do not have
1311 * valid peer information (as the connection may or may not be up).
1312 */
1defdda8 1313 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1314 *reason = bgp_path_selection_stale;
d62a17ae 1315 if (debug)
1316 zlog_debug(
1317 "%s: %s wins over %s due to latter path being STALE",
1318 pfx_buf, new_buf, exist_buf);
1319 return 1;
1320 }
0de5153c 1321
1defdda8 1322 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1323 *reason = bgp_path_selection_stale;
d62a17ae 1324 if (debug)
1325 zlog_debug(
1326 "%s: %s loses to %s due to former path being STALE",
1327 pfx_buf, new_buf, exist_buf);
1328 return 0;
1329 }
718e3744 1330
d62a17ae 1331 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1332 if (new->peer->su_remote == NULL) {
1333 *reason = bgp_path_selection_local_configured;
d62a17ae 1334 return 0;
fdf81fa0
DS
1335 }
1336 if (exist->peer->su_remote == NULL) {
1337 *reason = bgp_path_selection_local_configured;
d62a17ae 1338 return 1;
fdf81fa0 1339 }
9fbdd100 1340
d62a17ae 1341 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1342
1343 if (ret == 1) {
fdf81fa0 1344 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1345 if (debug)
1346 zlog_debug(
1347 "%s: %s loses to %s due to Neighor IP comparison",
1348 pfx_buf, new_buf, exist_buf);
1349 return 0;
1350 }
1351
1352 if (ret == -1) {
fdf81fa0 1353 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1354 if (debug)
1355 zlog_debug(
1356 "%s: %s wins over %s due to Neighor IP comparison",
1357 pfx_buf, new_buf, exist_buf);
1358 return 1;
1359 }
9fbdd100 1360
fdf81fa0 1361 *reason = bgp_path_selection_default;
d62a17ae 1362 if (debug)
1363 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1364 pfx_buf, new_buf, exist_buf);
718e3744 1365
d62a17ae 1366 return 1;
718e3744 1367}
1368
d071f237
AK
1369
1370int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1371 struct bgp_path_info *exist, int *paths_eq)
1372{
1373 enum bgp_path_selection_reason reason;
1374 char pfx_buf[PREFIX2STR_BUFFER];
1375
1376 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1377 AFI_L2VPN, SAFI_EVPN, &reason);
1378}
1379
65efcfce
LB
1380/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1381 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1382 * multipath is enabled
65efcfce 1383 * This version is compatible with */
18ee8310
DS
1384int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1385 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1386 afi_t afi, safi_t safi,
1387 enum bgp_path_selection_reason *reason)
d62a17ae 1388{
1389 int paths_eq;
1390 int ret;
18ee8310 1391 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1392 afi, safi, reason);
d62a17ae 1393
1394 if (paths_eq)
1395 ret = 0;
1396 else {
1397 if (ret == 1)
1398 ret = -1;
1399 else
1400 ret = 1;
1401 }
1402 return ret;
65efcfce
LB
1403}
1404
5a1ae2c2
DS
1405static enum filter_type bgp_input_filter(struct peer *peer,
1406 const struct prefix *p,
d62a17ae 1407 struct attr *attr, afi_t afi,
1408 safi_t safi)
718e3744 1409{
d62a17ae 1410 struct bgp_filter *filter;
6401252f 1411 enum filter_type ret = FILTER_PERMIT;
718e3744 1412
d62a17ae 1413 filter = &peer->filter[afi][safi];
718e3744 1414
d62a17ae 1415#define FILTER_EXIST_WARN(F, f, filter) \
1416 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1417 zlog_debug("%s: Could not find configured input %s-list %s!", \
1418 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1419
1420 if (DISTRIBUTE_IN_NAME(filter)) {
1421 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1422
6401252f
QY
1423 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1424 == FILTER_DENY) {
1425 ret = FILTER_DENY;
1426 goto done;
1427 }
d62a17ae 1428 }
1429
1430 if (PREFIX_LIST_IN_NAME(filter)) {
1431 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1432
6401252f
QY
1433 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1434 == PREFIX_DENY) {
1435 ret = FILTER_DENY;
1436 goto done;
1437 }
d62a17ae 1438 }
1439
1440 if (FILTER_LIST_IN_NAME(filter)) {
1441 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1442
1443 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1444 == AS_FILTER_DENY) {
1445 ret = FILTER_DENY;
1446 goto done;
1447 }
d62a17ae 1448 }
1449
6401252f 1450done:
c7bb4f00 1451 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1452 char pfxprint[PREFIX2STR_BUFFER];
1453
1454 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1455 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1456 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1457 }
1458
1459 return ret;
650f76c2 1460#undef FILTER_EXIST_WARN
718e3744 1461}
1462
b8685f9b
DS
1463static enum filter_type bgp_output_filter(struct peer *peer,
1464 const struct prefix *p,
d62a17ae 1465 struct attr *attr, afi_t afi,
1466 safi_t safi)
718e3744 1467{
d62a17ae 1468 struct bgp_filter *filter;
6401252f 1469 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1470
1471 filter = &peer->filter[afi][safi];
1472
1473#define FILTER_EXIST_WARN(F, f, filter) \
1474 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1475 zlog_debug("%s: Could not find configured output %s-list %s!", \
1476 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1477
d62a17ae 1478 if (DISTRIBUTE_OUT_NAME(filter)) {
1479 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1480
6401252f
QY
1481 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1482 == FILTER_DENY) {
1483 ret = FILTER_DENY;
1484 goto done;
1485 }
d62a17ae 1486 }
1487
1488 if (PREFIX_LIST_OUT_NAME(filter)) {
1489 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1490
d62a17ae 1491 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1492 == PREFIX_DENY) {
1493 ret = FILTER_DENY;
1494 goto done;
1495 }
d62a17ae 1496 }
718e3744 1497
d62a17ae 1498 if (FILTER_LIST_OUT_NAME(filter)) {
1499 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1500
d62a17ae 1501 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1502 == AS_FILTER_DENY) {
1503 ret = FILTER_DENY;
1504 goto done;
1505 }
1506 }
1507
c7bb4f00 1508 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1509 char pfxprint[PREFIX2STR_BUFFER];
1510
1511 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1512 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1513 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1514 }
718e3744 1515
6401252f
QY
1516done:
1517 return ret;
650f76c2 1518#undef FILTER_EXIST_WARN
718e3744 1519}
1520
1521/* If community attribute includes no_export then return 1. */
3dc339cd 1522static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1523{
9a706b42 1524 if (bgp_attr_get_community(attr)) {
d62a17ae 1525 /* NO_ADVERTISE check. */
9a706b42
DA
1526 if (community_include(bgp_attr_get_community(attr),
1527 COMMUNITY_NO_ADVERTISE))
3dc339cd 1528 return true;
d62a17ae 1529
1530 /* NO_EXPORT check. */
9a706b42
DA
1531 if (peer->sort == BGP_PEER_EBGP &&
1532 community_include(bgp_attr_get_community(attr),
1533 COMMUNITY_NO_EXPORT))
3dc339cd 1534 return true;
d62a17ae 1535
1536 /* NO_EXPORT_SUBCONFED check. */
1537 if (peer->sort == BGP_PEER_EBGP
1538 || peer->sort == BGP_PEER_CONFED)
9a706b42 1539 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1540 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1541 return true;
d62a17ae 1542 }
3dc339cd 1543 return false;
718e3744 1544}
1545
1546/* Route reflection loop check. */
3dc339cd 1547static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1548{
d62a17ae 1549 struct in_addr cluster_id;
779fee93 1550 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1551
779fee93 1552 if (cluster) {
d62a17ae 1553 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1554 cluster_id = peer->bgp->cluster_id;
1555 else
1556 cluster_id = peer->bgp->router_id;
1557
779fee93 1558 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1559 return true;
d62a17ae 1560 }
3dc339cd 1561 return false;
718e3744 1562}
6b0655a2 1563
d864dd9e
EB
1564static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1565{
1566 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1567 if (peer->local_role == ROLE_PROVIDER ||
1568 peer->local_role == ROLE_RS_SERVER)
1569 return true;
1570 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1571 return true;
1572 return false;
1573 }
1574 if (peer->local_role == ROLE_CUSTOMER ||
1575 peer->local_role == ROLE_PEER ||
1576 peer->local_role == ROLE_RS_CLIENT) {
1577 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1578 attr->otc = peer->as;
1579 }
1580 return false;
1581}
1582
1583static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1584{
1585 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1586 if (peer->local_role == ROLE_CUSTOMER ||
1587 peer->local_role == ROLE_RS_CLIENT ||
1588 peer->local_role == ROLE_PEER)
1589 return true;
1590 return false;
1591 }
1592 if (peer->local_role == ROLE_PROVIDER ||
1593 peer->local_role == ROLE_PEER ||
1594 peer->local_role == ROLE_RS_SERVER) {
1595 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1596 attr->otc = peer->bgp->as;
1597 }
1598 return false;
1599}
1600
5a78f2bc
EB
1601static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1602{
1603 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1604}
1605
5a1ae2c2 1606static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1607 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1608 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1609 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1610{
d62a17ae 1611 struct bgp_filter *filter;
82b692c0
LK
1612 struct bgp_path_info rmap_path = { 0 };
1613 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1614 route_map_result_t ret;
1615 struct route_map *rmap = NULL;
718e3744 1616
d62a17ae 1617 filter = &peer->filter[afi][safi];
718e3744 1618
d62a17ae 1619 /* Apply default weight value. */
1620 if (peer->weight[afi][safi])
1621 attr->weight = peer->weight[afi][safi];
718e3744 1622
d62a17ae 1623 if (rmap_name) {
1624 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1625
d62a17ae 1626 if (rmap == NULL)
1627 return RMAP_DENY;
1628 } else {
1629 if (ROUTE_MAP_IN_NAME(filter)) {
1630 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1631
d62a17ae 1632 if (rmap == NULL)
1633 return RMAP_DENY;
1634 }
1635 }
0b16f239 1636
d62a17ae 1637 /* Route map apply. */
1638 if (rmap) {
6006b807 1639 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1640 /* Duplicate current value to new structure for modification. */
40381db7
DS
1641 rmap_path.peer = peer;
1642 rmap_path.attr = attr;
82b692c0 1643 rmap_path.extra = &extra;
9bcb3eef 1644 rmap_path.net = dest;
196c6b09 1645
82b692c0
LK
1646 extra.num_labels = num_labels;
1647 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1648 memcpy(extra.label, label,
1649 num_labels * sizeof(mpls_label_t));
718e3744 1650
d62a17ae 1651 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1652
d62a17ae 1653 /* Apply BGP route map to the attribute. */
1782514f 1654 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1655
d62a17ae 1656 peer->rmap_type = 0;
0b16f239 1657
1f2263be 1658 if (ret == RMAP_DENYMATCH)
d62a17ae 1659 return RMAP_DENY;
0b16f239 1660 }
d62a17ae 1661 return RMAP_PERMIT;
0b16f239
DS
1662}
1663
5f040085 1664static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1665 struct attr *attr, afi_t afi, safi_t safi,
1666 const char *rmap_name)
0b16f239 1667{
40381db7 1668 struct bgp_path_info rmap_path;
d62a17ae 1669 route_map_result_t ret;
1670 struct route_map *rmap = NULL;
d7c0a89a 1671 uint8_t rmap_type;
0b16f239 1672
b787157a
DS
1673 /*
1674 * So if we get to this point and have no rmap_name
1675 * we want to just show the output as it currently
1676 * exists.
1677 */
1678 if (!rmap_name)
1679 return RMAP_PERMIT;
0b16f239 1680
d62a17ae 1681 /* Apply default weight value. */
1682 if (peer->weight[afi][safi])
1683 attr->weight = peer->weight[afi][safi];
0b16f239 1684
b787157a 1685 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1686
b787157a
DS
1687 /*
1688 * If we have a route map name and we do not find
1689 * the routemap that means we have an implicit
1690 * deny.
1691 */
1692 if (rmap == NULL)
1693 return RMAP_DENY;
0b16f239 1694
6006b807 1695 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1696 /* Route map apply. */
544be979 1697 /* Duplicate current value to new structure for modification. */
40381db7
DS
1698 rmap_path.peer = peer;
1699 rmap_path.attr = attr;
0b16f239 1700
0f672529 1701 rmap_type = peer->rmap_type;
b787157a 1702 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1703
b787157a 1704 /* Apply BGP route map to the attribute. */
1782514f 1705 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1706
0f672529 1707 peer->rmap_type = rmap_type;
b787157a
DS
1708
1709 if (ret == RMAP_DENYMATCH)
1710 /*
1711 * caller has multiple error paths with bgp_attr_flush()
1712 */
1713 return RMAP_DENY;
ac41b2a2 1714
d62a17ae 1715 return RMAP_PERMIT;
718e3744 1716}
6b0655a2 1717
5000f21c 1718/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1719static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1720 struct peer *peer, struct attr *attr)
1721{
1722 if (peer->sort == BGP_PEER_EBGP
1723 && (peer_af_flag_check(peer, afi, safi,
1724 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1725 || peer_af_flag_check(peer, afi, safi,
1726 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1727 || peer_af_flag_check(peer, afi, safi,
1728 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1729 || peer_af_flag_check(peer, afi, safi,
1730 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1731 // Take action on the entire aspath
1732 if (peer_af_flag_check(peer, afi, safi,
1733 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1734 || peer_af_flag_check(peer, afi, safi,
1735 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1736 if (peer_af_flag_check(
1737 peer, afi, safi,
1738 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1739 attr->aspath = aspath_replace_private_asns(
bf26b80e 1740 attr->aspath, bgp->as, peer->as);
d62a17ae 1741
179d5a0e
TA
1742 /*
1743 * Even if the aspath consists of just private ASNs we
1744 * need to walk the AS-Path to maintain all instances
1745 * of the peer's ASN to break possible loops.
1746 */
d62a17ae 1747 else
1748 attr->aspath = aspath_remove_private_asns(
bf26b80e 1749 attr->aspath, peer->as);
d62a17ae 1750 }
1751
1752 // 'all' was not specified so the entire aspath must be private
1753 // ASNs
1754 // for us to do anything
1755 else if (aspath_private_as_check(attr->aspath)) {
1756 if (peer_af_flag_check(
1757 peer, afi, safi,
1758 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1759 attr->aspath = aspath_replace_private_asns(
bf26b80e 1760 attr->aspath, bgp->as, peer->as);
d62a17ae 1761 else
179d5a0e
TA
1762 /*
1763 * Walk the aspath to retain any instances of
1764 * the peer_asn
1765 */
1766 attr->aspath = aspath_remove_private_asns(
1767 attr->aspath, peer->as);
d62a17ae 1768 }
1769 }
5000f21c
DS
1770}
1771
c7122e14 1772/* If this is an EBGP peer with as-override */
d62a17ae 1773static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1774 struct peer *peer, struct attr *attr)
1775{
9bbdb457
DA
1776 if (peer->sort == BGP_PEER_EBGP &&
1777 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
1778 attr->aspath = aspath_replace_specific_asn(attr->aspath,
1779 peer->as, bgp->as);
d62a17ae 1780}
1781
1479ed2f
DA
1782void bgp_attr_add_llgr_community(struct attr *attr)
1783{
1784 struct community *old;
1785 struct community *new;
1786 struct community *merge;
1787 struct community *llgr;
1788
9a706b42 1789 old = bgp_attr_get_community(attr);
1479ed2f
DA
1790 llgr = community_str2com("llgr-stale");
1791
1792 assert(llgr);
1793
1794 if (old) {
1795 merge = community_merge(community_dup(old), llgr);
1796
1797 if (old->refcnt == 0)
1798 community_free(&old);
1799
1800 new = community_uniq_sort(merge);
1801 community_free(&merge);
1802 } else {
1803 new = community_dup(llgr);
1804 }
1805
1806 community_free(&llgr);
1807
9a706b42 1808 bgp_attr_set_community(attr, new);
1479ed2f
DA
1809}
1810
7f323236
DW
1811void bgp_attr_add_gshut_community(struct attr *attr)
1812{
1813 struct community *old;
1814 struct community *new;
1815 struct community *merge;
1816 struct community *gshut;
1817
9a706b42 1818 old = bgp_attr_get_community(attr);
7f323236
DW
1819 gshut = community_str2com("graceful-shutdown");
1820
990f4f91 1821 assert(gshut);
1822
7f323236
DW
1823 if (old) {
1824 merge = community_merge(community_dup(old), gshut);
1825
a4d82a8a 1826 if (old->refcnt == 0)
3c1f53de 1827 community_free(&old);
7f323236
DW
1828
1829 new = community_uniq_sort(merge);
3c1f53de 1830 community_free(&merge);
7f323236
DW
1831 } else {
1832 new = community_dup(gshut);
1833 }
1834
3c1f53de 1835 community_free(&gshut);
9a706b42 1836 bgp_attr_set_community(attr, new);
7f323236
DW
1837
1838 /* When we add the graceful-shutdown community we must also
1839 * lower the local-preference */
1840 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1841 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1842}
1843
1844
e73c112e
MK
1845/* Notify BGP Conditional advertisement scanner process. */
1846void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1847{
e73c112e 1848 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1849 afi_t afi = SUBGRP_AFI(subgrp);
1850 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1851 struct bgp_filter *filter = &peer->filter[afi][safi];
1852
1853 if (!ADVERTISE_MAP_NAME(filter))
1854 return;
1855
52979c3b
DS
1856 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1857 return;
e73c112e 1858
52979c3b 1859 peer->advmap_table_change = true;
e73c112e
MK
1860}
1861
1862
f2ee6d5c 1863void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1864{
960035b2 1865 if (family == AF_INET) {
975a328e
DA
1866 attr->nexthop.s_addr = INADDR_ANY;
1867 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1868 }
d62a17ae 1869 if (family == AF_INET6)
1870 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1871 if (family == AF_EVPN)
1872 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1873}
1874
9bcb3eef 1875bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1876 struct update_subgroup *subgrp,
7f7940e6 1877 const struct prefix *p, struct attr *attr,
51c3a7de 1878 struct attr *post_attr)
d62a17ae 1879{
1880 struct bgp_filter *filter;
1881 struct peer *from;
1882 struct peer *peer;
1883 struct peer *onlypeer;
1884 struct bgp *bgp;
40381db7 1885 struct attr *piattr;
b68885f9 1886 route_map_result_t ret;
d62a17ae 1887 int transparent;
1888 int reflect;
1889 afi_t afi;
1890 safi_t safi;
1891 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1892 bool nh_reset = false;
1893 uint64_t cum_bw;
d62a17ae 1894
1895 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1896 return false;
d62a17ae 1897
1898 afi = SUBGRP_AFI(subgrp);
1899 safi = SUBGRP_SAFI(subgrp);
1900 peer = SUBGRP_PEER(subgrp);
1901 onlypeer = NULL;
1902 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1903 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1904
40381db7 1905 from = pi->peer;
d62a17ae 1906 filter = &peer->filter[afi][safi];
1907 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1908 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1909 : pi->attr;
3f9c7369 1910
d0bf49ec
LS
1911 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1912 peer->pmax_out[afi][safi] != 0 &&
1913 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1914 if (BGP_DEBUG(update, UPDATE_OUT) ||
1915 BGP_DEBUG(update, UPDATE_PREFIX)) {
1916 zlog_debug("%s reached maximum prefix to be send (%u)",
1917 peer->host, peer->pmax_out[afi][safi]);
1918 }
1919 return false;
1920 }
1921
49e5a4a0 1922#ifdef ENABLE_BGP_VNC
d62a17ae 1923 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1924 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1925 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1926
1927 /*
1928 * direct and direct_ext type routes originate internally even
1929 * though they can have peer pointers that reference other
1930 * systems
1931 */
8228a9a7
DS
1932 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1933 __func__, p);
d62a17ae 1934 samepeer_safe = 1;
1935 }
65efcfce
LB
1936#endif
1937
ddb5b488
PZ
1938 if (((afi == AFI_IP) || (afi == AFI_IP6))
1939 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1940 && (pi->type == ZEBRA_ROUTE_BGP)
1941 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1942
1943 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1944
1945 samepeer_safe = 1;
1946 }
1947
d62a17ae 1948 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1949 * pi is valid */
1950 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1951 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1952 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1953 return false;
d62a17ae 1954 }
adbac85e 1955
d62a17ae 1956 /* If this is not the bestpath then check to see if there is an enabled
1957 * addpath
1958 * feature that requires us to advertise it */
40381db7 1959 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1960 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1961 return false;
d62a17ae 1962 }
1963 }
06370dac 1964
d62a17ae 1965 /* Aggregate-address suppress check. */
4056a5f6
RZ
1966 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1967 return false;
3f9c7369 1968
13b7e7f0
DS
1969 /*
1970 * If we are doing VRF 2 VRF leaking via the import
1971 * statement, we want to prevent the route going
1972 * off box as that the RT and RD created are localy
1973 * significant and globaly useless.
1974 */
40381db7
DS
1975 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1976 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1977 return false;
13b7e7f0 1978
d62a17ae 1979 /* If it's labeled safi, make sure the route has a valid label. */
1980 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1981 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1982 if (!bgp_is_valid_label(&label)) {
1983 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1984 zlog_debug("u%" PRIu64 ":s%" PRIu64
1985 " %pFX is filtered - no label (%p)",
d62a17ae 1986 subgrp->update_group->id, subgrp->id,
8228a9a7 1987 p, &label);
3dc339cd 1988 return false;
d62a17ae 1989 }
1990 }
cd1964ff 1991
d62a17ae 1992 /* Do not send back route to sender. */
1993 if (onlypeer && from == onlypeer) {
3dc339cd 1994 return false;
d62a17ae 1995 }
3f9c7369 1996
d62a17ae 1997 /* Do not send the default route in the BGP table if the neighbor is
1998 * configured for default-originate */
1999 if (CHECK_FLAG(peer->af_flags[afi][safi],
2000 PEER_FLAG_DEFAULT_ORIGINATE)) {
2001 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2002 return false;
d62a17ae 2003 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2004 return false;
d62a17ae 2005 }
4125bb67 2006
d62a17ae 2007 /* Transparency check. */
2008 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2009 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2010 transparent = 1;
2011 else
2012 transparent = 0;
2013
2014 /* If community is not disabled check the no-export and local. */
40381db7 2015 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2016 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2017 zlog_debug("%s: community filter check fail for %pFX",
2018 __func__, p);
3dc339cd 2019 return false;
d62a17ae 2020 }
3f9c7369 2021
d62a17ae 2022 /* If the attribute has originator-id and it is same as remote
2023 peer's id. */
40381db7
DS
2024 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2025 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2026 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2027 zlog_debug(
a9f3f4f5
DA
2028 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2029 onlypeer, p);
3dc339cd 2030 return false;
d62a17ae 2031 }
3f9c7369 2032
d62a17ae 2033 /* ORF prefix-list filter check */
2034 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2035 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2036 || CHECK_FLAG(peer->af_cap[afi][safi],
2037 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2038 if (peer->orf_plist[afi][safi]) {
2039 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2040 == PREFIX_DENY) {
2041 if (bgp_debug_update(NULL, p,
2042 subgrp->update_group, 0))
2043 zlog_debug(
a9f3f4f5
DA
2044 "%pBP [Update:SEND] %pFX is filtered via ORF",
2045 peer, p);
3dc339cd 2046 return false;
d62a17ae 2047 }
2048 }
2049
2050 /* Output filter check. */
40381db7 2051 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2052 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2053 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2054 p);
3dc339cd 2055 return false;
d62a17ae 2056 }
3f9c7369 2057
d62a17ae 2058 /* AS path loop check. */
2b31007c
RZ
2059 if (onlypeer && onlypeer->as_path_loop_detection
2060 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2061 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2062 zlog_debug(
a9f3f4f5
DA
2063 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2064 onlypeer, onlypeer->as);
3dc339cd 2065 return false;
d62a17ae 2066 }
3f9c7369 2067
d62a17ae 2068 /* If we're a CONFED we need to loop check the CONFED ID too */
2069 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2070 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2071 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2072 zlog_debug(
a9f3f4f5
DA
2073 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2074 peer, bgp->confed_id);
3dc339cd 2075 return false;
d62a17ae 2076 }
3f9c7369 2077 }
3f9c7369 2078
d62a17ae 2079 /* Route-Reflect check. */
2080 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2081 reflect = 1;
2082 else
2083 reflect = 0;
2084
2085 /* IBGP reflection check. */
2086 if (reflect && !samepeer_safe) {
2087 /* A route from a Client peer. */
2088 if (CHECK_FLAG(from->af_flags[afi][safi],
2089 PEER_FLAG_REFLECTOR_CLIENT)) {
2090 /* Reflect to all the Non-Client peers and also to the
2091 Client peers other than the originator. Originator
2092 check
2093 is already done. So there is noting to do. */
2094 /* no bgp client-to-client reflection check. */
892fedb6
DA
2095 if (CHECK_FLAG(bgp->flags,
2096 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2097 if (CHECK_FLAG(peer->af_flags[afi][safi],
2098 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2099 return false;
d62a17ae 2100 } else {
2101 /* A route from a Non-client peer. Reflect to all other
2102 clients. */
2103 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2104 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2105 return false;
d62a17ae 2106 }
2107 }
3f9c7369 2108
51c3a7de
DA
2109 /* For modify attribute, copy it to temporary structure.
2110 * post_attr comes from BGP conditional advertisements, where
2111 * attributes are already processed by advertise-map route-map,
2112 * and this needs to be saved instead of overwriting from the
2113 * path attributes.
2114 */
2115 if (post_attr)
2116 *attr = *post_attr;
2117 else
2118 *attr = *piattr;
d62a17ae 2119
2120 /* If local-preference is not set. */
2121 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2122 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2123 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2124 attr->local_pref = bgp->default_local_pref;
3f9c7369 2125 }
3f9c7369 2126
d62a17ae 2127 /* If originator-id is not set and the route is to be reflected,
2128 set the originator id */
2129 if (reflect
2130 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2131 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2132 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2133 }
3f9c7369 2134
d62a17ae 2135 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2136 */
2137 if (peer->sort == BGP_PEER_EBGP
2138 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2139 if (from != bgp->peer_self && !transparent
2140 && !CHECK_FLAG(peer->af_flags[afi][safi],
2141 PEER_FLAG_MED_UNCHANGED))
2142 attr->flag &=
2143 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2144 }
3f9c7369 2145
d62a17ae 2146 /* Since the nexthop attribute can vary per peer, it is not explicitly
2147 * set
2148 * in announce check, only certain flags and length (or number of
2149 * nexthops
2150 * -- for IPv6/MP_REACH) are set here in order to guide the update
2151 * formation
2152 * code in setting the nexthop(s) on a per peer basis in
2153 * reformat_peer().
2154 * Typically, the source nexthop in the attribute is preserved but in
2155 * the
2156 * scenarios where we know it will always be overwritten, we reset the
2157 * nexthop to "0" in an attempt to achieve better Update packing. An
2158 * example of this is when a prefix from each of 2 IBGP peers needs to
2159 * be
2160 * announced to an EBGP peer (and they have the same attributes barring
2161 * their nexthop).
2162 */
2163 if (reflect)
2164 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2165
2166#define NEXTHOP_IS_V6 \
2167 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2168 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2169 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2170 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2171
2172 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2173 * if
2174 * the peer (group) is configured to receive link-local nexthop
2175 * unchanged
c728d027
DA
2176 * and it is available in the prefix OR we're not reflecting the route,
2177 * link-local nexthop address is valid and
d62a17ae 2178 * the peer (group) to whom we're going to announce is on a shared
2179 * network
2180 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2181 * By checking if nexthop LL address is valid we are sure that
2182 * we do not announce LL address as `::`.
d62a17ae 2183 */
2184 if (NEXTHOP_IS_V6) {
2185 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2186 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2187 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2188 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2189 || (!reflect && !transparent
c728d027
DA
2190 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2191 && peer->shared_network
d62a17ae 2192 && (from == bgp->peer_self
2193 || peer->sort == BGP_PEER_EBGP))) {
2194 attr->mp_nexthop_len =
2195 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2196 }
3f9c7369 2197
d62a17ae 2198 /* Clear off link-local nexthop in source, whenever it is not
2199 * needed to
2200 * ensure more prefixes share the same attribute for
2201 * announcement.
2202 */
2203 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2204 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2205 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2206 }
3f9c7369 2207
5a78f2bc
EB
2208 if (bgp_check_role_applicability(afi, safi) &&
2209 bgp_otc_egress(peer, attr))
d864dd9e
EB
2210 return false;
2211
d62a17ae 2212 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2213 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2214
0655090c
QY
2215 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2216 filter->advmap.aname &&
2217 route_map_lookup_by_name(filter->advmap.aname)) {
2218 struct bgp_path_info rmap_path = {0};
2219 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2220 struct attr dummy_attr = *attr;
2221
2222 /* Fill temp path_info */
2223 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2224 pi, peer, &dummy_attr);
2225
2226 struct route_map *amap =
2227 route_map_lookup_by_name(filter->advmap.aname);
2228
2229 ret = route_map_apply(amap, p, &rmap_path);
2230
2231 bgp_attr_flush(&dummy_attr);
2232
2233 /*
2234 * The conditional advertisement mode is Withdraw and this
2235 * prefix is a conditional prefix. Don't advertise it
2236 */
2237 if (ret == RMAP_PERMITMATCH)
2238 return false;
2239 }
2240
d62a17ae 2241 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2242 if (!post_attr &&
2243 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2244 struct bgp_path_info rmap_path = {0};
2245 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2246 struct attr dummy_attr = {0};
d62a17ae 2247
e34291b8 2248 /* Fill temp path_info */
9bcb3eef
DS
2249 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2250 pi, peer, attr);
16f7ce2b 2251
d62a17ae 2252 /* don't confuse inbound and outbound setting */
2253 RESET_FLAG(attr->rmap_change_flags);
2254
2255 /*
2256 * The route reflector is not allowed to modify the attributes
2257 * of the reflected IBGP routes unless explicitly allowed.
2258 */
2259 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2260 && !CHECK_FLAG(bgp->flags,
2261 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2262 dummy_attr = *attr;
40381db7 2263 rmap_path.attr = &dummy_attr;
d62a17ae 2264 }
3f9c7369 2265
d62a17ae 2266 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2267
4056a5f6 2268 if (bgp_path_suppressed(pi))
d62a17ae 2269 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2270 &rmap_path);
d62a17ae 2271 else
2272 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2273 &rmap_path);
d62a17ae 2274
7e7639f5 2275 bgp_attr_flush(&dummy_attr);
d62a17ae 2276 peer->rmap_type = 0;
2277
2278 if (ret == RMAP_DENYMATCH) {
778048bf 2279 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2280 zlog_debug(
a9f3f4f5
DA
2281 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2282 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2283 bgp_attr_flush(rmap_path.attr);
3dc339cd 2284 return false;
d62a17ae 2285 }
3f9c7369 2286 }
3f9c7369 2287
9dac9fc8
DA
2288 /* RFC 8212 to prevent route leaks.
2289 * This specification intends to improve this situation by requiring the
2290 * explicit configuration of both BGP Import and Export Policies for any
2291 * External BGP (EBGP) session such as customers, peers, or
2292 * confederation boundaries for all enabled address families. Through
2293 * codification of the aforementioned requirement, operators will
2294 * benefit from consistent behavior across different BGP
2295 * implementations.
2296 */
1d3fdccf 2297 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2298 if (!bgp_outbound_policy_exists(peer, filter)) {
2299 if (monotime_since(&bgp->ebgprequirespolicywarning,
2300 NULL) > FIFTEENMINUTE2USEC ||
2301 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2302 zlog_warn(
2303 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2304 monotime(&bgp->ebgprequirespolicywarning);
2305 }
3dc339cd 2306 return false;
b17826b7 2307 }
9dac9fc8 2308
fb29348a
DA
2309 /* draft-ietf-idr-deprecate-as-set-confed-set
2310 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2311 * Eventually, This document (if approved) updates RFC 4271
2312 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2313 * and obsoletes RFC 6472.
2314 */
7f972cd8 2315 if (peer->bgp->reject_as_sets)
fb29348a 2316 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2317 return false;
fb29348a 2318
01da2d26
DA
2319 /* If neighbor sso is configured, then check if the route has
2320 * SoO extended community and validate against the configured
2321 * one. If they match, do not announce, to prevent routing
2322 * loops.
2323 */
2324 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2325 peer->soo[afi][safi]) {
2326 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2327 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2328
2329 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2330 ECOMMUNITY_SITE_ORIGIN) ||
2331 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
2332 ECOMMUNITY_SITE_ORIGIN)) &&
2333 ecommunity_include(ecomm, ecomm_soo)) {
2334 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2335 zlog_debug(
2336 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2337 peer, p, ecommunity_str(ecomm_soo));
2338 return false;
2339 }
2340 }
2341
33d022bc
DA
2342 /* Codification of AS 0 Processing */
2343 if (aspath_check_as_zero(attr->aspath))
e2369003 2344 return false;
33d022bc 2345
637e5ba4 2346 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2347 if (peer->sort == BGP_PEER_IBGP
2348 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2349 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2350 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2351 } else {
2352 bgp_attr_add_gshut_community(attr);
2353 }
2354 }
2355
1479ed2f
DA
2356 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2357 * Capability" to a neighbor MUST perform the following upon receiving
2358 * a route from that neighbor with the "LLGR_STALE" community, or upon
2359 * attaching the "LLGR_STALE" community itself per Section 4.2:
2360 *
2361 * The route SHOULD NOT be advertised to any neighbor from which the
2362 * Long-lived Graceful Restart Capability has not been received.
2363 */
9a706b42
DA
2364 if (bgp_attr_get_community(attr) &&
2365 community_include(bgp_attr_get_community(attr),
2366 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2367 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2368 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2369 return false;
2370
d62a17ae 2371 /* After route-map has been applied, we check to see if the nexthop to
2372 * be carried in the attribute (that is used for the announcement) can
2373 * be cleared off or not. We do this in all cases where we would be
2374 * setting the nexthop to "ourselves". For IPv6, we only need to
2375 * consider
2376 * the global nexthop here; the link-local nexthop would have been
2377 * cleared
2378 * already, and if not, it is required by the update formation code.
2379 * Also see earlier comments in this function.
2380 */
2381 /*
2382 * If route-map has performed some operation on the nexthop or the peer
2383 * configuration says to pass it unchanged, we cannot reset the nexthop
2384 * here, so only attempt to do it if these aren't true. Note that the
2385 * route-map handler itself might have cleared the nexthop, if for
2386 * example,
2387 * it is configured as 'peer-address'.
2388 */
2389 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2390 piattr->rmap_change_flags)
d62a17ae 2391 && !transparent
2392 && !CHECK_FLAG(peer->af_flags[afi][safi],
2393 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2394 /* We can reset the nexthop, if setting (or forcing) it to
2395 * 'self' */
2396 if (CHECK_FLAG(peer->af_flags[afi][safi],
2397 PEER_FLAG_NEXTHOP_SELF)
2398 || CHECK_FLAG(peer->af_flags[afi][safi],
2399 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2400 if (!reflect
2401 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2402 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2403 subgroup_announce_reset_nhop(
2404 (peer_cap_enhe(peer, afi, safi)
2405 ? AF_INET6
2406 : p->family),
2407 attr);
7b651a32 2408 nh_reset = true;
2409 }
d62a17ae 2410 } else if (peer->sort == BGP_PEER_EBGP) {
2411 /* Can also reset the nexthop if announcing to EBGP, but
2412 * only if
2413 * no peer in the subgroup is on a shared subnet.
2414 * Note: 3rd party nexthop currently implemented for
2415 * IPv4 only.
2416 */
737af885
BS
2417 if ((p->family == AF_INET) &&
2418 (!bgp_subgrp_multiaccess_check_v4(
2419 piattr->nexthop,
7b651a32 2420 subgrp, from))) {
d62a17ae 2421 subgroup_announce_reset_nhop(
2422 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2423 ? AF_INET6
2424 : p->family),
737af885 2425 attr);
7b651a32 2426 nh_reset = true;
2427 }
737af885
BS
2428
2429 if ((p->family == AF_INET6) &&
2430 (!bgp_subgrp_multiaccess_check_v6(
2431 piattr->mp_nexthop_global,
7b651a32 2432 subgrp, from))) {
737af885
BS
2433 subgroup_announce_reset_nhop(
2434 (peer_cap_enhe(peer, afi, safi)
2435 ? AF_INET6
2436 : p->family),
2437 attr);
7b651a32 2438 nh_reset = true;
2439 }
737af885
BS
2440
2441
2442
40381db7 2443 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2444 /*
2445 * This flag is used for leaked vpn-vrf routes
2446 */
2447 int family = p->family;
2448
2449 if (peer_cap_enhe(peer, afi, safi))
2450 family = AF_INET6;
2451
2452 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2453 zlog_debug(
1defdda8 2454 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2455 __func__, family2str(family));
2456 subgroup_announce_reset_nhop(family, attr);
7b651a32 2457 nh_reset = true;
d62a17ae 2458 }
63696f1d 2459 }
960035b2 2460
63696f1d 2461 /* If IPv6/MP and nexthop does not have any override and happens
2462 * to
2463 * be a link-local address, reset it so that we don't pass along
2464 * the
2465 * source's link-local IPv6 address to recipients who may not be
2466 * on
2467 * the same interface.
2468 */
2469 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2470 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2471 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2472 nh_reset = true;
2473 }
d62a17ae 2474 }
3f9c7369 2475
7b651a32 2476 /*
2477 * When the next hop is set to ourselves, if all multipaths have
2478 * link-bandwidth announce the cumulative bandwidth as that makes
2479 * the most sense. However, don't modify if the link-bandwidth has
2480 * been explicitly set by user policy.
2481 */
2482 if (nh_reset &&
f7e1c681 2483 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2484 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2485 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2486 bgp_attr_set_ecommunity(
2487 attr,
2488 ecommunity_replace_linkbw(
2489 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2490 CHECK_FLAG(
2491 peer->flags,
2492 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2493
3dc339cd 2494 return true;
3f9c7369
DS
2495}
2496
cc9f21da 2497static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2498{
2499 struct afi_safi_info *info;
2500 afi_t afi;
2501 safi_t safi;
2502 struct bgp *bgp;
2503
2504 info = THREAD_ARG(thread);
2505 afi = info->afi;
2506 safi = info->safi;
2507 bgp = info->bgp;
2508
2509 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2510 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2511 safi);
f009ff26 2512
2513 bgp->gr_info[afi][safi].t_route_select = NULL;
2514
2515 XFREE(MTYPE_TMP, info);
2516
2517 /* Best path selection */
cc9f21da 2518 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2519}
2520
9bcb3eef 2521void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2522 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2523 struct bgp_path_info_pair *result, afi_t afi,
2524 safi_t safi)
2525{
2526 struct bgp_path_info *new_select;
2527 struct bgp_path_info *old_select;
40381db7
DS
2528 struct bgp_path_info *pi;
2529 struct bgp_path_info *pi1;
2530 struct bgp_path_info *pi2;
2531 struct bgp_path_info *nextpi = NULL;
d62a17ae 2532 int paths_eq, do_mpath, debug;
2533 struct list mp_list;
2534 char pfx_buf[PREFIX2STR_BUFFER];
2535 char path_buf[PATH_ADDPATH_STR_BUFFER];
2536
2537 bgp_mp_list_init(&mp_list);
2538 do_mpath =
2539 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2540
9bcb3eef 2541 debug = bgp_debug_bestpath(dest);
d62a17ae 2542
2543 if (debug)
9bcb3eef 2544 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2545
9bcb3eef 2546 dest->reason = bgp_path_selection_none;
d62a17ae 2547 /* bgp deterministic-med */
2548 new_select = NULL;
892fedb6 2549 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2550
1defdda8 2551 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2552 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2553 pi1 = pi1->next)
9bcb3eef 2554 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2555 BGP_PATH_DMED_SELECTED);
d62a17ae 2556
9bcb3eef 2557 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2558 pi1 = pi1->next) {
40381db7 2559 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2560 continue;
40381db7 2561 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2562 continue;
ea8b2282 2563 if (pi1->peer != bgp->peer_self)
feb17238 2564 if (!peer_established(pi1->peer))
d62a17ae 2565 continue;
2566
40381db7
DS
2567 new_select = pi1;
2568 if (pi1->next) {
2569 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2570 if (CHECK_FLAG(pi2->flags,
1defdda8 2571 BGP_PATH_DMED_CHECK))
d62a17ae 2572 continue;
40381db7 2573 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2574 continue;
ea8b2282 2575 if (pi2->peer != bgp->peer_self
d62a17ae 2576 && !CHECK_FLAG(
ea8b2282
DS
2577 pi2->peer->sflags,
2578 PEER_STATUS_NSF_WAIT))
40381db7 2579 if (pi2->peer->status
d62a17ae 2580 != Established)
2581 continue;
2582
121e245d
DS
2583 if (!aspath_cmp_left(pi1->attr->aspath,
2584 pi2->attr->aspath)
2585 && !aspath_cmp_left_confed(
40381db7 2586 pi1->attr->aspath,
121e245d
DS
2587 pi2->attr->aspath))
2588 continue;
d62a17ae 2589
121e245d
DS
2590 if (bgp_path_info_cmp(
2591 bgp, pi2, new_select,
2592 &paths_eq, mpath_cfg, debug,
fdf81fa0 2593 pfx_buf, afi, safi,
9bcb3eef 2594 &dest->reason)) {
121e245d 2595 bgp_path_info_unset_flag(
9bcb3eef 2596 dest, new_select,
121e245d
DS
2597 BGP_PATH_DMED_SELECTED);
2598 new_select = pi2;
d62a17ae 2599 }
121e245d
DS
2600
2601 bgp_path_info_set_flag(
9bcb3eef 2602 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2603 }
2604 }
9bcb3eef 2605 bgp_path_info_set_flag(dest, new_select,
18ee8310 2606 BGP_PATH_DMED_CHECK);
9bcb3eef 2607 bgp_path_info_set_flag(dest, new_select,
18ee8310 2608 BGP_PATH_DMED_SELECTED);
d62a17ae 2609
2610 if (debug) {
18ee8310 2611 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2612 new_select, path_buf, sizeof(path_buf));
8228a9a7 2613 zlog_debug(
4378495a
DS
2614 "%pBD(%s): %s is the bestpath from AS %u",
2615 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2616 aspath_get_first_as(
2617 new_select->attr->aspath));
d62a17ae 2618 }
2619 }
2620 }
96450faf 2621
d62a17ae 2622 /* Check old selected route and new selected route. */
2623 old_select = NULL;
2624 new_select = NULL;
9bcb3eef 2625 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2626 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2627 enum bgp_path_selection_reason reason;
2628
40381db7
DS
2629 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2630 old_select = pi;
d62a17ae 2631
40381db7 2632 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2633 /* reap REMOVED routes, if needs be
2634 * selected route must stay for a while longer though
2635 */
40381db7
DS
2636 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2637 && (pi != old_select))
9bcb3eef 2638 bgp_path_info_reap(dest, pi);
d62a17ae 2639
ddb5b488 2640 if (debug)
40381db7
DS
2641 zlog_debug("%s: pi %p in holddown", __func__,
2642 pi);
ddb5b488 2643
d62a17ae 2644 continue;
2645 }
96450faf 2646
40381db7
DS
2647 if (pi->peer && pi->peer != bgp->peer_self
2648 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2649 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2650
2651 if (debug)
2652 zlog_debug(
40381db7
DS
2653 "%s: pi %p non self peer %s not estab state",
2654 __func__, pi, pi->peer->host);
ddb5b488 2655
d62a17ae 2656 continue;
ddb5b488 2657 }
9fbdd100 2658
892fedb6 2659 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2660 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2661 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2662 if (debug)
40381db7 2663 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2664 continue;
2665 }
9fbdd100 2666
9bcb3eef 2667 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2668
9bcb3eef 2669 reason = dest->reason;
40381db7 2670 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2671 debug, pfx_buf, afi, safi,
2672 &dest->reason)) {
19ea4cec
DS
2673 if (new_select == NULL &&
2674 reason != bgp_path_selection_none)
9bcb3eef 2675 dest->reason = reason;
40381db7 2676 new_select = pi;
d62a17ae 2677 }
2678 }
718e3744 2679
d62a17ae 2680 /* Now that we know which path is the bestpath see if any of the other
2681 * paths
2682 * qualify as multipaths
2683 */
2684 if (debug) {
2685 if (new_select)
7533cad7
QY
2686 bgp_path_info_path_with_addpath_rx_str(
2687 new_select, path_buf, sizeof(path_buf));
d62a17ae 2688 else
772270f3 2689 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2690 zlog_debug(
4378495a
DS
2691 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2692 dest, bgp->name_pretty, path_buf,
d62a17ae 2693 old_select ? old_select->peer->host : "NONE");
96450faf 2694 }
9fbdd100 2695
d62a17ae 2696 if (do_mpath && new_select) {
9bcb3eef 2697 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2698 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2699
2700 if (debug)
18ee8310 2701 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2702 pi, path_buf, sizeof(path_buf));
d62a17ae 2703
40381db7 2704 if (pi == new_select) {
d62a17ae 2705 if (debug)
2706 zlog_debug(
4378495a
DS
2707 "%pBD(%s): %s is the bestpath, add to the multipath list",
2708 dest, bgp->name_pretty,
2709 path_buf);
40381db7 2710 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2711 continue;
2712 }
2713
40381db7 2714 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2715 continue;
2716
40381db7
DS
2717 if (pi->peer && pi->peer != bgp->peer_self
2718 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2719 PEER_STATUS_NSF_WAIT))
feb17238 2720 if (!peer_established(pi->peer))
d62a17ae 2721 continue;
2722
40381db7 2723 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2724 if (debug)
2725 zlog_debug(
8228a9a7
DS
2726 "%pBD: %s has the same nexthop as the bestpath, skip it",
2727 dest, path_buf);
d62a17ae 2728 continue;
2729 }
2730
40381db7 2731 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2732 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2733 &dest->reason);
d62a17ae 2734
2735 if (paths_eq) {
2736 if (debug)
2737 zlog_debug(
8228a9a7
DS
2738 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2739 dest, path_buf);
40381db7 2740 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2741 }
2742 }
2743 }
fee0f4c6 2744
4378495a 2745 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2746 mpath_cfg);
2747 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2748 bgp_mp_list_clear(&mp_list);
96450faf 2749
9bcb3eef 2750 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2751
d62a17ae 2752 result->old = old_select;
2753 result->new = new_select;
96450faf 2754
d62a17ae 2755 return;
fee0f4c6 2756}
2757
3f9c7369
DS
2758/*
2759 * A new route/change in bestpath of an existing route. Evaluate the path
2760 * for advertisement to the subgroup.
2761 */
3dc339cd
DA
2762void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2763 struct bgp_path_info *selected,
9bcb3eef 2764 struct bgp_dest *dest,
3dc339cd 2765 uint32_t addpath_tx_id)
d62a17ae 2766{
b54892e0 2767 const struct prefix *p;
d62a17ae 2768 struct peer *onlypeer;
2769 struct attr attr;
2770 afi_t afi;
2771 safi_t safi;
a77e2f4b
S
2772 struct bgp *bgp;
2773 bool advertise;
adbac85e 2774
9bcb3eef 2775 p = bgp_dest_get_prefix(dest);
d62a17ae 2776 afi = SUBGRP_AFI(subgrp);
2777 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2778 bgp = SUBGRP_INST(subgrp);
d62a17ae 2779 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2780 : NULL);
2781
2dbe669b
DA
2782 if (BGP_DEBUG(update, UPDATE_OUT))
2783 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2784
d62a17ae 2785 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2786 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2787 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2788 return;
d62a17ae 2789
6006b807 2790 memset(&attr, 0, sizeof(attr));
d62a17ae 2791 /* It's initialized in bgp_announce_check() */
2792
a77e2f4b
S
2793 /* Announcement to the subgroup. If the route is filtered withdraw it.
2794 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2795 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2796 * route
d62a17ae 2797 */
a77e2f4b
S
2798 advertise = bgp_check_advertise(bgp, dest);
2799
d62a17ae 2800 if (selected) {
7f7940e6 2801 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2802 NULL)) {
a77e2f4b
S
2803 /* Route is selected, if the route is already installed
2804 * in FIB, then it is advertised
2805 */
be785e35
DS
2806 if (advertise) {
2807 if (!bgp_check_withdrawal(bgp, dest))
2808 bgp_adj_out_set_subgroup(
2809 dest, subgrp, &attr, selected);
2810 else
2811 bgp_adj_out_unset_subgroup(
2812 dest, subgrp, 1, addpath_tx_id);
2813 }
a77e2f4b 2814 } else
9bcb3eef 2815 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2816 addpath_tx_id);
d62a17ae 2817 }
2818
2819 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2820 else {
9bcb3eef 2821 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2822 }
200df115 2823}
fee0f4c6 2824
3064bf43 2825/*
e1072051 2826 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2827 * This is called at the end of route processing.
3064bf43 2828 */
9bcb3eef 2829void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2830{
40381db7 2831 struct bgp_path_info *pi;
3064bf43 2832
9bcb3eef 2833 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2834 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2835 continue;
40381db7
DS
2836 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2837 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2838 }
3064bf43 2839}
2840
2841/*
2842 * Has the route changed from the RIB's perspective? This is invoked only
2843 * if the route selection returns the same best route as earlier - to
2844 * determine if we need to update zebra or not.
2845 */
9bcb3eef 2846bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2847{
4b7e6066 2848 struct bgp_path_info *mpinfo;
d62a17ae 2849
2bb9eff4
DS
2850 /* If this is multipath, check all selected paths for any nexthop
2851 * change or attribute change. Some attribute changes (e.g., community)
2852 * aren't of relevance to the RIB, but we'll update zebra to ensure
2853 * we handle the case of BGP nexthop change. This is the behavior
2854 * when the best path has an attribute change anyway.
d62a17ae 2855 */
1defdda8 2856 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2857 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2858 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2859 return true;
d62a17ae 2860
2bb9eff4
DS
2861 /*
2862 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2863 */
18ee8310
DS
2864 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2865 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2866 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2867 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2868 return true;
d62a17ae 2869 }
3064bf43 2870
d62a17ae 2871 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2872 return false;
3064bf43 2873}
2874
d62a17ae 2875struct bgp_process_queue {
2876 struct bgp *bgp;
9bcb3eef 2877 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2878#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2879 unsigned int flags;
2880 unsigned int queued;
200df115 2881};
2882
3b0c17e1 2883static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2884 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2885 struct bgp_path_info *new_select,
2886 struct bgp_path_info *old_select)
2887{
9bcb3eef 2888 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2889
2890 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2891 return;
2892
2893 if (advertise_type5_routes(bgp, afi) && new_select
2894 && is_route_injectable_into_evpn(new_select)) {
2895
2896 /* apply the route-map */
2897 if (bgp->adv_cmd_rmap[afi][safi].map) {
2898 route_map_result_t ret;
2899 struct bgp_path_info rmap_path;
2900 struct bgp_path_info_extra rmap_path_extra;
2901 struct attr dummy_attr;
2902
2903 dummy_attr = *new_select->attr;
2904
2905 /* Fill temp path_info */
9bcb3eef 2906 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2907 new_select, new_select->peer,
2908 &dummy_attr);
2909
2910 RESET_FLAG(dummy_attr.rmap_change_flags);
2911
2912 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2913 p, &rmap_path);
3b0c17e1 2914
2915 if (ret == RMAP_DENYMATCH) {
2916 bgp_attr_flush(&dummy_attr);
2917 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2918 safi);
2919 } else
2920 bgp_evpn_advertise_type5_route(
2921 bgp, p, &dummy_attr, afi, safi);
2922 } else {
2923 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2924 afi, safi);
2925 }
2926 } else if (advertise_type5_routes(bgp, afi) && old_select
2927 && is_route_injectable_into_evpn(old_select))
2928 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2929}
2930
bb2ca692
MS
2931/*
2932 * Utility to determine whether a particular path_info should use
2933 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2934 * in a path where we basically _know_ this is a BGP-LU route.
2935 */
2936static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2937{
2938 /* Certain types get imp null; so do paths where the nexthop is
2939 * not labeled.
2940 */
2941 if (new_select->sub_type == BGP_ROUTE_STATIC
2942 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2943 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2944 return true;
2945 else if (new_select->extra == NULL ||
2946 !bgp_is_valid_label(&new_select->extra->label[0]))
2947 /* TODO -- should be configurable? */
2948 return true;
2949 else
2950 return false;
2951}
2952
3103e8d2
DS
2953/*
2954 * old_select = The old best path
2955 * new_select = the new best path
2956 *
2957 * if (!old_select && new_select)
2958 * We are sending new information on.
2959 *
2960 * if (old_select && new_select) {
2961 * if (new_select != old_select)
2962 * We have a new best path send a change
2963 * else
2964 * We've received a update with new attributes that needs
2965 * to be passed on.
2966 * }
2967 *
2968 * if (old_select && !new_select)
2969 * We have no eligible route that we can announce or the rn
2970 * is being removed.
2971 */
9bcb3eef 2972static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2973 afi_t afi, safi_t safi)
d62a17ae 2974{
4b7e6066
DS
2975 struct bgp_path_info *new_select;
2976 struct bgp_path_info *old_select;
2977 struct bgp_path_info_pair old_and_new;
ddb5b488 2978 int debug = 0;
d62a17ae 2979
892fedb6 2980 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2981 if (dest)
2982 debug = bgp_debug_bestpath(dest);
b54892e0 2983 if (debug)
f4c713ae 2984 zlog_debug(
56ca3b5b 2985 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2986 __func__, dest);
f4c713ae
LB
2987 return;
2988 }
d62a17ae 2989 /* Is it end of initial update? (after startup) */
9bcb3eef 2990 if (!dest) {
e36f61b5
DS
2991 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2992 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2993
2994 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2995 FOREACH_AFI_SAFI (afi, safi) {
2996 if (bgp_fibupd_safi(safi))
2997 bgp_zebra_announce_table(bgp, afi, safi);
2998 }
d62a17ae 2999 bgp->main_peers_update_hold = 0;
3000
3001 bgp_start_routeadv(bgp);
aac24838 3002 return;
d62a17ae 3003 }
cb1faec9 3004
9bcb3eef 3005 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3006
9bcb3eef 3007 debug = bgp_debug_bestpath(dest);
b54892e0 3008 if (debug)
4378495a
DS
3009 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3010 dest, bgp->name_pretty, afi2str(afi),
3011 safi2str(safi));
ddb5b488 3012
f009ff26 3013 /* The best path calculation for the route is deferred if
3014 * BGP_NODE_SELECT_DEFER is set
3015 */
9bcb3eef 3016 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3017 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3018 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3019 return;
3020 }
3021
d62a17ae 3022 /* Best path selection. */
9bcb3eef 3023 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3024 afi, safi);
3025 old_select = old_and_new.old;
3026 new_select = old_and_new.new;
3027
3028 /* Do we need to allocate or free labels?
3029 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3030 * necessary to do this upon changes to best path. Exceptions:
3031 * - label index has changed -> recalculate resulting label
3032 * - path_info sub_type changed -> switch to/from implicit-null
3033 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3034 */
318cac96 3035 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3036 if (new_select) {
3037 if (!old_select
3038 || bgp_label_index_differs(new_select, old_select)
57592a53 3039 || new_select->sub_type != old_select->sub_type
9bcb3eef 3040 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3041 /* Enforced penultimate hop popping:
3042 * implicit-null for local routes, aggregate
3043 * and redistributed routes
3044 */
bb2ca692 3045 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3046 if (CHECK_FLAG(
9bcb3eef 3047 dest->flags,
992dd67e
PR
3048 BGP_NODE_REGISTERED_FOR_LABEL)
3049 || CHECK_FLAG(
3050 dest->flags,
3051 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3052 bgp_unregister_for_label(dest);
67f67ba4
DA
3053 dest->local_label = mpls_lse_encode(
3054 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3055 1);
9bcb3eef 3056 bgp_set_valid_label(&dest->local_label);
d62a17ae 3057 } else
9bcb3eef
DS
3058 bgp_register_for_label(dest,
3059 new_select);
d62a17ae 3060 }
9bcb3eef 3061 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3062 BGP_NODE_REGISTERED_FOR_LABEL)
3063 || CHECK_FLAG(dest->flags,
3064 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3065 bgp_unregister_for_label(dest);
318cac96 3066 }
992dd67e
PR
3067 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3068 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3069 bgp_unregister_for_label(dest);
d62a17ae 3070 }
cd1964ff 3071
b54892e0 3072 if (debug)
ddb5b488 3073 zlog_debug(
4378495a
DS
3074 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3075 __func__, dest, bgp->name_pretty, afi2str(afi),
3076 safi2str(safi), old_select, new_select);
ddb5b488 3077
d62a17ae 3078 /* If best route remains the same and this is not due to user-initiated
3079 * clear, see exactly what needs to be done.
3080 */
d62a17ae 3081 if (old_select && old_select == new_select
9bcb3eef 3082 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3083 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3084 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3085 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3086#ifdef ENABLE_BGP_VNC
d62a17ae 3087 vnc_import_bgp_add_route(bgp, p, old_select);
3088 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3089#endif
bb744275 3090 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3091 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3092
be785e35
DS
3093 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3094 && new_select->sub_type == BGP_ROUTE_NORMAL)
3095 SET_FLAG(dest->flags,
3096 BGP_NODE_FIB_INSTALL_PENDING);
3097
ddb5b488
PZ
3098 if (new_select->type == ZEBRA_ROUTE_BGP
3099 && (new_select->sub_type == BGP_ROUTE_NORMAL
3100 || new_select->sub_type
3101 == BGP_ROUTE_IMPORTED))
3102
9bcb3eef 3103 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3104 bgp, afi, safi);
3105 }
d62a17ae 3106 }
d62a17ae 3107
3108 /* If there is a change of interest to peers, reannounce the
3109 * route. */
1defdda8 3110 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3111 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3112 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3113 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3114
3115 /* unicast routes must also be annouced to
3116 * labeled-unicast update-groups */
3117 if (safi == SAFI_UNICAST)
3118 group_announce_route(bgp, afi,
9bcb3eef 3119 SAFI_LABELED_UNICAST, dest,
d62a17ae 3120 new_select);
3121
1defdda8 3122 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3123 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3124 }
fee0f4c6 3125
3b0c17e1 3126 /* advertise/withdraw type-5 routes */
3127 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3128 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3129 bgp_process_evpn_route_injection(
9bcb3eef 3130 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3131
b1875e65 3132 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3133 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3134 bgp_zebra_clear_route_change_flags(dest);
3135 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3136 return;
d62a17ae 3137 }
8ad7271d 3138
d62a17ae 3139 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3140 */
9bcb3eef 3141 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3142
3143 /* bestpath has changed; bump version */
3144 if (old_select || new_select) {
9bcb3eef 3145 bgp_bump_version(dest);
d62a17ae 3146
3147 if (!bgp->t_rmap_def_originate_eval) {
3148 bgp_lock(bgp);
3149 thread_add_timer(
3150 bm->master,
3151 update_group_refresh_default_originate_route_map,
3152 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3153 &bgp->t_rmap_def_originate_eval);
3154 }
3155 }
3f9c7369 3156
d62a17ae 3157 if (old_select)
9bcb3eef 3158 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3159 if (new_select) {
ddb5b488
PZ
3160 if (debug)
3161 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3162 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3163 bgp_path_info_unset_flag(dest, new_select,
3164 BGP_PATH_ATTR_CHANGED);
1defdda8 3165 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3166 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3167 }
338b3424 3168
49e5a4a0 3169#ifdef ENABLE_BGP_VNC
d62a17ae 3170 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3171 if (old_select != new_select) {
3172 if (old_select) {
3173 vnc_import_bgp_exterior_del_route(bgp, p,
3174 old_select);
3175 vnc_import_bgp_del_route(bgp, p, old_select);
3176 }
3177 if (new_select) {
3178 vnc_import_bgp_exterior_add_route(bgp, p,
3179 new_select);
3180 vnc_import_bgp_add_route(bgp, p, new_select);
3181 }
3182 }
3183 }
65efcfce
LB
3184#endif
3185
9bcb3eef 3186 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3187
3188 /* unicast routes must also be annouced to labeled-unicast update-groups
3189 */
3190 if (safi == SAFI_UNICAST)
9bcb3eef 3191 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3192 new_select);
3193
3194 /* FIB update. */
3195 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3196 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3197
d62a17ae 3198 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3199 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3200 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3201 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3202
be785e35
DS
3203 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3204 SET_FLAG(dest->flags,
3205 BGP_NODE_FIB_INSTALL_PENDING);
3206
2b659f33
MK
3207 /* if this is an evpn imported type-5 prefix,
3208 * we need to withdraw the route first to clear
3209 * the nh neigh and the RMAC entry.
3210 */
3211 if (old_select &&
3212 is_route_parent_evpn(old_select))
3213 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3214
9bcb3eef 3215 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3216 } else {
d62a17ae 3217 /* Withdraw the route from the kernel. */
3218 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3219 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3220 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3221 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3222
568e10ca 3223 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3224 }
718e3744 3225 }
3064bf43 3226
9bcb3eef 3227 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3228 old_select);
5424b7ba 3229
d62a17ae 3230 /* Clear any route change flags. */
9bcb3eef 3231 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3232
18ee8310 3233 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3234 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3235 bgp_path_info_reap(dest, old_select);
d62a17ae 3236
9bcb3eef 3237 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3238 return;
718e3744 3239}
3240
f009ff26 3241/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3242void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3243{
9bcb3eef 3244 struct bgp_dest *dest;
f009ff26 3245 int cnt = 0;
3246 struct afi_safi_info *thread_info;
f009ff26 3247
56c226e7
DS
3248 if (bgp->gr_info[afi][safi].t_route_select) {
3249 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3250
3251 thread_info = THREAD_ARG(t);
3252 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3253 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3254 }
f009ff26 3255
3256 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3257 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3258 get_afi_safi_str(afi, safi, false),
26742171 3259 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3260 }
3261
3262 /* Process the route list */
6338d242 3263 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3264 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3265 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3266 dest = bgp_route_next(dest)) {
3267 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3268 continue;
3269
3270 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3271 bgp->gr_info[afi][safi].gr_deferred--;
3272 bgp_process_main_one(bgp, dest, afi, safi);
3273 cnt++;
067ea165
CB
3274 }
3275 /* If iteration stopped before the entire table was traversed then the
3276 * node needs to be unlocked.
3277 */
3278 if (dest) {
3279 bgp_dest_unlock_node(dest);
3280 dest = NULL;
f009ff26 3281 }
3282
9e3b51a7 3283 /* Send EOR message when all routes are processed */
6338d242 3284 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3285 bgp_send_delayed_eor(bgp);
8c48b3b6 3286 /* Send route processing complete message to RIB */
3287 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3288 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3289 return;
9e3b51a7 3290 }
f009ff26 3291
3292 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3293
3294 thread_info->afi = afi;
3295 thread_info->safi = safi;
3296 thread_info->bgp = bgp;
3297
3298 /* If there are more routes to be processed, start the
3299 * selection timer
3300 */
3301 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3302 BGP_ROUTE_SELECT_DELAY,
3303 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3304}
3305
aac24838 3306static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3307{
aac24838
JB
3308 struct bgp_process_queue *pqnode = data;
3309 struct bgp *bgp = pqnode->bgp;
d62a17ae 3310 struct bgp_table *table;
9bcb3eef 3311 struct bgp_dest *dest;
aac24838
JB
3312
3313 /* eoiu marker */
3314 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3315 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3316 /* should always have dedicated wq call */
3317 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3318 return WQ_SUCCESS;
3319 }
3320
ac021f40 3321 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3322 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3323 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3324 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3325 table = bgp_dest_table(dest);
3326 /* note, new DESTs may be added as part of processing */
3327 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3328
9bcb3eef 3329 bgp_dest_unlock_node(dest);
d62a17ae 3330 bgp_table_unlock(table);
3331 }
aac24838
JB
3332
3333 return WQ_SUCCESS;
3334}
3335
3336static void bgp_processq_del(struct work_queue *wq, void *data)
3337{
3338 struct bgp_process_queue *pqnode = data;
3339
3340 bgp_unlock(pqnode->bgp);
3341
3342 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3343}
3344
b6c386bb 3345void bgp_process_queue_init(struct bgp *bgp)
200df115 3346{
b6c386bb
DS
3347 if (!bgp->process_queue) {
3348 char name[BUFSIZ];
3349
3350 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3351 bgp->process_queue = work_queue_new(bm->master, name);
3352 }
3353
3354 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3355 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3356 bgp->process_queue->spec.max_retries = 0;
3357 bgp->process_queue->spec.hold = 50;
d62a17ae 3358 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3359 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3360}
3361
cfe8d15a 3362static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3363{
3364 struct bgp_process_queue *pqnode;
3365
a4d82a8a
PZ
3366 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3367 sizeof(struct bgp_process_queue));
aac24838
JB
3368
3369 /* unlocked in bgp_processq_del */
3370 pqnode->bgp = bgp_lock(bgp);
3371 STAILQ_INIT(&pqnode->pqueue);
3372
aac24838
JB
3373 return pqnode;
3374}
3375
9bcb3eef 3376void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3377{
aac24838 3378#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3379 struct work_queue *wq = bgp->process_queue;
d62a17ae 3380 struct bgp_process_queue *pqnode;
cfe8d15a 3381 int pqnode_reuse = 0;
495f0b13 3382
d62a17ae 3383 /* already scheduled for processing? */
9bcb3eef 3384 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3385 return;
2e02b9b2 3386
f009ff26 3387 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3388 * the workqueue
3389 */
9bcb3eef 3390 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3391 if (BGP_DEBUG(update, UPDATE_OUT))
3392 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3393 dest);
f009ff26 3394 return;
3395 }
3396
46aeabed
LS
3397 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3398 if (BGP_DEBUG(update, UPDATE_OUT))
3399 zlog_debug(
3400 "Soft reconfigure table in progress for route %p",
3401 dest);
3402 return;
3403 }
3404
aac24838 3405 if (wq == NULL)
d62a17ae 3406 return;
3407
aac24838 3408 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3409 limit only if is from the same BGP view and it's not an EOIU marker
3410 */
aac24838
JB
3411 if (work_queue_item_count(wq)) {
3412 struct work_queue_item *item = work_queue_last_item(wq);
3413 pqnode = item->data;
228da428 3414
a4d82a8a
PZ
3415 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3416 || pqnode->bgp != bgp
3417 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3418 pqnode = bgp_processq_alloc(bgp);
3419 else
3420 pqnode_reuse = 1;
aac24838 3421 } else
cfe8d15a 3422 pqnode = bgp_processq_alloc(bgp);
aac24838 3423 /* all unlocked in bgp_process_wq */
9bcb3eef 3424 bgp_table_lock(bgp_dest_table(dest));
aac24838 3425
9bcb3eef
DS
3426 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3427 bgp_dest_lock_node(dest);
aac24838 3428
60466a63 3429 /* can't be enqueued twice */
9bcb3eef
DS
3430 assert(STAILQ_NEXT(dest, pq) == NULL);
3431 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3432 pqnode->queued++;
3433
cfe8d15a
LB
3434 if (!pqnode_reuse)
3435 work_queue_add(wq, pqnode);
3436
d62a17ae 3437 return;
fee0f4c6 3438}
0a486e5f 3439
d62a17ae 3440void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3441{
d62a17ae 3442 struct bgp_process_queue *pqnode;
cb1faec9 3443
b6c386bb 3444 if (bgp->process_queue == NULL)
d62a17ae 3445 return;
2e02b9b2 3446
cfe8d15a 3447 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3448
aac24838 3449 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3450 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3451}
3452
cc9f21da 3453static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3454{
d62a17ae 3455 struct peer *peer;
0a486e5f 3456
d62a17ae 3457 peer = THREAD_ARG(thread);
3458 peer->t_pmax_restart = NULL;
0a486e5f 3459
d62a17ae 3460 if (bgp_debug_neighbor_events(peer))
3461 zlog_debug(
3462 "%s Maximum-prefix restart timer expired, restore peering",
3463 peer->host);
0a486e5f 3464
a9bafa95 3465 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3466 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3467}
3468
9cbd06e0
DA
3469static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3470 safi_t safi)
3471{
3472 uint32_t count = 0;
f41b0459 3473 bool filtered = false;
9cbd06e0
DA
3474 struct bgp_dest *dest;
3475 struct bgp_adj_in *ain;
40bb2ccf 3476 struct attr attr = {};
9cbd06e0
DA
3477 struct bgp_table *table = peer->bgp->rib[afi][safi];
3478
3479 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3480 for (ain = dest->adj_in; ain; ain = ain->next) {
3481 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3482
3483 attr = *ain->attr;
9cbd06e0
DA
3484
3485 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3486 == FILTER_DENY)
f41b0459
DA
3487 filtered = true;
3488
3489 if (bgp_input_modifier(
3490 peer, rn_p, &attr, afi, safi,
3491 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3492 NULL, 0, NULL)
3493 == RMAP_DENY)
3494 filtered = true;
3495
3496 if (filtered)
9cbd06e0 3497 count++;
f41b0459 3498
d498917e 3499 bgp_attr_flush(&attr);
9cbd06e0
DA
3500 }
3501 }
3502
3503 return count;
3504}
3505
3dc339cd
DA
3506bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3507 int always)
718e3744 3508{
d62a17ae 3509 iana_afi_t pkt_afi;
5c525538 3510 iana_safi_t pkt_safi;
9cbd06e0
DA
3511 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3512 PEER_FLAG_MAX_PREFIX_FORCE))
3513 ? bgp_filtered_routes_count(peer, afi, safi)
3514 + peer->pcount[afi][safi]
3515 : peer->pcount[afi][safi];
9cabb64b 3516
d62a17ae 3517 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3518 return false;
e0701b79 3519
9cbd06e0 3520 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3521 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3522 PEER_STATUS_PREFIX_LIMIT)
3523 && !always)
3dc339cd 3524 return false;
e0701b79 3525
d62a17ae 3526 zlog_info(
f70c91dc
DA
3527 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3528 get_afi_safi_str(afi, safi, false), peer, pcount,
3529 peer->pmax[afi][safi]);
d62a17ae 3530 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3531
3532 if (CHECK_FLAG(peer->af_flags[afi][safi],
3533 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3534 return false;
d62a17ae 3535
3536 /* Convert AFI, SAFI to values for packet. */
3537 pkt_afi = afi_int2iana(afi);
3538 pkt_safi = safi_int2iana(safi);
3539 {
d7c0a89a 3540 uint8_t ndata[7];
d62a17ae 3541
3542 ndata[0] = (pkt_afi >> 8);
3543 ndata[1] = pkt_afi;
3544 ndata[2] = pkt_safi;
3545 ndata[3] = (peer->pmax[afi][safi] >> 24);
3546 ndata[4] = (peer->pmax[afi][safi] >> 16);
3547 ndata[5] = (peer->pmax[afi][safi] >> 8);
3548 ndata[6] = (peer->pmax[afi][safi]);
3549
3550 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3551 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3552 BGP_NOTIFY_CEASE_MAX_PREFIX,
3553 ndata, 7);
3554 }
3555
3556 /* Dynamic peers will just close their connection. */
3557 if (peer_dynamic_neighbor(peer))
3dc339cd 3558 return true;
d62a17ae 3559
3560 /* restart timer start */
3561 if (peer->pmax_restart[afi][safi]) {
3562 peer->v_pmax_restart =
3563 peer->pmax_restart[afi][safi] * 60;
3564
3565 if (bgp_debug_neighbor_events(peer))
3566 zlog_debug(
f70c91dc
DA
3567 "%pBP Maximum-prefix restart timer started for %d secs",
3568 peer, peer->v_pmax_restart);
d62a17ae 3569
3570 BGP_TIMER_ON(peer->t_pmax_restart,
3571 bgp_maximum_prefix_restart_timer,
3572 peer->v_pmax_restart);
3573 }
3574
3dc339cd 3575 return true;
d62a17ae 3576 } else
3577 UNSET_FLAG(peer->af_sflags[afi][safi],
3578 PEER_STATUS_PREFIX_LIMIT);
3579
b1823b69
DS
3580 if (pcount
3581 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3582 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3583 PEER_STATUS_PREFIX_THRESHOLD)
3584 && !always)
3dc339cd 3585 return false;
d62a17ae 3586
3587 zlog_info(
f70c91dc
DA
3588 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3589 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3590 peer->pmax[afi][safi]);
d62a17ae 3591 SET_FLAG(peer->af_sflags[afi][safi],
3592 PEER_STATUS_PREFIX_THRESHOLD);
3593 } else
3594 UNSET_FLAG(peer->af_sflags[afi][safi],
3595 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3596 return false;
718e3744 3597}
3598
b40d939b 3599/* Unconditionally remove the route from the RIB, without taking
3600 * damping into consideration (eg, because the session went down)
3601 */
9bcb3eef 3602void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3603 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3604{
f009ff26 3605
3606 struct bgp *bgp = NULL;
3607 bool delete_route = false;
3608
9bcb3eef
DS
3609 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3610 safi);
d62a17ae 3611
f009ff26 3612 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3613 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3614
f009ff26 3615 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3616 * flag
3617 */
3618 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3619 delete_route = true;
9bcb3eef 3620 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3621 delete_route = true;
f009ff26 3622 if (delete_route) {
9bcb3eef
DS
3623 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3624 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3625 bgp = pi->peer->bgp;
26742171 3626 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3627 }
3628 }
3629 }
4a11bf2c 3630
9bcb3eef
DS
3631 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3632 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3633}
3634
9bcb3eef 3635static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3636 struct peer *peer, afi_t afi, safi_t safi,
3637 struct prefix_rd *prd)
3638{
9bcb3eef 3639 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3640
d62a17ae 3641 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3642 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3643 */
b4f7f45b
IR
3644 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3645 && peer->sort == BGP_PEER_EBGP)
3646 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3647 == BGP_DAMP_SUPPRESSED) {
3648 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3649 safi);
3650 return;
d62a17ae 3651 }
3652
49e5a4a0 3653#ifdef ENABLE_BGP_VNC
d62a17ae 3654 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3655 struct bgp_dest *pdest = NULL;
d62a17ae 3656 struct bgp_table *table = NULL;
3657
9bcb3eef
DS
3658 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3659 (struct prefix *)prd);
3660 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3661 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3662
3663 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3664 peer->bgp, prd, table, p, pi);
d62a17ae 3665 }
9bcb3eef 3666 bgp_dest_unlock_node(pdest);
d62a17ae 3667 }
3668 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3669 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3670
b54892e0
DS
3671 vnc_import_bgp_del_route(peer->bgp, p, pi);
3672 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3673 }
65efcfce 3674 }
d62a17ae 3675#endif
128ea8ab 3676
d62a17ae 3677 /* If this is an EVPN route, process for un-import. */
3678 if (safi == SAFI_EVPN)
b54892e0 3679 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3680
9bcb3eef 3681 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3682}
3683
4b7e6066
DS
3684struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3685 struct peer *peer, struct attr *attr,
9bcb3eef 3686 struct bgp_dest *dest)
fb018d25 3687{
4b7e6066 3688 struct bgp_path_info *new;
fb018d25 3689
d62a17ae 3690 /* Make new BGP info. */
4b7e6066 3691 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3692 new->type = type;
3693 new->instance = instance;
3694 new->sub_type = sub_type;
3695 new->peer = peer;
3696 new->attr = attr;
083ec940 3697 new->uptime = monotime(NULL);
9bcb3eef 3698 new->net = dest;
d62a17ae 3699 return new;
fb018d25
DS
3700}
3701
c265ee22 3702/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3703bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3704 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3705 struct bgp_dest *dest)
d62a17ae 3706{
2dbe3fa9 3707 bool ret = false;
b099a5c8
DA
3708 bool is_bgp_static_route =
3709 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3710 : false;
d62a17ae 3711
e8442016
DS
3712 /*
3713 * Only validated for unicast and multicast currently.
3714 * Also valid for EVPN where the nexthop is an IP address.
3715 * If we are a bgp static route being checked then there is
3716 * no need to check to see if the nexthop is martian as
3717 * that it should be ok.
3718 */
3719 if (is_bgp_static_route ||
3720 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3721 return false;
d62a17ae 3722
3723 /* If NEXT_HOP is present, validate it. */
3724 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3725 if (attr->nexthop.s_addr == INADDR_ANY ||
3726 !ipv4_unicast_valid(&attr->nexthop) ||
3727 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3728 return true;
d62a17ae 3729 }
c265ee22 3730
d62a17ae 3731 /* If MP_NEXTHOP is present, validate it. */
3732 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3733 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3734 * it is not an IPv6 link-local address.
0355b41d
DA
3735 *
3736 * If we receive an UPDATE with nexthop length set to 32 bytes
3737 * we shouldn't discard an UPDATE if it's set to (::).
3738 * The link-local (2st) is validated along the code path later.
d62a17ae 3739 */
3740 if (attr->mp_nexthop_len) {
3741 switch (attr->mp_nexthop_len) {
3742 case BGP_ATTR_NHLEN_IPV4:
3743 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3744 ret = (attr->mp_nexthop_global_in.s_addr ==
3745 INADDR_ANY ||
3746 !ipv4_unicast_valid(
3747 &attr->mp_nexthop_global_in) ||
3748 bgp_nexthop_self(bgp, afi, type, stype, attr,
3749 dest));
d62a17ae 3750 break;
3751
3752 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3753 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3754 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3755 &attr->mp_nexthop_global)
d62a17ae 3756 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3757 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3758 &attr->mp_nexthop_global)
3759 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3760 dest));
d62a17ae 3761 break;
0355b41d
DA
3762 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3763 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3764 || IN6_IS_ADDR_MULTICAST(
3765 &attr->mp_nexthop_global)
3766 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3767 dest));
0355b41d 3768 break;
d62a17ae 3769
3770 default:
3dc339cd 3771 ret = true;
d62a17ae 3772 break;
3773 }
3774 }
c265ee22 3775
d62a17ae 3776 return ret;
3777}
3778
aade37d7 3779static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3780{
3781 struct community *old;
3782 struct community *new;
3783 struct community *merge;
aade37d7 3784 struct community *no_export;
2721dd61 3785
9a706b42 3786 old = bgp_attr_get_community(attr);
aade37d7 3787 no_export = community_str2com("no-export");
2721dd61 3788
b4efa101
DA
3789 assert(no_export);
3790
2721dd61 3791 if (old) {
aade37d7 3792 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3793
3794 if (!old->refcnt)
3795 community_free(&old);
3796
3797 new = community_uniq_sort(merge);
3798 community_free(&merge);
3799 } else {
aade37d7 3800 new = community_dup(no_export);
2721dd61
DA
3801 }
3802
aade37d7 3803 community_free(&no_export);
2721dd61 3804
9a706b42 3805 bgp_attr_set_community(attr, new);
2721dd61
DA
3806}
3807
5a1ae2c2 3808int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3809 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3810 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3811 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3812 struct bgp_route_evpn *evpn)
d62a17ae 3813{
3814 int ret;
3815 int aspath_loop_count = 0;
9bcb3eef 3816 struct bgp_dest *dest;
d62a17ae 3817 struct bgp *bgp;
3818 struct attr new_attr;
3819 struct attr *attr_new;
40381db7 3820 struct bgp_path_info *pi;
4b7e6066
DS
3821 struct bgp_path_info *new;
3822 struct bgp_path_info_extra *extra;
d62a17ae 3823 const char *reason;
3824 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3825 int connected = 0;
3826 int do_loop_check = 1;
3827 int has_valid_label = 0;
7c312383 3828 afi_t nh_afi;
949b0f24 3829 uint8_t pi_type = 0;
3830 uint8_t pi_sub_type = 0;
9146341f 3831 bool force_evpn_import = false;
907707db 3832 safi_t orig_safi = safi;
a486300b 3833 bool leak_success = true;
949b0f24 3834
c7bb4f00 3835 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3836 char pfxprint[PREFIX2STR_BUFFER];
3837
3838 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3839 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3840 afi, safi, attr);
6401252f
QY
3841 }
3842
49e5a4a0 3843#ifdef ENABLE_BGP_VNC
d62a17ae 3844 int vnc_implicit_withdraw = 0;
65efcfce 3845#endif
d62a17ae 3846 int same_attr = 0;
718e3744 3847
907707db
MS
3848 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3849 if (orig_safi == SAFI_LABELED_UNICAST)
3850 safi = SAFI_UNICAST;
3851
6006b807 3852 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3853 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3854 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3855
d62a17ae 3856 bgp = peer->bgp;
9bcb3eef 3857 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3858 /* TODO: Check to see if we can get rid of "is_valid_label" */
3859 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3860 has_valid_label = (num_labels > 0) ? 1 : 0;
3861 else
3862 has_valid_label = bgp_is_valid_label(label);
718e3744 3863
28f66de2
MS
3864 if (has_valid_label)
3865 assert(label != NULL);
3866
66ff6089
AD
3867 /* Update overlay index of the attribute */
3868 if (afi == AFI_L2VPN && evpn)
3869 memcpy(&attr->evpn_overlay, evpn,
3870 sizeof(struct bgp_route_evpn));
3871
d62a17ae 3872 /* When peer's soft reconfiguration enabled. Record input packet in
3873 Adj-RIBs-In. */
3874 if (!soft_reconfig
3875 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3876 && peer != bgp->peer_self)
9bcb3eef 3877 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3878
3879 /* Check previously received route. */
9bcb3eef 3880 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3881 if (pi->peer == peer && pi->type == type
3882 && pi->sub_type == sub_type
3883 && pi->addpath_rx_id == addpath_id)
d62a17ae 3884 break;
3885
3886 /* AS path local-as loop check. */
3887 if (peer->change_local_as) {
c4368918
DW
3888 if (peer->allowas_in[afi][safi])
3889 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3890 else if (!CHECK_FLAG(peer->flags,
3891 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3892 aspath_loop_count = 1;
3893
3894 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3895 > aspath_loop_count) {
b4d46cc9 3896 peer->stat_pfx_aspath_loop++;
692174a1 3897 reason = "as-path contains our own AS;";
d62a17ae 3898 goto filtered;
3899 }
718e3744 3900 }
718e3744 3901
d62a17ae 3902 /* If the peer is configured for "allowas-in origin" and the last ASN in
3903 * the
3904 * as-path is our ASN then we do not need to call aspath_loop_check
3905 */
3906 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3907 if (aspath_get_last_as(attr->aspath) == bgp->as)
3908 do_loop_check = 0;
3909
3910 /* AS path loop check. */
3911 if (do_loop_check) {
3912 if (aspath_loop_check(attr->aspath, bgp->as)
3913 > peer->allowas_in[afi][safi]
3914 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3915 && aspath_loop_check(attr->aspath, bgp->confed_id)
3916 > peer->allowas_in[afi][safi])) {
b4d46cc9 3917 peer->stat_pfx_aspath_loop++;
d62a17ae 3918 reason = "as-path contains our own AS;";
3919 goto filtered;
3920 }
3921 }
aac9ef6c 3922
d62a17ae 3923 /* Route reflector originator ID check. */
3924 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3925 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3926 peer->stat_pfx_originator_loop++;
d62a17ae 3927 reason = "originator is us;";
3928 goto filtered;
3929 }
718e3744 3930
d62a17ae 3931 /* Route reflector cluster ID check. */
3932 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3933 peer->stat_pfx_cluster_loop++;
d62a17ae 3934 reason = "reflected from the same cluster;";
3935 goto filtered;
3936 }
718e3744 3937
d62a17ae 3938 /* Apply incoming filter. */
907707db 3939 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3940 peer->stat_pfx_filter++;
d62a17ae 3941 reason = "filter;";
3942 goto filtered;
3943 }
718e3744 3944
a8b72dc6
DA
3945 /* RFC 8212 to prevent route leaks.
3946 * This specification intends to improve this situation by requiring the
3947 * explicit configuration of both BGP Import and Export Policies for any
3948 * External BGP (EBGP) session such as customers, peers, or
3949 * confederation boundaries for all enabled address families. Through
3950 * codification of the aforementioned requirement, operators will
3951 * benefit from consistent behavior across different BGP
3952 * implementations.
3953 */
1d3fdccf 3954 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3955 if (!bgp_inbound_policy_exists(peer,
3956 &peer->filter[afi][safi])) {
3957 reason = "inbound policy missing";
b17826b7
DS
3958 if (monotime_since(&bgp->ebgprequirespolicywarning,
3959 NULL) > FIFTEENMINUTE2USEC ||
3960 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3961 zlog_warn(
3962 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3963 monotime(&bgp->ebgprequirespolicywarning);
3964 }
a8b72dc6
DA
3965 goto filtered;
3966 }
3967
fb29348a
DA
3968 /* draft-ietf-idr-deprecate-as-set-confed-set
3969 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3970 * Eventually, This document (if approved) updates RFC 4271
3971 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3972 * and obsoletes RFC 6472.
3973 */
7f972cd8 3974 if (peer->bgp->reject_as_sets)
fb29348a
DA
3975 if (aspath_check_as_sets(attr->aspath)) {
3976 reason =
3977 "as-path contains AS_SET or AS_CONFED_SET type;";
3978 goto filtered;
3979 }
3980
6f4f49b2 3981 new_attr = *attr;
d62a17ae 3982
3983 /* Apply incoming route-map.
3984 * NB: new_attr may now contain newly allocated values from route-map
3985 * "set"
3986 * commands, so we need bgp_attr_flush in the error paths, until we
3987 * intern
3988 * the attr (which takes over the memory references) */
907707db 3989 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3990 num_labels, dest)
3991 == RMAP_DENY) {
b4d46cc9 3992 peer->stat_pfx_filter++;
d62a17ae 3993 reason = "route-map;";
3994 bgp_attr_flush(&new_attr);
3995 goto filtered;
3996 }
718e3744 3997
05864da7 3998 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3999 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4000 /* remove from RIB previous entry */
4001 bgp_zebra_withdraw(p, pi, bgp, safi);
4002 }
4003
7f323236
DW
4004 if (peer->sort == BGP_PEER_EBGP) {
4005
2721dd61
DA
4006 /* rfc7999:
4007 * A BGP speaker receiving an announcement tagged with the
4008 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4009 * NO_EXPORT community as defined in RFC1997, or a
4010 * similar community, to prevent propagation of the
4011 * prefix outside the local AS. The community to prevent
4012 * propagation SHOULD be chosen according to the operator's
4013 * routing policy.
4014 */
9a706b42
DA
4015 if (bgp_attr_get_community(&new_attr) &&
4016 community_include(bgp_attr_get_community(&new_attr),
4017 COMMUNITY_BLACKHOLE))
aade37d7 4018 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4019
a4d82a8a
PZ
4020 /* If we receive the graceful-shutdown community from an eBGP
4021 * peer we must lower local-preference */
9a706b42
DA
4022 if (bgp_attr_get_community(&new_attr) &&
4023 community_include(bgp_attr_get_community(&new_attr),
4024 COMMUNITY_GSHUT)) {
7f323236
DW
4025 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4026 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4027
a4d82a8a
PZ
4028 /* If graceful-shutdown is configured then add the GSHUT
4029 * community to all paths received from eBGP peers */
637e5ba4 4030 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 4031 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4032 }
4033
949b0f24 4034 if (pi) {
4035 pi_type = pi->type;
4036 pi_sub_type = pi->sub_type;
4037 }
4038
d62a17ae 4039 /* next hop check. */
a4d82a8a 4040 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
4041 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
4042 &new_attr, dest)) {
b4d46cc9 4043 peer->stat_pfx_nh_invalid++;
d62a17ae 4044 reason = "martian or self next-hop;";
4045 bgp_attr_flush(&new_attr);
4046 goto filtered;
4047 }
718e3744 4048
5c14a191 4049 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4050 peer->stat_pfx_nh_invalid++;
4e802e66 4051 reason = "self mac;";
4dbf2038 4052 bgp_attr_flush(&new_attr);
4e802e66
DS
4053 goto filtered;
4054 }
4055
5a78f2bc
EB
4056 if (bgp_check_role_applicability(afi, safi) &&
4057 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4058 reason = "failing otc validation";
4059 bgp_attr_flush(&new_attr);
4060 goto filtered;
4061 }
a1b773e2
DS
4062 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4063 * condition :
4064 * Suppress fib is enabled
4065 * BGP_OPT_NO_FIB is not enabled
4066 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4067 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4068 */
4069 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4070 && (sub_type == BGP_ROUTE_NORMAL)
4071 && (!bgp_option_check(BGP_OPT_NO_FIB))
4072 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4073 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4074
9cbd06e0
DA
4075 /* If maximum prefix count is configured and current prefix
4076 * count exeed it.
4077 */
4dbf2038
IR
4078 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4079 bgp_attr_flush(&new_attr);
9cbd06e0 4080 return -1;
4dbf2038
IR
4081 }
4082
01da2d26
DA
4083 /* If neighbor soo is configured, tag all incoming routes with
4084 * this SoO tag and then filter out advertisements in
4085 * subgroup_announce_check() if it matches the configured SoO
4086 * on the other peer.
4087 */
4088 if (peer->soo[afi][safi]) {
4089 struct ecommunity *old_ecomm =
4090 bgp_attr_get_ecommunity(&new_attr);
4091 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4092 struct ecommunity *new_ecomm;
4093
4094 if (old_ecomm) {
4095 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4096 ecomm_soo);
4097
4098 if (!old_ecomm->refcnt)
4099 ecommunity_free(&old_ecomm);
4100 } else {
4101 new_ecomm = ecommunity_dup(ecomm_soo);
4102 }
4103
4104 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4105 }
4106
4dbf2038 4107 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4108
d62a17ae 4109 /* If the update is implicit withdraw. */
40381db7 4110 if (pi) {
083ec940 4111 pi->uptime = monotime(NULL);
40381db7 4112 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4113
9bcb3eef 4114 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4115
d62a17ae 4116 /* Same attribute comes in. */
40381db7 4117 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4118 && same_attr
d62a17ae 4119 && (!has_valid_label
40381db7 4120 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4121 num_labels * sizeof(mpls_label_t))
66ff6089 4122 == 0)) {
b4f7f45b
IR
4123 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4124 BGP_CONFIG_DAMPENING)
d62a17ae 4125 && peer->sort == BGP_PEER_EBGP
40381db7 4126 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4127 if (bgp_debug_update(peer, p, NULL, 1)) {
4128 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4129 afi, safi, prd, p, label,
4130 num_labels, addpath_id ? 1 : 0,
66ff6089 4131 addpath_id, evpn, pfx_buf,
a4d82a8a 4132 sizeof(pfx_buf));
f70c91dc 4133 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4134 pfx_buf);
4135 }
4136
9bcb3eef 4137 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4138 != BGP_DAMP_SUPPRESSED) {
40381db7 4139 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4140 safi);
9bcb3eef 4141 bgp_process(bgp, dest, afi, safi);
d62a17ae 4142 }
4143 } else /* Duplicate - odd */
4144 {
4145 if (bgp_debug_update(peer, p, NULL, 1)) {
4146 if (!peer->rcvd_attr_printed) {
4147 zlog_debug(
f70c91dc
DA
4148 "%pBP rcvd UPDATE w/ attr: %s",
4149 peer,
d62a17ae 4150 peer->rcvd_attr_str);
4151 peer->rcvd_attr_printed = 1;
4152 }
4153
4154 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4155 afi, safi, prd, p, label,
4156 num_labels, addpath_id ? 1 : 0,
66ff6089 4157 addpath_id, evpn, pfx_buf,
a4d82a8a 4158 sizeof(pfx_buf));
d62a17ae 4159 zlog_debug(
f70c91dc
DA
4160 "%pBP rcvd %s...duplicate ignored",
4161 peer, pfx_buf);
d62a17ae 4162 }
4163
4164 /* graceful restart STALE flag unset. */
40381db7 4165 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4166 bgp_path_info_unset_flag(
9bcb3eef
DS
4167 dest, pi, BGP_PATH_STALE);
4168 bgp_dest_set_defer_flag(dest, false);
4169 bgp_process(bgp, dest, afi, safi);
d62a17ae 4170 }
4171 }
4172
9bcb3eef 4173 bgp_dest_unlock_node(dest);
d62a17ae 4174 bgp_attr_unintern(&attr_new);
4175
4176 return 0;
4177 }
718e3744 4178
d62a17ae 4179 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4180 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4181 if (bgp_debug_update(peer, p, NULL, 1)) {
4182 bgp_debug_rdpfxpath2str(
a4d82a8a 4183 afi, safi, prd, p, label, num_labels,
66ff6089 4184 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4185 pfx_buf, sizeof(pfx_buf));
d62a17ae 4186 zlog_debug(
f70c91dc
DA
4187 "%pBP rcvd %s, flapped quicker than processing",
4188 peer, pfx_buf);
d62a17ae 4189 }
4190
9bcb3eef 4191 bgp_path_info_restore(dest, pi);
9146341f 4192
4193 /*
4194 * If the BGP_PATH_REMOVED flag is set, then EVPN
4195 * routes would have been unimported already when a
4196 * prior BGP withdraw processing happened. Such routes
4197 * need to be imported again, so flag accordingly.
4198 */
4199 force_evpn_import = true;
d62a17ae 4200 }
718e3744 4201
d62a17ae 4202 /* Received Logging. */
4203 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4204 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4205 num_labels, addpath_id ? 1 : 0,
66ff6089 4206 addpath_id, evpn, pfx_buf,
a4d82a8a 4207 sizeof(pfx_buf));
f70c91dc 4208 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4209 }
718e3744 4210
d62a17ae 4211 /* graceful restart STALE flag unset. */
f009ff26 4212 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4213 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4214 bgp_dest_set_defer_flag(dest, false);
f009ff26 4215 }
d62a17ae 4216
4217 /* The attribute is changed. */
9bcb3eef 4218 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4219
4220 /* implicit withdraw, decrement aggregate and pcount here.
4221 * only if update is accepted, they'll increment below.
4222 */
40381db7 4223 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4224
4225 /* Update bgp route dampening information. */
b4f7f45b 4226 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4227 && peer->sort == BGP_PEER_EBGP) {
4228 /* This is implicit withdraw so we should update
b4f7f45b
IR
4229 dampening
4230 information. */
40381db7 4231 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4232 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4233 }
49e5a4a0 4234#ifdef ENABLE_BGP_VNC
d62a17ae 4235 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4236 struct bgp_dest *pdest = NULL;
d62a17ae 4237 struct bgp_table *table = NULL;
4238
9bcb3eef
DS
4239 pdest = bgp_node_get(bgp->rib[afi][safi],
4240 (struct prefix *)prd);
4241 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4242 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4243
4244 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4245 bgp, prd, table, p, pi);
d62a17ae 4246 }
9bcb3eef 4247 bgp_dest_unlock_node(pdest);
d62a17ae 4248 }
4249 if ((afi == AFI_IP || afi == AFI_IP6)
4250 && (safi == SAFI_UNICAST)) {
40381db7 4251 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4252 /*
4253 * Implicit withdraw case.
4254 */
4255 ++vnc_implicit_withdraw;
40381db7
DS
4256 vnc_import_bgp_del_route(bgp, p, pi);
4257 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4258 }
4259 }
65efcfce 4260#endif
128ea8ab 4261
d62a17ae 4262 /* Special handling for EVPN update of an existing route. If the
4263 * extended community attribute has changed, we need to
4264 * un-import
4265 * the route using its existing extended community. It will be
4266 * subsequently processed for import with the new extended
4267 * community.
4268 */
6f8c9c11
PR
4269 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4270 && !same_attr) {
40381db7 4271 if ((pi->attr->flag
d62a17ae 4272 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4273 && (attr_new->flag
4274 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4275 int cmp;
4276
b53e67a3
DA
4277 cmp = ecommunity_cmp(
4278 bgp_attr_get_ecommunity(pi->attr),
4279 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4280 if (!cmp) {
4281 if (bgp_debug_update(peer, p, NULL, 1))
4282 zlog_debug(
4283 "Change in EXT-COMM, existing %s new %s",
4284 ecommunity_str(
b53e67a3
DA
4285 bgp_attr_get_ecommunity(
4286 pi->attr)),
d62a17ae 4287 ecommunity_str(
b53e67a3
DA
4288 bgp_attr_get_ecommunity(
4289 attr_new)));
6f8c9c11
PR
4290 if (safi == SAFI_EVPN)
4291 bgp_evpn_unimport_route(
4292 bgp, afi, safi, p, pi);
4293 else /* SAFI_MPLS_VPN */
4294 vpn_leak_to_vrf_withdraw(bgp,
4295 pi);
d62a17ae 4296 }
4297 }
4298 }
718e3744 4299
d62a17ae 4300 /* Update to new attribute. */
40381db7
DS
4301 bgp_attr_unintern(&pi->attr);
4302 pi->attr = attr_new;
d62a17ae 4303
4304 /* Update MPLS label */
4305 if (has_valid_label) {
40381db7 4306 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4307 if (extra->label != label) {
4308 memcpy(&extra->label, label,
dbd587da 4309 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4310 extra->num_labels = num_labels;
4311 }
b57ba6d2
MK
4312 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4313 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4314 }
718e3744 4315
e496b420
HS
4316 /* Update SRv6 SID */
4317 if (attr->srv6_l3vpn) {
4318 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4319 if (sid_diff(&extra->sid[0].sid,
4320 &attr->srv6_l3vpn->sid)) {
4321 sid_copy(&extra->sid[0].sid,
e496b420
HS
4322 &attr->srv6_l3vpn->sid);
4323 extra->num_sids = 1;
cc8f05df 4324
16f3db2d
RS
4325 extra->sid[0].loc_block_len = 0;
4326 extra->sid[0].loc_node_len = 0;
4327 extra->sid[0].func_len = 0;
4328 extra->sid[0].arg_len = 0;
ea7cd161
RS
4329 extra->sid[0].transposition_len = 0;
4330 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4331
4332 if (attr->srv6_l3vpn->loc_block_len != 0) {
4333 extra->sid[0].loc_block_len =
4334 attr->srv6_l3vpn->loc_block_len;
4335 extra->sid[0].loc_node_len =
4336 attr->srv6_l3vpn->loc_node_len;
4337 extra->sid[0].func_len =
4338 attr->srv6_l3vpn->func_len;
4339 extra->sid[0].arg_len =
4340 attr->srv6_l3vpn->arg_len;
ea7cd161 4341 extra->sid[0].transposition_len =
cc8f05df 4342 attr->srv6_l3vpn
ea7cd161
RS
4343 ->transposition_len;
4344 extra->sid[0].transposition_offset =
cc8f05df 4345 attr->srv6_l3vpn
ea7cd161
RS
4346 ->transposition_offset;
4347 }
e496b420
HS
4348 }
4349 } else if (attr->srv6_vpn) {
4350 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4351 if (sid_diff(&extra->sid[0].sid,
4352 &attr->srv6_vpn->sid)) {
4353 sid_copy(&extra->sid[0].sid,
4354 &attr->srv6_vpn->sid);
e496b420
HS
4355 extra->num_sids = 1;
4356 }
4357 }
4358
49e5a4a0 4359#ifdef ENABLE_BGP_VNC
d62a17ae 4360 if ((afi == AFI_IP || afi == AFI_IP6)
4361 && (safi == SAFI_UNICAST)) {
4362 if (vnc_implicit_withdraw) {
4363 /*
4364 * Add back the route with its new attributes
4365 * (e.g., nexthop).
4366 * The route is still selected, until the route
4367 * selection
4368 * queued by bgp_process actually runs. We have
4369 * to make this
4370 * update to the VNC side immediately to avoid
4371 * racing against
4372 * configuration changes (e.g., route-map
4373 * changes) which
4374 * trigger re-importation of the entire RIB.
4375 */
40381db7
DS
4376 vnc_import_bgp_add_route(bgp, p, pi);
4377 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4378 }
4379 }
65efcfce
LB
4380#endif
4381
d62a17ae 4382 /* Update bgp route dampening information. */
b4f7f45b 4383 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4384 && peer->sort == BGP_PEER_EBGP) {
4385 /* Now we do normal update dampening. */
9bcb3eef 4386 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4387 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4388 bgp_dest_unlock_node(dest);
d62a17ae 4389 return 0;
4390 }
4391 }
128ea8ab 4392
d62a17ae 4393 /* Nexthop reachability check - for unicast and
4394 * labeled-unicast.. */
7c312383
AD
4395 if (((afi == AFI_IP || afi == AFI_IP6)
4396 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4397 || (safi == SAFI_EVPN &&
4398 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4399 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4400 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4401 && !CHECK_FLAG(peer->flags,
4402 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4403 && !CHECK_FLAG(bgp->flags,
4404 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4405 connected = 1;
4406 else
4407 connected = 0;
4408
960035b2
PZ
4409 struct bgp *bgp_nexthop = bgp;
4410
40381db7
DS
4411 if (pi->extra && pi->extra->bgp_orig)
4412 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4413
7c312383
AD
4414 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4415
4416 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4417 safi, pi, NULL, connected,
4418 p)
a4d82a8a 4419 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4420 bgp_path_info_set_flag(dest, pi,
4421 BGP_PATH_VALID);
d62a17ae 4422 else {
4423 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4424 zlog_debug("%s(%pI4): NH unresolved",
4425 __func__,
4426 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4427 }
9bcb3eef 4428 bgp_path_info_unset_flag(dest, pi,
18ee8310 4429 BGP_PATH_VALID);
d62a17ae 4430 }
4431 } else
9bcb3eef 4432 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4433
49e5a4a0 4434#ifdef ENABLE_BGP_VNC
d62a17ae 4435 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4436 struct bgp_dest *pdest = NULL;
d62a17ae 4437 struct bgp_table *table = NULL;
4438
9bcb3eef
DS
4439 pdest = bgp_node_get(bgp->rib[afi][safi],
4440 (struct prefix *)prd);
4441 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4442 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4443
4444 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4445 bgp, prd, table, p, pi);
d62a17ae 4446 }
9bcb3eef 4447 bgp_dest_unlock_node(pdest);
d62a17ae 4448 }
4449#endif
718e3744 4450
d62a17ae 4451 /* If this is an EVPN route and some attribute has changed,
9146341f 4452 * or we are explicitly told to perform a route import, process
d62a17ae 4453 * route for import. If the extended community has changed, we
4454 * would
4455 * have done the un-import earlier and the import would result
4456 * in the
4457 * route getting injected into appropriate L2 VNIs. If it is
4458 * just
4459 * some other attribute change, the import will result in
4460 * updating
4461 * the attributes for the route in the VNI(s).
4462 */
9146341f 4463 if (safi == SAFI_EVPN &&
4464 (!same_attr || force_evpn_import) &&
7c312383 4465 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4466 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4467
4468 /* Process change. */
40381db7 4469 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4470
9bcb3eef
DS
4471 bgp_process(bgp, dest, afi, safi);
4472 bgp_dest_unlock_node(dest);
558d1fec 4473
ddb5b488
PZ
4474 if (SAFI_UNICAST == safi
4475 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4476 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4477
40381db7 4478 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4479 }
4480 if ((SAFI_MPLS_VPN == safi)
4481 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4482
a486300b 4483 leak_success = vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4484 }
4485
49e5a4a0 4486#ifdef ENABLE_BGP_VNC
d62a17ae 4487 if (SAFI_MPLS_VPN == safi) {
4488 mpls_label_t label_decoded = decode_label(label);
28070ee3 4489
d62a17ae 4490 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4491 type, sub_type, &label_decoded);
4492 }
4493 if (SAFI_ENCAP == safi) {
4494 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4495 type, sub_type, NULL);
4496 }
28070ee3 4497#endif
a486300b
PG
4498 if ((safi == SAFI_MPLS_VPN) &&
4499 !CHECK_FLAG(bgp->af_flags[afi][safi],
4500 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4501 !leak_success) {
4502 bgp_unlink_nexthop(pi);
4503 bgp_path_info_delete(dest, pi);
4504 }
d62a17ae 4505 return 0;
4506 } // End of implicit withdraw
718e3744 4507
d62a17ae 4508 /* Received Logging. */
4509 if (bgp_debug_update(peer, p, NULL, 1)) {
4510 if (!peer->rcvd_attr_printed) {
f70c91dc 4511 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4512 peer->rcvd_attr_str);
4513 peer->rcvd_attr_printed = 1;
4514 }
718e3744 4515
a4d82a8a 4516 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4517 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4518 pfx_buf, sizeof(pfx_buf));
f70c91dc 4519 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4520 }
718e3744 4521
d62a17ae 4522 /* Make new BGP info. */
9bcb3eef 4523 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4524
d62a17ae 4525 /* Update MPLS label */
4526 if (has_valid_label) {
18ee8310 4527 extra = bgp_path_info_extra_get(new);
8ba71050 4528 if (extra->label != label) {
dbd587da
QY
4529 memcpy(&extra->label, label,
4530 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4531 extra->num_labels = num_labels;
4532 }
b57ba6d2
MK
4533 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4534 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4535 }
718e3744 4536
e496b420
HS
4537 /* Update SRv6 SID */
4538 if (safi == SAFI_MPLS_VPN) {
4539 extra = bgp_path_info_extra_get(new);
4540 if (attr->srv6_l3vpn) {
16f3db2d 4541 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4542 extra->num_sids = 1;
cc8f05df 4543
16f3db2d
RS
4544 extra->sid[0].loc_block_len =
4545 attr->srv6_l3vpn->loc_block_len;
4546 extra->sid[0].loc_node_len =
4547 attr->srv6_l3vpn->loc_node_len;
4548 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4549 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4550 extra->sid[0].transposition_len =
4551 attr->srv6_l3vpn->transposition_len;
4552 extra->sid[0].transposition_offset =
4553 attr->srv6_l3vpn->transposition_offset;
e496b420 4554 } else if (attr->srv6_vpn) {
16f3db2d 4555 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4556 extra->num_sids = 1;
4557 }
4558 }
4559
d62a17ae 4560 /* Nexthop reachability check. */
7c312383
AD
4561 if (((afi == AFI_IP || afi == AFI_IP6)
4562 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4563 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4564 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4565 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4566 && !CHECK_FLAG(peer->flags,
4567 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4568 && !CHECK_FLAG(bgp->flags,
4569 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4570 connected = 1;
4571 else
4572 connected = 0;
4573
7c312383
AD
4574 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4575
4053e952 4576 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4577 connected, p)
a4d82a8a 4578 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4579 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4580 else {
4581 if (BGP_DEBUG(nht, NHT)) {
4582 char buf1[INET6_ADDRSTRLEN];
4583 inet_ntop(AF_INET,
4584 (const void *)&attr_new->nexthop,
4585 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4586 zlog_debug("%s(%s): NH unresolved", __func__,
4587 buf1);
d62a17ae 4588 }
9bcb3eef 4589 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4590 }
4591 } else
9bcb3eef 4592 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4593
d62a17ae 4594 /* Addpath ID */
4595 new->addpath_rx_id = addpath_id;
4596
4597 /* Increment prefix */
4598 bgp_aggregate_increment(bgp, p, new, afi, safi);
4599
4600 /* Register new BGP information. */
9bcb3eef 4601 bgp_path_info_add(dest, new);
d62a17ae 4602
4603 /* route_node_get lock */
9bcb3eef 4604 bgp_dest_unlock_node(dest);
558d1fec 4605
49e5a4a0 4606#ifdef ENABLE_BGP_VNC
d62a17ae 4607 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4608 struct bgp_dest *pdest = NULL;
d62a17ae 4609 struct bgp_table *table = NULL;
4610
9bcb3eef
DS
4611 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4612 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4613 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4614
4615 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4616 bgp, prd, table, p, new);
4617 }
9bcb3eef 4618 bgp_dest_unlock_node(pdest);
d62a17ae 4619 }
65efcfce
LB
4620#endif
4621
d62a17ae 4622 /* If this is an EVPN route, process for import. */
7c312383 4623 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4624 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4625
9bcb3eef 4626 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4627
d62a17ae 4628 /* Process change. */
9bcb3eef 4629 bgp_process(bgp, dest, afi, safi);
718e3744 4630
ddb5b488
PZ
4631 if (SAFI_UNICAST == safi
4632 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4633 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4634 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4635 }
4636 if ((SAFI_MPLS_VPN == safi)
4637 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
a486300b 4638 leak_success = vpn_leak_to_vrf_update(bgp, new);
ddb5b488 4639 }
49e5a4a0 4640#ifdef ENABLE_BGP_VNC
d62a17ae 4641 if (SAFI_MPLS_VPN == safi) {
4642 mpls_label_t label_decoded = decode_label(label);
28070ee3 4643
d62a17ae 4644 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4645 sub_type, &label_decoded);
4646 }
4647 if (SAFI_ENCAP == safi) {
4648 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4649 sub_type, NULL);
4650 }
28070ee3 4651#endif
a486300b
PG
4652 if ((safi == SAFI_MPLS_VPN) &&
4653 !CHECK_FLAG(bgp->af_flags[afi][safi],
4654 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4655 !leak_success) {
4656 bgp_unlink_nexthop(new);
4657 bgp_path_info_delete(dest, new);
4658 }
28070ee3 4659
d62a17ae 4660 return 0;
718e3744 4661
d62a17ae 4662/* This BGP update is filtered. Log the reason then update BGP
4663 entry. */
4664filtered:
9bcb3eef 4665 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4666
d62a17ae 4667 if (bgp_debug_update(peer, p, NULL, 1)) {
4668 if (!peer->rcvd_attr_printed) {
f70c91dc 4669 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4670 peer->rcvd_attr_str);
4671 peer->rcvd_attr_printed = 1;
4672 }
718e3744 4673
a4d82a8a 4674 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4675 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4676 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4677 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4678 peer, pfx_buf, reason);
d62a17ae 4679 }
128ea8ab 4680
40381db7 4681 if (pi) {
d62a17ae 4682 /* If this is an EVPN route, un-import it as it is now filtered.
4683 */
4684 if (safi == SAFI_EVPN)
40381db7 4685 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4686
ddb5b488
PZ
4687 if (SAFI_UNICAST == safi
4688 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4689 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4690
40381db7 4691 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4692 }
4693 if ((SAFI_MPLS_VPN == safi)
4694 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4695
40381db7 4696 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4697 }
4698
9bcb3eef 4699 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4700 }
4701
9bcb3eef 4702 bgp_dest_unlock_node(dest);
558d1fec 4703
49e5a4a0 4704#ifdef ENABLE_BGP_VNC
d62a17ae 4705 /*
4706 * Filtered update is treated as an implicit withdrawal (see
4707 * bgp_rib_remove()
4708 * a few lines above)
4709 */
4710 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4711 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4712 0);
4713 }
97736e32
PZ
4714#endif
4715
d62a17ae 4716 return 0;
718e3744 4717}
4718
26a3ffd6 4719int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4720 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4721 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4722 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4723{
d62a17ae 4724 struct bgp *bgp;
4725 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4726 struct bgp_dest *dest;
40381db7 4727 struct bgp_path_info *pi;
718e3744 4728
49e5a4a0 4729#ifdef ENABLE_BGP_VNC
d62a17ae 4730 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4731 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4732 0);
4733 }
28070ee3
PZ
4734#endif
4735
d62a17ae 4736 bgp = peer->bgp;
4737
4738 /* Lookup node. */
9bcb3eef 4739 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4740
4741 /* If peer is soft reconfiguration enabled. Record input packet for
4742 * further calculation.
4743 *
4744 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4745 * routes that are filtered. This tanks out Quagga RS pretty badly due
4746 * to
4747 * the iteration over all RS clients.
4748 * Since we need to remove the entry from adj_in anyway, do that first
4749 * and
4750 * if there was no entry, we don't need to do anything more.
4751 */
4752 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4753 && peer != bgp->peer_self)
9bcb3eef 4754 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4755 peer->stat_pfx_dup_withdraw++;
4756
d62a17ae 4757 if (bgp_debug_update(peer, p, NULL, 1)) {
4758 bgp_debug_rdpfxpath2str(
a4d82a8a 4759 afi, safi, prd, p, label, num_labels,
6c995628
AD
4760 addpath_id ? 1 : 0, addpath_id, NULL,
4761 pfx_buf, sizeof(pfx_buf));
d62a17ae 4762 zlog_debug(
4763 "%s withdrawing route %s not in adj-in",
4764 peer->host, pfx_buf);
4765 }
9bcb3eef 4766 bgp_dest_unlock_node(dest);
d62a17ae 4767 return 0;
4768 }
cd808e74 4769
d62a17ae 4770 /* Lookup withdrawn route. */
9bcb3eef 4771 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4772 if (pi->peer == peer && pi->type == type
4773 && pi->sub_type == sub_type
4774 && pi->addpath_rx_id == addpath_id)
d62a17ae 4775 break;
4776
4777 /* Logging. */
4778 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4779 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4780 addpath_id ? 1 : 0, addpath_id, NULL,
4781 pfx_buf, sizeof(pfx_buf));
f70c91dc 4782 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4783 pfx_buf);
4784 }
718e3744 4785
d62a17ae 4786 /* Withdraw specified route from routing table. */
40381db7 4787 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4788 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4789 if (SAFI_UNICAST == safi
4790 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4791 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4792 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4793 }
4794 if ((SAFI_MPLS_VPN == safi)
4795 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4796
40381db7 4797 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4798 }
4799 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4800 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4801 addpath_id ? 1 : 0, addpath_id, NULL,
4802 pfx_buf, sizeof(pfx_buf));
d62a17ae 4803 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4804 }
718e3744 4805
d62a17ae 4806 /* Unlock bgp_node_get() lock. */
9bcb3eef 4807 bgp_dest_unlock_node(dest);
d62a17ae 4808
4809 return 0;
718e3744 4810}
6b0655a2 4811
d62a17ae 4812void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4813 int withdraw)
718e3744 4814{
d62a17ae 4815 struct update_subgroup *subgrp;
4816 subgrp = peer_subgroup(peer, afi, safi);
4817 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4818}
6182d65b 4819
718e3744 4820
3f9c7369
DS
4821/*
4822 * bgp_stop_announce_route_timer
4823 */
d62a17ae 4824void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4825{
d62a17ae 4826 if (!paf->t_announce_route)
4827 return;
4828
c3aaa89a 4829 THREAD_OFF(paf->t_announce_route);
718e3744 4830}
6b0655a2 4831
3f9c7369
DS
4832/*
4833 * bgp_announce_route_timer_expired
4834 *
4835 * Callback that is invoked when the route announcement timer for a
4836 * peer_af expires.
4837 */
cc9f21da 4838static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4839{
d62a17ae 4840 struct peer_af *paf;
4841 struct peer *peer;
558d1fec 4842
d62a17ae 4843 paf = THREAD_ARG(t);
4844 peer = paf->peer;
718e3744 4845
feb17238 4846 if (!peer_established(peer))
cc9f21da 4847 return;
3f9c7369 4848
d62a17ae 4849 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4850 return;
3f9c7369 4851
d62a17ae 4852 peer_af_announce_route(paf, 1);
c5aec50b
MK
4853
4854 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4855 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4856}
4857
3f9c7369
DS
4858/*
4859 * bgp_announce_route
4860 *
4861 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4862 *
4863 * if force is true we will force an update even if the update
4864 * limiting code is attempted to kick in.
3f9c7369 4865 */
e1a32ec1 4866void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4867{
4868 struct peer_af *paf;
4869 struct update_subgroup *subgrp;
4870
4871 paf = peer_af_find(peer, afi, safi);
4872 if (!paf)
4873 return;
4874 subgrp = PAF_SUBGRP(paf);
4875
4876 /*
4877 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4878 * or a refresh has already been triggered.
4879 */
4880 if (!subgrp || paf->t_announce_route)
4881 return;
4882
e1a32ec1
DS
4883 if (force)
4884 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4885
d62a17ae 4886 /*
4887 * Start a timer to stagger/delay the announce. This serves
4888 * two purposes - announcement can potentially be combined for
4889 * multiple peers and the announcement doesn't happen in the
4890 * vty context.
4891 */
4892 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4893 (subgrp->peer_count == 1)
4894 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4895 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4896 &paf->t_announce_route);
3f9c7369
DS
4897}
4898
4899/*
4900 * Announce routes from all AF tables to a peer.
4901 *
4902 * This should ONLY be called when there is a need to refresh the
4903 * routes to the peer based on a policy change for this peer alone
4904 * or a route refresh request received from the peer.
4905 * The operation will result in splitting the peer from its existing
4906 * subgroups and putting it in new subgroups.
4907 */
d62a17ae 4908void bgp_announce_route_all(struct peer *peer)
718e3744 4909{
d62a17ae 4910 afi_t afi;
4911 safi_t safi;
4912
05c7a1cc 4913 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4914 bgp_announce_route(peer, afi, safi, false);
718e3744 4915}
6b0655a2 4916
46aeabed
LS
4917/* Flag or unflag bgp_dest to determine whether it should be treated by
4918 * bgp_soft_reconfig_table_task.
4919 * Flag if flag is true. Unflag if flag is false.
4920 */
4921static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4922{
4923 struct bgp_dest *dest;
4924 struct bgp_adj_in *ain;
4925
4926 if (!table)
4927 return;
4928
4929 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4930 for (ain = dest->adj_in; ain; ain = ain->next) {
4931 if (ain->peer != NULL)
4932 break;
4933 }
4934 if (flag && ain != NULL && ain->peer != NULL)
4935 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4936 else
4937 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4938 }
4939}
4940
4941static int bgp_soft_reconfig_table_update(struct peer *peer,
4942 struct bgp_dest *dest,
4943 struct bgp_adj_in *ain, afi_t afi,
4944 safi_t safi, struct prefix_rd *prd)
4945{
4946 struct bgp_path_info *pi;
4947 uint32_t num_labels = 0;
4948 mpls_label_t *label_pnt = NULL;
4949 struct bgp_route_evpn evpn;
4950
4951 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4952 if (pi->peer == peer)
4953 break;
4954
4955 if (pi && pi->extra)
4956 num_labels = pi->extra->num_labels;
4957 if (num_labels)
4958 label_pnt = &pi->extra->label[0];
4959 if (pi)
4960 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4961 sizeof(evpn));
4962 else
4963 memset(&evpn, 0, sizeof(evpn));
4964
4965 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4966 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4967 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4968 &evpn);
4969}
4970
d62a17ae 4971static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4972 struct bgp_table *table,
4973 struct prefix_rd *prd)
718e3744 4974{
d62a17ae 4975 int ret;
9bcb3eef 4976 struct bgp_dest *dest;
d62a17ae 4977 struct bgp_adj_in *ain;
718e3744 4978
d62a17ae 4979 if (!table)
4980 table = peer->bgp->rib[afi][safi];
718e3744 4981
9bcb3eef
DS
4982 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4983 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4984 if (ain->peer != peer)
4985 continue;
8692c506 4986
46aeabed
LS
4987 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4988 afi, safi, prd);
ea47320b
DL
4989
4990 if (ret < 0) {
9bcb3eef 4991 bgp_dest_unlock_node(dest);
ea47320b 4992 return;
d62a17ae 4993 }
4994 }
718e3744 4995}
4996
46aeabed
LS
4997/* Do soft reconfig table per bgp table.
4998 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4999 * when BGP_NODE_SOFT_RECONFIG is set,
5000 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5001 * Schedule a new thread to continue the job.
5002 * Without splitting the full job into several part,
5003 * vtysh waits for the job to finish before responding to a BGP command
5004 */
cc9f21da 5005static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5006{
5007 uint32_t iter, max_iter;
5008 int ret;
5009 struct bgp_dest *dest;
5010 struct bgp_adj_in *ain;
5011 struct peer *peer;
5012 struct bgp_table *table;
5013 struct prefix_rd *prd;
5014 struct listnode *node, *nnode;
5015
5016 table = THREAD_ARG(thread);
5017 prd = NULL;
5018
5019 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5020 if (table->soft_reconfig_init) {
5021 /* first call of the function with a new srta structure.
5022 * Don't do any treatment this time on nodes
5023 * in order vtysh to respond quickly
5024 */
5025 max_iter = 0;
5026 }
5027
5028 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5029 dest = bgp_route_next(dest)) {
5030 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5031 continue;
5032
5033 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5034
5035 for (ain = dest->adj_in; ain; ain = ain->next) {
5036 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5037 nnode, peer)) {
5038 if (ain->peer != peer)
5039 continue;
5040
5041 ret = bgp_soft_reconfig_table_update(
5042 peer, dest, ain, table->afi,
5043 table->safi, prd);
5044 iter++;
5045
5046 if (ret < 0) {
5047 bgp_dest_unlock_node(dest);
5048 listnode_delete(
5049 table->soft_reconfig_peers,
5050 peer);
5051 bgp_announce_route(peer, table->afi,
e1a32ec1 5052 table->safi, false);
46aeabed
LS
5053 if (list_isempty(
5054 table->soft_reconfig_peers)) {
5055 list_delete(
5056 &table->soft_reconfig_peers);
5057 bgp_soft_reconfig_table_flag(
5058 table, false);
cc9f21da 5059 return;
46aeabed
LS
5060 }
5061 }
5062 }
5063 }
5064 }
5065
5066 /* we're either starting the initial iteration,
5067 * or we're going to continue an ongoing iteration
5068 */
5069 if (dest || table->soft_reconfig_init) {
5070 table->soft_reconfig_init = false;
5071 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5072 table, 0, &table->soft_reconfig_thread);
cc9f21da 5073 return;
46aeabed
LS
5074 }
5075 /* we're done, clean up the background iteration context info and
5076 schedule route annoucement
5077 */
5078 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5079 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5080 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5081 }
5082
5083 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5084}
5085
5086
5087/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5088 * and peer.
5089 * - bgp cannot be NULL
5090 * - if table and peer are NULL, cancel all threads within the bgp instance
5091 * - if table is NULL and peer is not,
5092 * remove peer in all threads within the bgp instance
5093 * - if peer is NULL, cancel all threads matching table within the bgp instance
5094 */
5095void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5096 const struct bgp_table *table,
5097 const struct peer *peer)
5098{
5099 struct peer *npeer;
5100 struct listnode *node, *nnode;
5101 int afi, safi;
5102 struct bgp_table *ntable;
5103
5104 if (!bgp)
5105 return;
5106
5107 FOREACH_AFI_SAFI (afi, safi) {
5108 ntable = bgp->rib[afi][safi];
5109 if (!ntable)
5110 continue;
5111 if (table && table != ntable)
5112 continue;
5113
5114 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5115 npeer)) {
5116 if (peer && peer != npeer)
5117 continue;
5118 listnode_delete(ntable->soft_reconfig_peers, npeer);
5119 }
5120
5121 if (!ntable->soft_reconfig_peers
5122 || !list_isempty(ntable->soft_reconfig_peers))
5123 continue;
5124
5125 list_delete(&ntable->soft_reconfig_peers);
5126 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5127 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5128 }
5129}
5130
d62a17ae 5131void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5132{
9bcb3eef 5133 struct bgp_dest *dest;
d62a17ae 5134 struct bgp_table *table;
46aeabed
LS
5135 struct listnode *node, *nnode;
5136 struct peer *npeer;
5137 struct peer_af *paf;
718e3744 5138
feb17238 5139 if (!peer_established(peer))
d62a17ae 5140 return;
718e3744 5141
d62a17ae 5142 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5143 && (safi != SAFI_EVPN)) {
5144 table = peer->bgp->rib[afi][safi];
5145 if (!table)
5146 return;
5147
5148 table->soft_reconfig_init = true;
5149
5150 if (!table->soft_reconfig_peers)
5151 table->soft_reconfig_peers = list_new();
5152 npeer = NULL;
5153 /* add peer to the table soft_reconfig_peers if not already
5154 * there
5155 */
5156 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5157 npeer)) {
5158 if (peer == npeer)
5159 break;
5160 }
5161 if (peer != npeer)
5162 listnode_add(table->soft_reconfig_peers, peer);
5163
5164 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5165 * on table would start back at the beginning.
5166 */
5167 bgp_soft_reconfig_table_flag(table, true);
5168
5169 if (!table->soft_reconfig_thread)
5170 thread_add_event(bm->master,
5171 bgp_soft_reconfig_table_task, table, 0,
5172 &table->soft_reconfig_thread);
5173 /* Cancel bgp_announce_route_timer_expired threads.
5174 * bgp_announce_route_timer_expired threads have been scheduled
5175 * to announce routes as soon as the soft_reconfigure process
5176 * finishes.
5177 * In this case, soft_reconfigure is also scheduled by using
5178 * a thread but is planned after the
5179 * bgp_announce_route_timer_expired threads. It means that,
5180 * without cancelling the threads, the route announcement task
5181 * would run before the soft reconfiguration one. That would
5182 * useless and would block vtysh during several seconds. Route
5183 * announcements are rescheduled as soon as the soft_reconfigure
5184 * process finishes.
5185 */
5186 paf = peer_af_find(peer, afi, safi);
5187 if (paf)
5188 bgp_stop_announce_route_timer(paf);
5189 } else
9bcb3eef
DS
5190 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5191 dest = bgp_route_next(dest)) {
5192 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5193
b54892e0
DS
5194 if (table == NULL)
5195 continue;
8692c506 5196
9bcb3eef 5197 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5198 struct prefix_rd prd;
5199
5200 prd.family = AF_UNSPEC;
5201 prd.prefixlen = 64;
5202 memcpy(&prd.val, p->u.val, 8);
5203
5204 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5205 }
718e3744 5206}
6b0655a2 5207
228da428 5208
d62a17ae 5209struct bgp_clear_node_queue {
9bcb3eef 5210 struct bgp_dest *dest;
228da428
CC
5211};
5212
d62a17ae 5213static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5214{
d62a17ae 5215 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5216 struct bgp_dest *dest = cnq->dest;
d62a17ae 5217 struct peer *peer = wq->spec.data;
40381db7 5218 struct bgp_path_info *pi;
3103e8d2 5219 struct bgp *bgp;
9bcb3eef
DS
5220 afi_t afi = bgp_dest_table(dest)->afi;
5221 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5222
9bcb3eef 5223 assert(dest && peer);
3103e8d2 5224 bgp = peer->bgp;
d62a17ae 5225
5226 /* It is possible that we have multiple paths for a prefix from a peer
5227 * if that peer is using AddPath.
5228 */
9bcb3eef 5229 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5230 if (pi->peer != peer)
ea47320b
DL
5231 continue;
5232
5233 /* graceful restart STALE flag set. */
9af52ccf
DA
5234 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5235 && peer->nsf[afi][safi])
5236 || CHECK_FLAG(peer->af_sflags[afi][safi],
5237 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5238 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5239 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5240 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5241 else {
5242 /* If this is an EVPN route, process for
5243 * un-import. */
5244 if (safi == SAFI_EVPN)
9bcb3eef
DS
5245 bgp_evpn_unimport_route(
5246 bgp, afi, safi,
5247 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5248 /* Handle withdraw for VRF route-leaking and L3VPN */
5249 if (SAFI_UNICAST == safi
5250 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5251 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5252 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5253 bgp, pi);
960035b2 5254 }
3103e8d2 5255 if (SAFI_MPLS_VPN == safi &&
960035b2 5256 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5257 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5258 }
3103e8d2 5259
9bcb3eef 5260 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5261 }
ea47320b 5262 }
d62a17ae 5263 return WQ_SUCCESS;
200df115 5264}
5265
d62a17ae 5266static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5267{
d62a17ae 5268 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5269 struct bgp_dest *dest = cnq->dest;
5270 struct bgp_table *table = bgp_dest_table(dest);
228da428 5271
9bcb3eef 5272 bgp_dest_unlock_node(dest);
d62a17ae 5273 bgp_table_unlock(table);
5274 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5275}
5276
d62a17ae 5277static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5278{
d62a17ae 5279 struct peer *peer = wq->spec.data;
64e580a7 5280
d62a17ae 5281 /* Tickle FSM to start moving again */
5282 BGP_EVENT_ADD(peer, Clearing_Completed);
5283
5284 peer_unlock(peer); /* bgp_clear_route */
200df115 5285}
718e3744 5286
d62a17ae 5287static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5288{
d62a17ae 5289 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5290
5291 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5292#undef CLEAR_QUEUE_NAME_LEN
5293
0ce1ca80 5294 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5295 peer->clear_node_queue->spec.hold = 10;
5296 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5297 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5298 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5299 peer->clear_node_queue->spec.max_retries = 0;
5300
5301 /* we only 'lock' this peer reference when the queue is actually active
5302 */
5303 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5304}
5305
d62a17ae 5306static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5307 struct bgp_table *table)
65ca75e0 5308{
9bcb3eef 5309 struct bgp_dest *dest;
b6c386bb 5310 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5311
d62a17ae 5312 if (!table)
5313 table = peer->bgp->rib[afi][safi];
dc83d712 5314
d62a17ae 5315 /* If still no table => afi/safi isn't configured at all or smth. */
5316 if (!table)
5317 return;
dc83d712 5318
9bcb3eef 5319 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5320 struct bgp_path_info *pi, *next;
d62a17ae 5321 struct bgp_adj_in *ain;
5322 struct bgp_adj_in *ain_next;
5323
5324 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5325 * queued for every clearing peer, regardless of whether it is
5326 * relevant to the peer at hand.
5327 *
5328 * Overview: There are 3 different indices which need to be
5329 * scrubbed, potentially, when a peer is removed:
5330 *
5331 * 1 peer's routes visible via the RIB (ie accepted routes)
5332 * 2 peer's routes visible by the (optional) peer's adj-in index
5333 * 3 other routes visible by the peer's adj-out index
5334 *
5335 * 3 there is no hurry in scrubbing, once the struct peer is
5336 * removed from bgp->peer, we could just GC such deleted peer's
5337 * adj-outs at our leisure.
5338 *
5339 * 1 and 2 must be 'scrubbed' in some way, at least made
5340 * invisible via RIB index before peer session is allowed to be
5341 * brought back up. So one needs to know when such a 'search' is
5342 * complete.
5343 *
5344 * Ideally:
5345 *
5346 * - there'd be a single global queue or a single RIB walker
5347 * - rather than tracking which route_nodes still need to be
5348 * examined on a peer basis, we'd track which peers still
5349 * aren't cleared
5350 *
5351 * Given that our per-peer prefix-counts now should be reliable,
5352 * this may actually be achievable. It doesn't seem to be a huge
5353 * problem at this time,
5354 *
5355 * It is possible that we have multiple paths for a prefix from
5356 * a peer
5357 * if that peer is using AddPath.
5358 */
9bcb3eef 5359 ain = dest->adj_in;
d62a17ae 5360 while (ain) {
5361 ain_next = ain->next;
5362
6a840fd9 5363 if (ain->peer == peer)
9bcb3eef 5364 bgp_adj_in_remove(dest, ain);
d62a17ae 5365
5366 ain = ain_next;
5367 }
5368
9bcb3eef 5369 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5370 next = pi->next;
5371 if (pi->peer != peer)
d62a17ae 5372 continue;
5373
5374 if (force)
9bcb3eef 5375 bgp_path_info_reap(dest, pi);
d62a17ae 5376 else {
5377 struct bgp_clear_node_queue *cnq;
5378
5379 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5380 bgp_table_lock(bgp_dest_table(dest));
5381 bgp_dest_lock_node(dest);
d62a17ae 5382 cnq = XCALLOC(
5383 MTYPE_BGP_CLEAR_NODE_QUEUE,
5384 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5385 cnq->dest = dest;
d62a17ae 5386 work_queue_add(peer->clear_node_queue, cnq);
5387 break;
5388 }
5389 }
5390 }
5391 return;
5392}
5393
5394void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5395{
9bcb3eef 5396 struct bgp_dest *dest;
d62a17ae 5397 struct bgp_table *table;
5398
5399 if (peer->clear_node_queue == NULL)
5400 bgp_clear_node_queue_init(peer);
5401
5402 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5403 * Idle until it receives a Clearing_Completed event. This protects
5404 * against peers which flap faster than we can we clear, which could
5405 * lead to:
5406 *
5407 * a) race with routes from the new session being installed before
5408 * clear_route_node visits the node (to delete the route of that
5409 * peer)
5410 * b) resource exhaustion, clear_route_node likely leads to an entry
5411 * on the process_main queue. Fast-flapping could cause that queue
5412 * to grow and grow.
5413 */
5414
5415 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5416 * the unlock will happen upon work-queue completion; other wise, the
5417 * unlock happens at the end of this function.
5418 */
5419 if (!peer->clear_node_queue->thread)
5420 peer_lock(peer);
5421
5422 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5423 bgp_clear_route_table(peer, afi, safi, NULL);
5424 else
9bcb3eef
DS
5425 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5426 dest = bgp_route_next(dest)) {
5427 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5428 if (!table)
5429 continue;
5430
5431 bgp_clear_route_table(peer, afi, safi, table);
5432 }
d62a17ae 5433
5434 /* unlock if no nodes got added to the clear-node-queue. */
5435 if (!peer->clear_node_queue->thread)
5436 peer_unlock(peer);
718e3744 5437}
d62a17ae 5438
5439void bgp_clear_route_all(struct peer *peer)
718e3744 5440{
d62a17ae 5441 afi_t afi;
5442 safi_t safi;
718e3744 5443
05c7a1cc
QY
5444 FOREACH_AFI_SAFI (afi, safi)
5445 bgp_clear_route(peer, afi, safi);
65efcfce 5446
49e5a4a0 5447#ifdef ENABLE_BGP_VNC
d62a17ae 5448 rfapiProcessPeerDown(peer);
65efcfce 5449#endif
718e3744 5450}
5451
d62a17ae 5452void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5453{
d62a17ae 5454 struct bgp_table *table;
9bcb3eef 5455 struct bgp_dest *dest;
d62a17ae 5456 struct bgp_adj_in *ain;
5457 struct bgp_adj_in *ain_next;
718e3744 5458
d62a17ae 5459 table = peer->bgp->rib[afi][safi];
718e3744 5460
d62a17ae 5461 /* It is possible that we have multiple paths for a prefix from a peer
5462 * if that peer is using AddPath.
5463 */
9bcb3eef
DS
5464 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5465 ain = dest->adj_in;
43143c8f 5466
d62a17ae 5467 while (ain) {
5468 ain_next = ain->next;
43143c8f 5469
6a840fd9 5470 if (ain->peer == peer)
9bcb3eef 5471 bgp_adj_in_remove(dest, ain);
43143c8f 5472
d62a17ae 5473 ain = ain_next;
5474 }
5475 }
718e3744 5476}
93406d87 5477
1479ed2f
DA
5478/* If any of the routes from the peer have been marked with the NO_LLGR
5479 * community, either as sent by the peer, or as the result of a configured
5480 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5481 * operation of [RFC4271].
5482 */
d62a17ae 5483void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5484{
9bcb3eef 5485 struct bgp_dest *dest;
40381db7 5486 struct bgp_path_info *pi;
d62a17ae 5487 struct bgp_table *table;
5488
9af52ccf 5489 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5490 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5491 dest = bgp_route_next(dest)) {
5492 struct bgp_dest *rm;
d62a17ae 5493
5494 /* look for neighbor in tables */
9bcb3eef 5495 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5496 if (!table)
ea47320b
DL
5497 continue;
5498
5499 for (rm = bgp_table_top(table); rm;
5500 rm = bgp_route_next(rm))
9bcb3eef 5501 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5502 pi = pi->next) {
40381db7 5503 if (pi->peer != peer)
ea47320b 5504 continue;
1479ed2f
DA
5505 if (CHECK_FLAG(
5506 peer->af_sflags[afi][safi],
5507 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5508 bgp_attr_get_community(pi->attr) &&
1479ed2f 5509 !community_include(
9a706b42
DA
5510 bgp_attr_get_community(
5511 pi->attr),
1479ed2f 5512 COMMUNITY_NO_LLGR))
e3015d91 5513 continue;
40381db7 5514 if (!CHECK_FLAG(pi->flags,
1defdda8 5515 BGP_PATH_STALE))
e3015d91 5516 continue;
ea47320b 5517
641065d4
KM
5518 /*
5519 * If this is VRF leaked route
5520 * process for withdraw.
5521 */
5522 if (pi->sub_type ==
5523 BGP_ROUTE_IMPORTED &&
5524 peer->bgp->inst_type ==
5525 BGP_INSTANCE_TYPE_DEFAULT)
5526 vpn_leak_to_vrf_withdraw(
5527 peer->bgp, pi);
5528
40381db7 5529 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5530 break;
5531 }
d62a17ae 5532 }
5533 } else {
9bcb3eef
DS
5534 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5535 dest = bgp_route_next(dest))
5536 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5537 pi = pi->next) {
40381db7 5538 if (pi->peer != peer)
ea47320b 5539 continue;
1479ed2f
DA
5540 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5541 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5542 bgp_attr_get_community(pi->attr) &&
5543 !community_include(
5544 bgp_attr_get_community(pi->attr),
5545 COMMUNITY_NO_LLGR))
e3015d91 5546 continue;
40381db7 5547 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5548 continue;
641065d4
KM
5549 if (safi == SAFI_UNICAST &&
5550 (peer->bgp->inst_type ==
5551 BGP_INSTANCE_TYPE_VRF ||
5552 peer->bgp->inst_type ==
5553 BGP_INSTANCE_TYPE_DEFAULT))
5554 vpn_leak_from_vrf_withdraw(
5555 bgp_get_default(), peer->bgp,
5556 pi);
5557
9bcb3eef 5558 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5559 break;
5560 }
d62a17ae 5561 }
93406d87 5562}
6b0655a2 5563
9af52ccf
DA
5564void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5565{
5566 struct bgp_dest *dest, *ndest;
5567 struct bgp_path_info *pi;
5568 struct bgp_table *table;
5569
5570 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5571 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5572 dest = bgp_route_next(dest)) {
5573 table = bgp_dest_get_bgp_table_info(dest);
5574 if (!table)
5575 continue;
5576
5577 for (ndest = bgp_table_top(table); ndest;
5578 ndest = bgp_route_next(ndest)) {
5579 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5580 pi = pi->next) {
5581 if (pi->peer != peer)
5582 continue;
5583
5584 if ((CHECK_FLAG(
5585 peer->af_sflags[afi][safi],
5586 PEER_STATUS_ENHANCED_REFRESH))
5587 && !CHECK_FLAG(pi->flags,
5588 BGP_PATH_STALE)
5589 && !CHECK_FLAG(
5590 pi->flags,
5591 BGP_PATH_UNUSEABLE)) {
5592 if (bgp_debug_neighbor_events(
5593 peer))
5594 zlog_debug(
5595 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5596 peer->host,
5597 afi2str(afi),
5598 safi2str(safi),
5599 bgp_dest_get_prefix(
5600 ndest));
5601
5602 bgp_path_info_set_flag(
5603 ndest, pi,
5604 BGP_PATH_STALE);
5605 }
5606 }
5607 }
5608 }
5609 } else {
5610 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5611 dest = bgp_route_next(dest)) {
5612 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5613 pi = pi->next) {
5614 if (pi->peer != peer)
5615 continue;
5616
5617 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5618 PEER_STATUS_ENHANCED_REFRESH))
5619 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5620 && !CHECK_FLAG(pi->flags,
5621 BGP_PATH_UNUSEABLE)) {
5622 if (bgp_debug_neighbor_events(peer))
5623 zlog_debug(
5624 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5625 peer->host,
5626 afi2str(afi),
5627 safi2str(safi),
5628 bgp_dest_get_prefix(
5629 dest));
5630
5631 bgp_path_info_set_flag(dest, pi,
5632 BGP_PATH_STALE);
5633 }
5634 }
5635 }
5636 }
5637}
5638
3dc339cd 5639bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5640{
e0df4c04 5641 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5642 return true;
e0df4c04 5643
9dac9fc8
DA
5644 if (peer->sort == BGP_PEER_EBGP
5645 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5646 || FILTER_LIST_OUT_NAME(filter)
5647 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5648 return true;
5649 return false;
9dac9fc8
DA
5650}
5651
3dc339cd 5652bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5653{
e0df4c04 5654 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5655 return true;
e0df4c04 5656
9dac9fc8
DA
5657 if (peer->sort == BGP_PEER_EBGP
5658 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5659 || FILTER_LIST_IN_NAME(filter)
5660 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5661 return true;
5662 return false;
9dac9fc8
DA
5663}
5664
568e10ca 5665static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5666 safi_t safi)
bb86c601 5667{
9bcb3eef 5668 struct bgp_dest *dest;
40381db7 5669 struct bgp_path_info *pi;
4b7e6066 5670 struct bgp_path_info *next;
bb86c601 5671
9bcb3eef
DS
5672 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5673 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5674 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5675
40381db7 5676 next = pi->next;
1b7bb747
CS
5677
5678 /* Unimport EVPN routes from VRFs */
5679 if (safi == SAFI_EVPN)
5680 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5681 SAFI_EVPN, p, pi);
1b7bb747 5682
40381db7
DS
5683 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5684 && pi->type == ZEBRA_ROUTE_BGP
5685 && (pi->sub_type == BGP_ROUTE_NORMAL
5686 || pi->sub_type == BGP_ROUTE_AGGREGATE
5687 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5688
d62a17ae 5689 if (bgp_fibupd_safi(safi))
b54892e0 5690 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5691 }
9514b37d 5692
9bcb3eef 5693 bgp_path_info_reap(dest, pi);
d62a17ae 5694 }
bb86c601
LB
5695}
5696
718e3744 5697/* Delete all kernel routes. */
d62a17ae 5698void bgp_cleanup_routes(struct bgp *bgp)
5699{
5700 afi_t afi;
9bcb3eef 5701 struct bgp_dest *dest;
67009e22 5702 struct bgp_table *table;
d62a17ae 5703
5704 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5705 if (afi == AFI_L2VPN)
5706 continue;
568e10ca 5707 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5708 SAFI_UNICAST);
d62a17ae 5709 /*
5710 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5711 */
5712 if (afi != AFI_L2VPN) {
5713 safi_t safi;
5714 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5715 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5716 dest = bgp_route_next(dest)) {
5717 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5718 if (table != NULL) {
5719 bgp_cleanup_table(bgp, table, safi);
5720 bgp_table_finish(&table);
9bcb3eef
DS
5721 bgp_dest_set_bgp_table_info(dest, NULL);
5722 bgp_dest_unlock_node(dest);
d62a17ae 5723 }
5724 }
5725 safi = SAFI_ENCAP;
9bcb3eef
DS
5726 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5727 dest = bgp_route_next(dest)) {
5728 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5729 if (table != NULL) {
5730 bgp_cleanup_table(bgp, table, safi);
5731 bgp_table_finish(&table);
9bcb3eef
DS
5732 bgp_dest_set_bgp_table_info(dest, NULL);
5733 bgp_dest_unlock_node(dest);
d62a17ae 5734 }
5735 }
5736 }
5737 }
9bcb3eef
DS
5738 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5739 dest = bgp_route_next(dest)) {
5740 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5741 if (table != NULL) {
5742 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5743 bgp_table_finish(&table);
9bcb3eef
DS
5744 bgp_dest_set_bgp_table_info(dest, NULL);
5745 bgp_dest_unlock_node(dest);
d62a17ae 5746 }
bb86c601 5747 }
718e3744 5748}
5749
d62a17ae 5750void bgp_reset(void)
718e3744 5751{
d62a17ae 5752 vty_reset();
5753 bgp_zclient_reset();
5754 access_list_reset();
5755 prefix_list_reset();
718e3744 5756}
6b0655a2 5757
be92fc9f 5758bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5759{
d62a17ae 5760 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5761 && CHECK_FLAG(peer->af_cap[afi][safi],
5762 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5763}
5764
718e3744 5765/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5766 value. */
d62a17ae 5767int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5768 struct bgp_nlri *packet)
5769{
d7c0a89a
QY
5770 uint8_t *pnt;
5771 uint8_t *lim;
d62a17ae 5772 struct prefix p;
5773 int psize;
5774 int ret;
5775 afi_t afi;
5776 safi_t safi;
be92fc9f 5777 bool addpath_capable;
d7c0a89a 5778 uint32_t addpath_id;
d62a17ae 5779
d62a17ae 5780 pnt = packet->nlri;
5781 lim = pnt + packet->length;
5782 afi = packet->afi;
5783 safi = packet->safi;
5784 addpath_id = 0;
be92fc9f 5785 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5786
5787 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5788 syntactic validity. If the field is syntactically incorrect,
5789 then the Error Subcode is set to Invalid Network Field. */
5790 for (; pnt < lim; pnt += psize) {
5791 /* Clear prefix structure. */
6006b807 5792 memset(&p, 0, sizeof(p));
d62a17ae 5793
be92fc9f 5794 if (addpath_capable) {
d62a17ae 5795
5796 /* When packet overflow occurs return immediately. */
761ed665 5797 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5798 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5799
a3a850a1 5800 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5801 addpath_id = ntohl(addpath_id);
d62a17ae 5802 pnt += BGP_ADDPATH_ID_LEN;
5803 }
718e3744 5804
d62a17ae 5805 /* Fetch prefix length. */
5806 p.prefixlen = *pnt++;
5807 /* afi/safi validity already verified by caller,
5808 * bgp_update_receive */
5809 p.family = afi2family(afi);
5810
5811 /* Prefix length check. */
5812 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5813 flog_err(
e50f7cfd 5814 EC_BGP_UPDATE_RCV,
14454c9f 5815 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5816 peer->host, p.prefixlen, packet->afi);
513386b5 5817 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5818 }
6b0655a2 5819
d62a17ae 5820 /* Packet size overflow check. */
5821 psize = PSIZE(p.prefixlen);
5822
5823 /* When packet overflow occur return immediately. */
5824 if (pnt + psize > lim) {
af4c2728 5825 flog_err(
e50f7cfd 5826 EC_BGP_UPDATE_RCV,
d62a17ae 5827 "%s [Error] Update packet error (prefix length %d overflows packet)",
5828 peer->host, p.prefixlen);
513386b5 5829 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5830 }
5831
5832 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5833 * prefix for the v4 and v6 afi's and unicast/multicast */
5834 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5835 flog_err(
e50f7cfd 5836 EC_BGP_UPDATE_RCV,
d62a17ae 5837 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5838 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5839 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5840 }
5841
5842 /* Fetch prefix from NLRI packet. */
a85297a7 5843 memcpy(p.u.val, pnt, psize);
d62a17ae 5844
5845 /* Check address. */
5846 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5847 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5848 /* From RFC4271 Section 6.3:
5849 *
5850 * If a prefix in the NLRI field is semantically
5851 * incorrect
5852 * (e.g., an unexpected multicast IP address),
5853 * an error SHOULD
5854 * be logged locally, and the prefix SHOULD be
5855 * ignored.
a4d82a8a 5856 */
af4c2728 5857 flog_err(
e50f7cfd 5858 EC_BGP_UPDATE_RCV,
23d0a753
DA
5859 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5860 peer->host, &p.u.prefix4);
d62a17ae 5861 continue;
5862 }
5863 }
5864
5865 /* Check address. */
5866 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5867 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5868 flog_err(
e50f7cfd 5869 EC_BGP_UPDATE_RCV,
c0d72166
DS
5870 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5871 peer->host, &p.u.prefix6);
d62a17ae 5872
5873 continue;
5874 }
5875 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5876 flog_err(
e50f7cfd 5877 EC_BGP_UPDATE_RCV,
c0d72166
DS
5878 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5879 peer->host, &p.u.prefix6);
d62a17ae 5880
5881 continue;
5882 }
5883 }
5884
5885 /* Normal process. */
5886 if (attr)
5887 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5888 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5889 NULL, NULL, 0, 0, NULL);
d62a17ae 5890 else
5891 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5892 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5893 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5894 NULL);
d62a17ae 5895
513386b5
DA
5896 /* Do not send BGP notification twice when maximum-prefix count
5897 * overflow. */
5898 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5899 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5900
5901 /* Address family configuration mismatch. */
d62a17ae 5902 if (ret < 0)
513386b5 5903 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5904 }
5905
5906 /* Packet length consistency check. */
5907 if (pnt != lim) {
af4c2728 5908 flog_err(
e50f7cfd 5909 EC_BGP_UPDATE_RCV,
d62a17ae 5910 "%s [Error] Update packet error (prefix length mismatch with total length)",
5911 peer->host);
513386b5 5912 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5913 }
6b0655a2 5914
513386b5 5915 return BGP_NLRI_PARSE_OK;
718e3744 5916}
5917
d62a17ae 5918static struct bgp_static *bgp_static_new(void)
718e3744 5919{
d62a17ae 5920 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5921}
5922
d62a17ae 5923static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5924{
0a22ddfb 5925 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5926 route_map_counter_decrement(bgp_static->rmap.map);
5927
0a22ddfb 5928 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5929 XFREE(MTYPE_BGP_STATIC, bgp_static);
5930}
5931
5f040085 5932void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5933 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5934{
9bcb3eef 5935 struct bgp_dest *dest;
40381db7 5936 struct bgp_path_info *pi;
4b7e6066 5937 struct bgp_path_info *new;
40381db7 5938 struct bgp_path_info rmap_path;
d62a17ae 5939 struct attr attr;
5940 struct attr *attr_new;
b68885f9 5941 route_map_result_t ret;
49e5a4a0 5942#ifdef ENABLE_BGP_VNC
d62a17ae 5943 int vnc_implicit_withdraw = 0;
65efcfce 5944#endif
fee0f4c6 5945
d62a17ae 5946 assert(bgp_static);
dd8103a9 5947
9bcb3eef 5948 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5949
0f05ea43 5950 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 5951
d62a17ae 5952 attr.nexthop = bgp_static->igpnexthop;
5953 attr.med = bgp_static->igpmetric;
5954 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5955
7226bc40
TA
5956 if (afi == AFI_IP)
5957 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
5958
d62a17ae 5959 if (bgp_static->atomic)
5960 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5961
d62a17ae 5962 /* Store label index, if required. */
5963 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5964 attr.label_index = bgp_static->label_index;
5965 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5966 }
718e3744 5967
d62a17ae 5968 /* Apply route-map. */
5969 if (bgp_static->rmap.name) {
5970 struct attr attr_tmp = attr;
80ced710 5971
6006b807 5972 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
5973 rmap_path.peer = bgp->peer_self;
5974 rmap_path.attr = &attr_tmp;
fee0f4c6 5975
d62a17ae 5976 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5977
1782514f 5978 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5979
d62a17ae 5980 bgp->peer_self->rmap_type = 0;
718e3744 5981
d62a17ae 5982 if (ret == RMAP_DENYMATCH) {
5983 /* Free uninterned attribute. */
5984 bgp_attr_flush(&attr_tmp);
718e3744 5985
d62a17ae 5986 /* Unintern original. */
5987 aspath_unintern(&attr.aspath);
5988 bgp_static_withdraw(bgp, p, afi, safi);
5989 return;
5990 }
7f323236 5991
637e5ba4 5992 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5993 bgp_attr_add_gshut_community(&attr_tmp);
5994
d62a17ae 5995 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5996 } else {
5997
637e5ba4 5998 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5999 bgp_attr_add_gshut_community(&attr);
6000
d62a17ae 6001 attr_new = bgp_attr_intern(&attr);
7f323236 6002 }
718e3744 6003
9bcb3eef 6004 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6005 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6006 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6007 break;
6008
40381db7
DS
6009 if (pi) {
6010 if (attrhash_cmp(pi->attr, attr_new)
6011 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6012 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6013 bgp_dest_unlock_node(dest);
d62a17ae 6014 bgp_attr_unintern(&attr_new);
6015 aspath_unintern(&attr.aspath);
6016 return;
6017 } else {
6018 /* The attribute is changed. */
9bcb3eef 6019 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6020
6021 /* Rewrite BGP route information. */
40381db7 6022 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6023 bgp_path_info_restore(dest, pi);
d62a17ae 6024 else
40381db7 6025 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6026#ifdef ENABLE_BGP_VNC
d62a17ae 6027 if ((afi == AFI_IP || afi == AFI_IP6)
6028 && (safi == SAFI_UNICAST)) {
40381db7 6029 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6030 /*
6031 * Implicit withdraw case.
40381db7 6032 * We have to do this before pi is
d62a17ae 6033 * changed
6034 */
6035 ++vnc_implicit_withdraw;
40381db7 6036 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6037 vnc_import_bgp_exterior_del_route(
40381db7 6038 bgp, p, pi);
d62a17ae 6039 }
6040 }
65efcfce 6041#endif
40381db7
DS
6042 bgp_attr_unintern(&pi->attr);
6043 pi->attr = attr_new;
083ec940 6044 pi->uptime = monotime(NULL);
49e5a4a0 6045#ifdef ENABLE_BGP_VNC
d62a17ae 6046 if ((afi == AFI_IP || afi == AFI_IP6)
6047 && (safi == SAFI_UNICAST)) {
6048 if (vnc_implicit_withdraw) {
40381db7 6049 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6050 vnc_import_bgp_exterior_add_route(
40381db7 6051 bgp, p, pi);
d62a17ae 6052 }
6053 }
65efcfce 6054#endif
718e3744 6055
d62a17ae 6056 /* Nexthop reachability check. */
892fedb6 6057 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6058 && (safi == SAFI_UNICAST
6059 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6060
6061 struct bgp *bgp_nexthop = bgp;
6062
40381db7
DS
6063 if (pi->extra && pi->extra->bgp_orig)
6064 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6065
6066 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6067 afi, safi, pi, NULL,
654a5978 6068 0, p))
9bcb3eef 6069 bgp_path_info_set_flag(dest, pi,
18ee8310 6070 BGP_PATH_VALID);
d62a17ae 6071 else {
6072 if (BGP_DEBUG(nht, NHT)) {
6073 char buf1[INET6_ADDRSTRLEN];
6074 inet_ntop(p->family,
6075 &p->u.prefix, buf1,
6076 INET6_ADDRSTRLEN);
6077 zlog_debug(
6078 "%s(%s): Route not in table, not advertising",
15569c58 6079 __func__, buf1);
d62a17ae 6080 }
18ee8310 6081 bgp_path_info_unset_flag(
9bcb3eef 6082 dest, pi, BGP_PATH_VALID);
d62a17ae 6083 }
6084 } else {
6085 /* Delete the NHT structure if any, if we're
6086 * toggling between
6087 * enabling/disabling import check. We
6088 * deregister the route
6089 * from NHT to avoid overloading NHT and the
6090 * process interaction
6091 */
40381db7 6092 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6093 bgp_path_info_set_flag(dest, pi,
6094 BGP_PATH_VALID);
d62a17ae 6095 }
6096 /* Process change. */
40381db7 6097 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6098 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6099
6100 if (SAFI_UNICAST == safi
6101 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6102 || bgp->inst_type
6103 == BGP_INSTANCE_TYPE_DEFAULT)) {
6104 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6105 pi);
ddb5b488
PZ
6106 }
6107
9bcb3eef 6108 bgp_dest_unlock_node(dest);
d62a17ae 6109 aspath_unintern(&attr.aspath);
6110 return;
6111 }
718e3744 6112 }
718e3744 6113
d62a17ae 6114 /* Make new BGP info. */
6115 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6116 attr_new, dest);
d62a17ae 6117 /* Nexthop reachability check. */
892fedb6 6118 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6119 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6120 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6121 p))
9bcb3eef 6122 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6123 else {
6124 if (BGP_DEBUG(nht, NHT)) {
6125 char buf1[INET6_ADDRSTRLEN];
6126 inet_ntop(p->family, &p->u.prefix, buf1,
6127 INET6_ADDRSTRLEN);
6128 zlog_debug(
6129 "%s(%s): Route not in table, not advertising",
15569c58 6130 __func__, buf1);
d62a17ae 6131 }
9bcb3eef 6132 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6133 }
6134 } else {
6135 /* Delete the NHT structure if any, if we're toggling between
6136 * enabling/disabling import check. We deregister the route
6137 * from NHT to avoid overloading NHT and the process interaction
6138 */
6139 bgp_unlink_nexthop(new);
6140
9bcb3eef 6141 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6142 }
078430f6 6143
d62a17ae 6144 /* Aggregate address increment. */
6145 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6146
d62a17ae 6147 /* Register new BGP information. */
9bcb3eef 6148 bgp_path_info_add(dest, new);
718e3744 6149
d62a17ae 6150 /* route_node_get lock */
9bcb3eef 6151 bgp_dest_unlock_node(dest);
d62a17ae 6152
6153 /* Process change. */
9bcb3eef 6154 bgp_process(bgp, dest, afi, safi);
d62a17ae 6155
ddb5b488
PZ
6156 if (SAFI_UNICAST == safi
6157 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6158 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6159 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6160 }
6161
d62a17ae 6162 /* Unintern original. */
6163 aspath_unintern(&attr.aspath);
718e3744 6164}
6165
5f040085 6166void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6167 safi_t safi)
718e3744 6168{
9bcb3eef 6169 struct bgp_dest *dest;
40381db7 6170 struct bgp_path_info *pi;
718e3744 6171
9bcb3eef 6172 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6173
d62a17ae 6174 /* Check selected route and self inserted route. */
9bcb3eef 6175 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6176 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6177 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6178 break;
6179
6180 /* Withdraw static BGP route from routing table. */
40381db7 6181 if (pi) {
ddb5b488
PZ
6182 if (SAFI_UNICAST == safi
6183 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6184 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6185 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6186 }
40381db7
DS
6187 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6188 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6189 bgp_path_info_delete(dest, pi);
6190 bgp_process(bgp, dest, afi, safi);
d62a17ae 6191 }
718e3744 6192
d62a17ae 6193 /* Unlock bgp_node_lookup. */
9bcb3eef 6194 bgp_dest_unlock_node(dest);
718e3744 6195}
6196
137446f9
LB
6197/*
6198 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6199 */
5f040085 6200static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6201 afi_t afi, safi_t safi,
6202 struct prefix_rd *prd)
718e3744 6203{
9bcb3eef 6204 struct bgp_dest *dest;
40381db7 6205 struct bgp_path_info *pi;
718e3744 6206
9bcb3eef 6207 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6208
d62a17ae 6209 /* Check selected route and self inserted route. */
9bcb3eef 6210 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6211 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6212 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6213 break;
718e3744 6214
d62a17ae 6215 /* Withdraw static BGP route from routing table. */
40381db7 6216 if (pi) {
49e5a4a0 6217#ifdef ENABLE_BGP_VNC
d62a17ae 6218 rfapiProcessWithdraw(
40381db7 6219 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6220 1); /* Kill, since it is an administrative change */
65efcfce 6221#endif
ddb5b488
PZ
6222 if (SAFI_MPLS_VPN == safi
6223 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6224 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6225 }
40381db7 6226 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6227 bgp_path_info_delete(dest, pi);
6228 bgp_process(bgp, dest, afi, safi);
d62a17ae 6229 }
718e3744 6230
d62a17ae 6231 /* Unlock bgp_node_lookup. */
9bcb3eef 6232 bgp_dest_unlock_node(dest);
718e3744 6233}
6234
5f040085 6235static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6236 struct bgp_static *bgp_static, afi_t afi,
6237 safi_t safi)
137446f9 6238{
9bcb3eef 6239 struct bgp_dest *dest;
4b7e6066 6240 struct bgp_path_info *new;
d62a17ae 6241 struct attr *attr_new;
6242 struct attr attr = {0};
40381db7 6243 struct bgp_path_info *pi;
49e5a4a0 6244#ifdef ENABLE_BGP_VNC
d62a17ae 6245 mpls_label_t label = 0;
65efcfce 6246#endif
d7c0a89a 6247 uint32_t num_labels = 0;
137446f9 6248
d62a17ae 6249 assert(bgp_static);
137446f9 6250
b57ba6d2
MK
6251 if (bgp_static->label != MPLS_INVALID_LABEL)
6252 num_labels = 1;
9bcb3eef
DS
6253 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6254 &bgp_static->prd);
137446f9 6255
0f05ea43 6256 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6257
d62a17ae 6258 attr.nexthop = bgp_static->igpnexthop;
6259 attr.med = bgp_static->igpmetric;
6260 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6261
d62a17ae 6262 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6263 || (safi == SAFI_ENCAP)) {
6264 if (afi == AFI_IP) {
6265 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6266 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6267 }
6268 }
6269 if (afi == AFI_L2VPN) {
b04c1e99
IR
6270 if (bgp_static->gatewayIp.family == AF_INET) {
6271 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6272 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6273 &bgp_static->gatewayIp.u.prefix4,
6274 IPV4_MAX_BYTELEN);
b04c1e99
IR
6275 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6276 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6277 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6278 &bgp_static->gatewayIp.u.prefix6,
6279 IPV6_MAX_BYTELEN);
b04c1e99 6280 }
0a50c248 6281 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6282 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6283 struct bgp_encap_type_vxlan bet;
6006b807 6284 memset(&bet, 0, sizeof(bet));
3714a385 6285 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6286 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6287 }
6288 if (bgp_static->router_mac) {
6289 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6290 }
6291 }
6292 /* Apply route-map. */
6293 if (bgp_static->rmap.name) {
6294 struct attr attr_tmp = attr;
40381db7 6295 struct bgp_path_info rmap_path;
b68885f9 6296 route_map_result_t ret;
137446f9 6297
40381db7
DS
6298 rmap_path.peer = bgp->peer_self;
6299 rmap_path.attr = &attr_tmp;
137446f9 6300
d62a17ae 6301 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6302
1782514f 6303 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6304
d62a17ae 6305 bgp->peer_self->rmap_type = 0;
137446f9 6306
d62a17ae 6307 if (ret == RMAP_DENYMATCH) {
6308 /* Free uninterned attribute. */
6309 bgp_attr_flush(&attr_tmp);
137446f9 6310
d62a17ae 6311 /* Unintern original. */
6312 aspath_unintern(&attr.aspath);
6313 bgp_static_withdraw_safi(bgp, p, afi, safi,
6314 &bgp_static->prd);
6315 return;
6316 }
137446f9 6317
d62a17ae 6318 attr_new = bgp_attr_intern(&attr_tmp);
6319 } else {
6320 attr_new = bgp_attr_intern(&attr);
6321 }
137446f9 6322
9bcb3eef 6323 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6324 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6325 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6326 break;
6327
40381db7 6328 if (pi) {
40381db7 6329 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6330 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6331 bgp_dest_unlock_node(dest);
d62a17ae 6332 bgp_attr_unintern(&attr_new);
6333 aspath_unintern(&attr.aspath);
6334 return;
6335 } else {
6336 /* The attribute is changed. */
9bcb3eef 6337 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6338
6339 /* Rewrite BGP route information. */
40381db7 6340 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6341 bgp_path_info_restore(dest, pi);
d62a17ae 6342 else
40381db7
DS
6343 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6344 bgp_attr_unintern(&pi->attr);
6345 pi->attr = attr_new;
083ec940 6346 pi->uptime = monotime(NULL);
49e5a4a0 6347#ifdef ENABLE_BGP_VNC
40381db7
DS
6348 if (pi->extra)
6349 label = decode_label(&pi->extra->label[0]);
65efcfce 6350#endif
137446f9 6351
d62a17ae 6352 /* Process change. */
40381db7 6353 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6354 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6355
6356 if (SAFI_MPLS_VPN == safi
6357 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6358 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6359 }
49e5a4a0 6360#ifdef ENABLE_BGP_VNC
40381db7
DS
6361 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6362 pi->attr, afi, safi, pi->type,
6363 pi->sub_type, &label);
65efcfce 6364#endif
9bcb3eef 6365 bgp_dest_unlock_node(dest);
d62a17ae 6366 aspath_unintern(&attr.aspath);
6367 return;
6368 }
6369 }
137446f9
LB
6370
6371
d62a17ae 6372 /* Make new BGP info. */
6373 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6374 attr_new, dest);
1defdda8 6375 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6376 bgp_path_info_extra_get(new);
b57ba6d2
MK
6377 if (num_labels) {
6378 new->extra->label[0] = bgp_static->label;
6379 new->extra->num_labels = num_labels;
6380 }
49e5a4a0 6381#ifdef ENABLE_BGP_VNC
d62a17ae 6382 label = decode_label(&bgp_static->label);
65efcfce 6383#endif
137446f9 6384
d62a17ae 6385 /* Aggregate address increment. */
6386 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6387
d62a17ae 6388 /* Register new BGP information. */
9bcb3eef 6389 bgp_path_info_add(dest, new);
d62a17ae 6390 /* route_node_get lock */
9bcb3eef 6391 bgp_dest_unlock_node(dest);
137446f9 6392
d62a17ae 6393 /* Process change. */
9bcb3eef 6394 bgp_process(bgp, dest, afi, safi);
137446f9 6395
ddb5b488
PZ
6396 if (SAFI_MPLS_VPN == safi
6397 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6398 vpn_leak_to_vrf_update(bgp, new);
6399 }
49e5a4a0 6400#ifdef ENABLE_BGP_VNC
d62a17ae 6401 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6402 safi, new->type, new->sub_type, &label);
65efcfce
LB
6403#endif
6404
d62a17ae 6405 /* Unintern original. */
6406 aspath_unintern(&attr.aspath);
137446f9
LB
6407}
6408
718e3744 6409/* Configure static BGP network. When user don't run zebra, static
6410 route should be installed as valid. */
585f1adc
IR
6411static int bgp_static_set(struct vty *vty, const char *negate,
6412 const char *ip_str, afi_t afi, safi_t safi,
6413 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6414{
585f1adc
IR
6415 VTY_DECLVAR_CONTEXT(bgp, bgp);
6416 int ret;
d62a17ae 6417 struct prefix p;
6418 struct bgp_static *bgp_static;
9bcb3eef 6419 struct bgp_dest *dest;
d7c0a89a 6420 uint8_t need_update = 0;
d62a17ae 6421
585f1adc
IR
6422 /* Convert IP prefix string to struct prefix. */
6423 ret = str2prefix(ip_str, &p);
6424 if (!ret) {
6425 vty_out(vty, "%% Malformed prefix\n");
6426 return CMD_WARNING_CONFIG_FAILED;
6427 }
6428 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6429 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6430 return CMD_WARNING_CONFIG_FAILED;
6431 }
6432
d62a17ae 6433 apply_mask(&p);
718e3744 6434
e2a86ad9 6435 if (negate) {
718e3744 6436
e2a86ad9 6437 /* Set BGP static route configuration. */
9bcb3eef 6438 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6439
9bcb3eef 6440 if (!dest) {
585f1adc
IR
6441 vty_out(vty, "%% Can't find static route specified\n");
6442 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6443 }
6444
9bcb3eef 6445 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6446
e2a86ad9
DS
6447 if ((label_index != BGP_INVALID_LABEL_INDEX)
6448 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6449 vty_out(vty,
6450 "%% label-index doesn't match static route\n");
70d9b134 6451 bgp_dest_unlock_node(dest);
585f1adc 6452 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6453 }
d62a17ae 6454
e2a86ad9
DS
6455 if ((rmap && bgp_static->rmap.name)
6456 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6457 vty_out(vty,
6458 "%% route-map name doesn't match static route\n");
70d9b134 6459 bgp_dest_unlock_node(dest);
585f1adc 6460 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6461 }
718e3744 6462
e2a86ad9
DS
6463 /* Update BGP RIB. */
6464 if (!bgp_static->backdoor)
6465 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6466
e2a86ad9
DS
6467 /* Clear configuration. */
6468 bgp_static_free(bgp_static);
9bcb3eef
DS
6469 bgp_dest_set_bgp_static_info(dest, NULL);
6470 bgp_dest_unlock_node(dest);
6471 bgp_dest_unlock_node(dest);
e2a86ad9 6472 } else {
718e3744 6473
e2a86ad9 6474 /* Set BGP static route configuration. */
9bcb3eef
DS
6475 dest = bgp_node_get(bgp->route[afi][safi], &p);
6476 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6477 if (bgp_static) {
e2a86ad9 6478 /* Configuration change. */
e2a86ad9
DS
6479 /* Label index cannot be changed. */
6480 if (bgp_static->label_index != label_index) {
585f1adc
IR
6481 vty_out(vty, "%% cannot change label-index\n");
6482 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6483 }
d62a17ae 6484
e2a86ad9 6485 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6486 if (bgp_static->valid
6487 && bgp_static->backdoor != backdoor)
e2a86ad9 6488 need_update = 1;
718e3744 6489
e2a86ad9 6490 bgp_static->backdoor = backdoor;
718e3744 6491
e2a86ad9 6492 if (rmap) {
0a22ddfb
QY
6493 XFREE(MTYPE_ROUTE_MAP_NAME,
6494 bgp_static->rmap.name);
b4897fa5 6495 route_map_counter_decrement(
6496 bgp_static->rmap.map);
e2a86ad9
DS
6497 bgp_static->rmap.name =
6498 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6499 bgp_static->rmap.map =
6500 route_map_lookup_by_name(rmap);
b4897fa5 6501 route_map_counter_increment(
6502 bgp_static->rmap.map);
e2a86ad9 6503 } else {
0a22ddfb
QY
6504 XFREE(MTYPE_ROUTE_MAP_NAME,
6505 bgp_static->rmap.name);
b4897fa5 6506 route_map_counter_decrement(
6507 bgp_static->rmap.map);
e2a86ad9
DS
6508 bgp_static->rmap.map = NULL;
6509 bgp_static->valid = 0;
6510 }
9bcb3eef 6511 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6512 } else {
6513 /* New configuration. */
6514 bgp_static = bgp_static_new();
6515 bgp_static->backdoor = backdoor;
6516 bgp_static->valid = 0;
6517 bgp_static->igpmetric = 0;
975a328e 6518 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6519 bgp_static->label_index = label_index;
718e3744 6520
e2a86ad9 6521 if (rmap) {
0a22ddfb
QY
6522 XFREE(MTYPE_ROUTE_MAP_NAME,
6523 bgp_static->rmap.name);
b4897fa5 6524 route_map_counter_decrement(
6525 bgp_static->rmap.map);
e2a86ad9
DS
6526 bgp_static->rmap.name =
6527 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6528 bgp_static->rmap.map =
6529 route_map_lookup_by_name(rmap);
b4897fa5 6530 route_map_counter_increment(
6531 bgp_static->rmap.map);
e2a86ad9 6532 }
9bcb3eef 6533 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6534 }
d62a17ae 6535
e2a86ad9
DS
6536 bgp_static->valid = 1;
6537 if (need_update)
6538 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6539
e2a86ad9
DS
6540 if (!bgp_static->backdoor)
6541 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6542 }
d62a17ae 6543
585f1adc 6544 return CMD_SUCCESS;
d62a17ae 6545}
6546
6547void bgp_static_add(struct bgp *bgp)
6548{
6549 afi_t afi;
6550 safi_t safi;
9bcb3eef
DS
6551 struct bgp_dest *dest;
6552 struct bgp_dest *rm;
d62a17ae 6553 struct bgp_table *table;
6554 struct bgp_static *bgp_static;
6555
47fc6261 6556 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6557 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6558 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6559 dest = bgp_route_next(dest)) {
6560 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6561 continue;
ea47320b 6562
05c7a1cc
QY
6563 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6564 || (safi == SAFI_EVPN)) {
9bcb3eef 6565 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6566
6567 for (rm = bgp_table_top(table); rm;
6568 rm = bgp_route_next(rm)) {
a78beeb5 6569 bgp_static =
9bcb3eef 6570 bgp_dest_get_bgp_static_info(
5a8ba9fc 6571 rm);
9bcb3eef
DS
6572 bgp_static_update_safi(
6573 bgp, bgp_dest_get_prefix(rm),
6574 bgp_static, afi, safi);
d62a17ae 6575 }
05c7a1cc 6576 } else {
5a8ba9fc 6577 bgp_static_update(
9bcb3eef
DS
6578 bgp, bgp_dest_get_prefix(dest),
6579 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6580 safi);
ea47320b 6581 }
05c7a1cc 6582 }
47fc6261 6583 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6584}
6585
718e3744 6586/* Called from bgp_delete(). Delete all static routes from the BGP
6587 instance. */
d62a17ae 6588void bgp_static_delete(struct bgp *bgp)
6589{
6590 afi_t afi;
6591 safi_t safi;
9bcb3eef
DS
6592 struct bgp_dest *dest;
6593 struct bgp_dest *rm;
d62a17ae 6594 struct bgp_table *table;
6595 struct bgp_static *bgp_static;
6596
05c7a1cc 6597 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6598 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6599 dest = bgp_route_next(dest)) {
6600 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6601 continue;
ea47320b 6602
05c7a1cc
QY
6603 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6604 || (safi == SAFI_EVPN)) {
9bcb3eef 6605 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6606
6607 for (rm = bgp_table_top(table); rm;
6608 rm = bgp_route_next(rm)) {
a78beeb5 6609 bgp_static =
9bcb3eef 6610 bgp_dest_get_bgp_static_info(
5a8ba9fc 6611 rm);
c7d14ba6
PG
6612 if (!bgp_static)
6613 continue;
6614
05c7a1cc 6615 bgp_static_withdraw_safi(
9bcb3eef 6616 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6617 AFI_IP, safi,
6618 (struct prefix_rd *)
9bcb3eef
DS
6619 bgp_dest_get_prefix(
6620 dest));
ea47320b 6621 bgp_static_free(bgp_static);
811c6797 6622 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6623 NULL);
811c6797 6624 bgp_dest_unlock_node(rm);
d62a17ae 6625 }
05c7a1cc 6626 } else {
9bcb3eef 6627 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6628 bgp_static_withdraw(bgp,
9bcb3eef 6629 bgp_dest_get_prefix(dest),
b54892e0 6630 afi, safi);
05c7a1cc 6631 bgp_static_free(bgp_static);
9bcb3eef
DS
6632 bgp_dest_set_bgp_static_info(dest, NULL);
6633 bgp_dest_unlock_node(dest);
ea47320b 6634 }
05c7a1cc 6635 }
d62a17ae 6636}
6637
6638void bgp_static_redo_import_check(struct bgp *bgp)
6639{
6640 afi_t afi;
6641 safi_t safi;
9bcb3eef
DS
6642 struct bgp_dest *dest;
6643 struct bgp_dest *rm;
d62a17ae 6644 struct bgp_table *table;
6645 struct bgp_static *bgp_static;
6646
6647 /* Use this flag to force reprocessing of the route */
892fedb6 6648 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6649 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6650 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6651 dest = bgp_route_next(dest)) {
6652 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6653 continue;
ea47320b 6654
05c7a1cc
QY
6655 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6656 || (safi == SAFI_EVPN)) {
9bcb3eef 6657 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6658
6659 for (rm = bgp_table_top(table); rm;
6660 rm = bgp_route_next(rm)) {
a78beeb5 6661 bgp_static =
9bcb3eef 6662 bgp_dest_get_bgp_static_info(
5a8ba9fc 6663 rm);
9bcb3eef
DS
6664 bgp_static_update_safi(
6665 bgp, bgp_dest_get_prefix(rm),
6666 bgp_static, afi, safi);
d62a17ae 6667 }
05c7a1cc 6668 } else {
9bcb3eef
DS
6669 bgp_static = bgp_dest_get_bgp_static_info(dest);
6670 bgp_static_update(bgp,
6671 bgp_dest_get_prefix(dest),
6672 bgp_static, afi, safi);
ea47320b 6673 }
05c7a1cc
QY
6674 }
6675 }
892fedb6 6676 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6677}
6678
6679static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6680 safi_t safi)
6681{
6682 struct bgp_table *table;
9bcb3eef 6683 struct bgp_dest *dest;
40381db7 6684 struct bgp_path_info *pi;
d62a17ae 6685
dfb6fd1d
NT
6686 /* Do not install the aggregate route if BGP is in the
6687 * process of termination.
6688 */
892fedb6
DA
6689 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6690 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6691 return;
6692
d62a17ae 6693 table = bgp->rib[afi][safi];
9bcb3eef
DS
6694 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6695 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6696 if (pi->peer == bgp->peer_self
6697 && ((pi->type == ZEBRA_ROUTE_BGP
6698 && pi->sub_type == BGP_ROUTE_STATIC)
6699 || (pi->type != ZEBRA_ROUTE_BGP
6700 && pi->sub_type
d62a17ae 6701 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6702 bgp_aggregate_decrement(
6703 bgp, bgp_dest_get_prefix(dest), pi, afi,
6704 safi);
40381db7 6705 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6706 bgp_path_info_delete(dest, pi);
6707 bgp_process(bgp, dest, afi, safi);
d62a17ae 6708 }
6709 }
6710 }
ad4cbda1 6711}
6712
6713/*
6714 * Purge all networks and redistributed routes from routing table.
6715 * Invoked upon the instance going down.
6716 */
d62a17ae 6717void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6718{
d62a17ae 6719 afi_t afi;
6720 safi_t safi;
ad4cbda1 6721
05c7a1cc
QY
6722 FOREACH_AFI_SAFI (afi, safi)
6723 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6724}
6725
137446f9
LB
6726/*
6727 * gpz 110624
6728 * Currently this is used to set static routes for VPN and ENCAP.
6729 * I think it can probably be factored with bgp_static_set.
6730 */
d62a17ae 6731int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6732 const char *ip_str, const char *rd_str,
6733 const char *label_str, const char *rmap_str,
6734 int evpn_type, const char *esi, const char *gwip,
6735 const char *ethtag, const char *routermac)
6736{
6737 VTY_DECLVAR_CONTEXT(bgp, bgp);
6738 int ret;
6739 struct prefix p;
6740 struct prefix_rd prd;
9bcb3eef
DS
6741 struct bgp_dest *pdest;
6742 struct bgp_dest *dest;
d62a17ae 6743 struct bgp_table *table;
6744 struct bgp_static *bgp_static;
6745 mpls_label_t label = MPLS_INVALID_LABEL;
6746 struct prefix gw_ip;
6747
6748 /* validate ip prefix */
6749 ret = str2prefix(ip_str, &p);
6750 if (!ret) {
6751 vty_out(vty, "%% Malformed prefix\n");
6752 return CMD_WARNING_CONFIG_FAILED;
6753 }
6754 apply_mask(&p);
6755 if ((afi == AFI_L2VPN)
6756 && (bgp_build_evpn_prefix(evpn_type,
6757 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6758 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6759 return CMD_WARNING_CONFIG_FAILED;
6760 }
718e3744 6761
d62a17ae 6762 ret = str2prefix_rd(rd_str, &prd);
6763 if (!ret) {
6764 vty_out(vty, "%% Malformed rd\n");
6765 return CMD_WARNING_CONFIG_FAILED;
6766 }
718e3744 6767
d62a17ae 6768 if (label_str) {
6769 unsigned long label_val;
6770 label_val = strtoul(label_str, NULL, 10);
6771 encode_label(label_val, &label);
6772 }
9bedbb1e 6773
d62a17ae 6774 if (safi == SAFI_EVPN) {
6775 if (esi && str2esi(esi, NULL) == 0) {
6776 vty_out(vty, "%% Malformed ESI\n");
6777 return CMD_WARNING_CONFIG_FAILED;
6778 }
6779 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6780 vty_out(vty, "%% Malformed Router MAC\n");
6781 return CMD_WARNING_CONFIG_FAILED;
6782 }
6783 if (gwip) {
6006b807 6784 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6785 ret = str2prefix(gwip, &gw_ip);
6786 if (!ret) {
6787 vty_out(vty, "%% Malformed GatewayIp\n");
6788 return CMD_WARNING_CONFIG_FAILED;
6789 }
6790 if ((gw_ip.family == AF_INET
3714a385 6791 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6792 (struct prefix_evpn *)&p))
6793 || (gw_ip.family == AF_INET6
3714a385 6794 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6795 (struct prefix_evpn *)&p))) {
6796 vty_out(vty,
6797 "%% GatewayIp family differs with IP prefix\n");
6798 return CMD_WARNING_CONFIG_FAILED;
6799 }
6800 }
6801 }
9bcb3eef
DS
6802 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6803 if (!bgp_dest_has_bgp_path_info_data(pdest))
6804 bgp_dest_set_bgp_table_info(pdest,
67009e22 6805 bgp_table_init(bgp, afi, safi));
9bcb3eef 6806 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6807
9bcb3eef 6808 dest = bgp_node_get(table, &p);
d62a17ae 6809
9bcb3eef 6810 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6811 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6812 bgp_dest_unlock_node(dest);
d62a17ae 6813 } else {
6814 /* New configuration. */
6815 bgp_static = bgp_static_new();
6816 bgp_static->backdoor = 0;
6817 bgp_static->valid = 0;
6818 bgp_static->igpmetric = 0;
975a328e 6819 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6820 bgp_static->label = label;
6821 bgp_static->prd = prd;
6822
6823 if (rmap_str) {
0a22ddfb 6824 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6825 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6826 bgp_static->rmap.name =
6827 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6828 bgp_static->rmap.map =
6829 route_map_lookup_by_name(rmap_str);
b4897fa5 6830 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6831 }
718e3744 6832
d62a17ae 6833 if (safi == SAFI_EVPN) {
6834 if (esi) {
6835 bgp_static->eth_s_id =
6836 XCALLOC(MTYPE_ATTR,
0a50c248 6837 sizeof(esi_t));
d62a17ae 6838 str2esi(esi, bgp_static->eth_s_id);
6839 }
6840 if (routermac) {
6841 bgp_static->router_mac =
28328ea9 6842 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6843 (void)prefix_str2mac(routermac,
6844 bgp_static->router_mac);
d62a17ae 6845 }
6846 if (gwip)
6847 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6848 }
9bcb3eef 6849 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6850
d62a17ae 6851 bgp_static->valid = 1;
6852 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6853 }
718e3744 6854
d62a17ae 6855 return CMD_SUCCESS;
718e3744 6856}
6857
6858/* Configure static BGP network. */
d62a17ae 6859int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6860 const char *ip_str, const char *rd_str,
6861 const char *label_str, int evpn_type, const char *esi,
6862 const char *gwip, const char *ethtag)
6863{
6864 VTY_DECLVAR_CONTEXT(bgp, bgp);
6865 int ret;
6866 struct prefix p;
6867 struct prefix_rd prd;
9bcb3eef
DS
6868 struct bgp_dest *pdest;
6869 struct bgp_dest *dest;
d62a17ae 6870 struct bgp_table *table;
6871 struct bgp_static *bgp_static;
6872 mpls_label_t label = MPLS_INVALID_LABEL;
6873
6874 /* Convert IP prefix string to struct prefix. */
6875 ret = str2prefix(ip_str, &p);
6876 if (!ret) {
6877 vty_out(vty, "%% Malformed prefix\n");
6878 return CMD_WARNING_CONFIG_FAILED;
6879 }
6880 apply_mask(&p);
6881 if ((afi == AFI_L2VPN)
6882 && (bgp_build_evpn_prefix(evpn_type,
6883 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6884 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6885 return CMD_WARNING_CONFIG_FAILED;
6886 }
6887 ret = str2prefix_rd(rd_str, &prd);
6888 if (!ret) {
6889 vty_out(vty, "%% Malformed rd\n");
6890 return CMD_WARNING_CONFIG_FAILED;
6891 }
718e3744 6892
d62a17ae 6893 if (label_str) {
6894 unsigned long label_val;
6895 label_val = strtoul(label_str, NULL, 10);
6896 encode_label(label_val, &label);
6897 }
718e3744 6898
9bcb3eef
DS
6899 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6900 if (!bgp_dest_has_bgp_path_info_data(pdest))
6901 bgp_dest_set_bgp_table_info(pdest,
67009e22 6902 bgp_table_init(bgp, afi, safi));
d62a17ae 6903 else
9bcb3eef
DS
6904 bgp_dest_unlock_node(pdest);
6905 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6906
9bcb3eef 6907 dest = bgp_node_lookup(table, &p);
6b0655a2 6908
9bcb3eef 6909 if (dest) {
d62a17ae 6910 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6911
9bcb3eef 6912 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6913 bgp_static_free(bgp_static);
9bcb3eef
DS
6914 bgp_dest_set_bgp_static_info(dest, NULL);
6915 bgp_dest_unlock_node(dest);
6916 bgp_dest_unlock_node(dest);
d62a17ae 6917 } else
6918 vty_out(vty, "%% Can't find the route\n");
6919
6920 return CMD_SUCCESS;
6921}
6922
6923static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6924 const char *rmap_name)
6925{
6926 VTY_DECLVAR_CONTEXT(bgp, bgp);
6927 struct bgp_rmap *rmap;
6928
6929 rmap = &bgp->table_map[afi][safi];
6930 if (rmap_name) {
0a22ddfb 6931 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6932 route_map_counter_decrement(rmap->map);
d62a17ae 6933 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6934 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6935 route_map_counter_increment(rmap->map);
d62a17ae 6936 } else {
0a22ddfb 6937 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6938 route_map_counter_decrement(rmap->map);
d62a17ae 6939 rmap->map = NULL;
6940 }
73ac8160 6941
d62a17ae 6942 if (bgp_fibupd_safi(safi))
6943 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6944
d62a17ae 6945 return CMD_SUCCESS;
73ac8160
DS
6946}
6947
d62a17ae 6948static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6949 const char *rmap_name)
73ac8160 6950{
d62a17ae 6951 VTY_DECLVAR_CONTEXT(bgp, bgp);
6952 struct bgp_rmap *rmap;
73ac8160 6953
d62a17ae 6954 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6955 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6956 route_map_counter_decrement(rmap->map);
d62a17ae 6957 rmap->map = NULL;
73ac8160 6958
d62a17ae 6959 if (bgp_fibupd_safi(safi))
6960 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6961
d62a17ae 6962 return CMD_SUCCESS;
73ac8160
DS
6963}
6964
2b791107 6965void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6966 safi_t safi)
73ac8160 6967{
d62a17ae 6968 if (bgp->table_map[afi][safi].name) {
d62a17ae 6969 vty_out(vty, " table-map %s\n",
6970 bgp->table_map[afi][safi].name);
6971 }
73ac8160
DS
6972}
6973
73ac8160
DS
6974DEFUN (bgp_table_map,
6975 bgp_table_map_cmd,
6976 "table-map WORD",
6977 "BGP table to RIB route download filter\n"
6978 "Name of the route map\n")
6979{
d62a17ae 6980 int idx_word = 1;
6981 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6982 argv[idx_word]->arg);
73ac8160
DS
6983}
6984DEFUN (no_bgp_table_map,
6985 no_bgp_table_map_cmd,
6986 "no table-map WORD",
3a2d747c 6987 NO_STR
73ac8160
DS
6988 "BGP table to RIB route download filter\n"
6989 "Name of the route map\n")
6990{
d62a17ae 6991 int idx_word = 2;
6992 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6993 argv[idx_word]->arg);
73ac8160
DS
6994}
6995
585f1adc
IR
6996DEFPY(bgp_network,
6997 bgp_network_cmd,
6998 "[no] network \
6999 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7000 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7001 backdoor$backdoor}]",
7002 NO_STR
7003 "Specify a network to announce via BGP\n"
7004 "IPv4 prefix\n"
7005 "Network number\n"
7006 "Network mask\n"
7007 "Network mask\n"
7008 "Route-map to modify the attributes\n"
7009 "Name of the route map\n"
7010 "Label index to associate with the prefix\n"
7011 "Label index value\n"
7012 "Specify a BGP backdoor route\n")
7013{
7014 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7015
7016 if (address_str) {
7017 int ret;
718e3744 7018
e2a86ad9 7019 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7020 addr_prefix_str,
7021 sizeof(addr_prefix_str));
e2a86ad9
DS
7022 if (!ret) {
7023 vty_out(vty, "%% Inconsistent address and mask\n");
7024 return CMD_WARNING_CONFIG_FAILED;
7025 }
d62a17ae 7026 }
718e3744 7027
585f1adc
IR
7028 return bgp_static_set(
7029 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7030 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7031 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7032}
7033
585f1adc
IR
7034DEFPY(ipv6_bgp_network,
7035 ipv6_bgp_network_cmd,
7036 "[no] network X:X::X:X/M$prefix \
70dd370f 7037 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7038 NO_STR
7039 "Specify a network to announce via BGP\n"
7040 "IPv6 prefix\n"
7041 "Route-map to modify the attributes\n"
7042 "Name of the route map\n"
7043 "Label index to associate with the prefix\n"
7044 "Label index value\n")
37a87b8f 7045{
585f1adc
IR
7046 return bgp_static_set(
7047 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7048 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7049}
7050
d62a17ae 7051static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7052{
d62a17ae 7053 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7054}
7055
d62a17ae 7056static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7057{
365ab2e7
RZ
7058 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7059 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7060 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7061 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7062 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7063}
718e3744 7064
365ab2e7
RZ
7065/**
7066 * Helper function to avoid repeated code: prepare variables for a
7067 * `route_map_apply` call.
7068 *
7069 * \returns `true` on route map match, otherwise `false`.
7070 */
7071static bool aggr_suppress_map_test(struct bgp *bgp,
7072 struct bgp_aggregate *aggregate,
7073 struct bgp_path_info *pi)
7074{
7075 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7076 route_map_result_t rmr = RMAP_DENYMATCH;
7077 struct bgp_path_info rmap_path = {};
7078 struct attr attr = {};
7079
7080 /* No route map entries created, just don't match. */
7081 if (aggregate->suppress_map == NULL)
7082 return false;
7083
7084 /* Call route map matching and return result. */
7085 attr.aspath = aspath_empty();
7086 rmap_path.peer = bgp->peer_self;
7087 rmap_path.attr = &attr;
7088
7089 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7090 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7091 bgp->peer_self->rmap_type = 0;
7092
7093 bgp_attr_flush(&attr);
afb254d7 7094 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7095
7096 return rmr == RMAP_PERMITMATCH;
7097}
7098
4056a5f6
RZ
7099/** Test whether the aggregation has suppressed this path or not. */
7100static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7101 struct bgp_path_info *pi)
7102{
7103 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7104 return false;
7105
7106 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7107}
7108
7109/**
7110 * Suppress this path and keep the reference.
7111 *
7112 * \returns `true` if needs processing otherwise `false`.
7113 */
7114static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7115 struct bgp_path_info *pi)
7116{
7117 struct bgp_path_info_extra *pie;
7118
7119 /* Path is already suppressed by this aggregation. */
7120 if (aggr_suppress_exists(aggregate, pi))
7121 return false;
7122
7123 pie = bgp_path_info_extra_get(pi);
7124
7125 /* This is the first suppression, allocate memory and list it. */
7126 if (pie->aggr_suppressors == NULL)
7127 pie->aggr_suppressors = list_new();
7128
7129 listnode_add(pie->aggr_suppressors, aggregate);
7130
7131 /* Only mark for processing if suppressed. */
7132 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7133 if (BGP_DEBUG(update, UPDATE_OUT))
7134 zlog_debug("aggregate-address suppressing: %pFX",
7135 bgp_dest_get_prefix(pi->net));
7136
4056a5f6
RZ
7137 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7138 return true;
7139 }
7140
7141 return false;
7142}
7143
7144/**
7145 * Unsuppress this path and remove the reference.
7146 *
7147 * \returns `true` if needs processing otherwise `false`.
7148 */
7149static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7150 struct bgp_path_info *pi)
7151{
7152 /* Path wasn't suppressed. */
7153 if (!aggr_suppress_exists(aggregate, pi))
7154 return false;
7155
7156 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7157
7158 /* Unsuppress and free extra memory if last item. */
7159 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7160 if (BGP_DEBUG(update, UPDATE_OUT))
7161 zlog_debug("aggregate-address unsuppressing: %pFX",
7162 bgp_dest_get_prefix(pi->net));
7163
4056a5f6
RZ
7164 list_delete(&pi->extra->aggr_suppressors);
7165 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7166 return true;
7167 }
7168
7169 return false;
7170}
7171
3dc339cd
DA
7172static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7173 struct aspath *aspath,
7174 struct community *comm,
7175 struct ecommunity *ecomm,
7176 struct lcommunity *lcomm)
eaaf8adb
DS
7177{
7178 static struct aspath *ae = NULL;
7179
7180 if (!ae)
7181 ae = aspath_empty();
7182
40381db7 7183 if (!pi)
3dc339cd 7184 return false;
eaaf8adb 7185
40381db7 7186 if (origin != pi->attr->origin)
3dc339cd 7187 return false;
eaaf8adb 7188
40381db7 7189 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7190 return false;
29f7d023 7191
9a706b42 7192 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7193 return false;
eaaf8adb 7194
b53e67a3 7195 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7196 return false;
eaaf8adb 7197
1bcf3a96 7198 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7199 return false;
dd18c5a9 7200
40381db7 7201 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7202 return false;
7ce8a8e0 7203
3dc339cd 7204 return true;
eaaf8adb
DS
7205}
7206
5f040085
DS
7207static void bgp_aggregate_install(
7208 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7209 uint8_t origin, struct aspath *aspath, struct community *community,
7210 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7211 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7212{
9bcb3eef 7213 struct bgp_dest *dest;
c701010e 7214 struct bgp_table *table;
6f94b685 7215 struct bgp_path_info *pi, *orig, *new;
20894f50 7216 struct attr *attr;
c701010e
DS
7217
7218 table = bgp->rib[afi][safi];
7219
9bcb3eef 7220 dest = bgp_node_get(table, p);
eaaf8adb 7221
9bcb3eef 7222 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7223 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7224 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7225 break;
7226
6aabb15d
RZ
7227 /*
7228 * If we have paths with different MEDs, then don't install
7229 * (or uninstall) the aggregate route.
7230 */
7231 if (aggregate->match_med && aggregate->med_mismatched)
7232 goto uninstall_aggregate_route;
7233
c701010e 7234 if (aggregate->count > 0) {
eaaf8adb
DS
7235 /*
7236 * If the aggregate information has not changed
7237 * no need to re-install it again.
7238 */
6f94b685 7239 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7240 ecommunity, lcommunity)) {
9bcb3eef 7241 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7242
7243 if (aspath)
7244 aspath_free(aspath);
7245 if (community)
3c1f53de 7246 community_free(&community);
3da2cc32
DS
7247 if (ecommunity)
7248 ecommunity_free(&ecommunity);
dd18c5a9
DS
7249 if (lcommunity)
7250 lcommunity_free(&lcommunity);
eaaf8adb
DS
7251
7252 return;
7253 }
7254
7255 /*
7256 * Mark the old as unusable
7257 */
40381db7 7258 if (pi)
9bcb3eef 7259 bgp_path_info_delete(dest, pi);
eaaf8adb 7260
20894f50
DA
7261 attr = bgp_attr_aggregate_intern(
7262 bgp, origin, aspath, community, ecommunity, lcommunity,
7263 aggregate, atomic_aggregate, p);
7264
7265 if (!attr) {
7266 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7267 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7268 zlog_debug("%s: %pFX null attribute", __func__,
7269 p);
20894f50
DA
7270 return;
7271 }
7272
3da2cc32 7273 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7274 bgp->peer_self, attr, dest);
20894f50 7275
1defdda8 7276 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7277
9bcb3eef
DS
7278 bgp_path_info_add(dest, new);
7279 bgp_process(bgp, dest, afi, safi);
c701010e 7280 } else {
6aabb15d 7281 uninstall_aggregate_route:
6f94b685 7282 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7283 if (pi->peer == bgp->peer_self
7284 && pi->type == ZEBRA_ROUTE_BGP
7285 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7286 break;
7287
7288 /* Withdraw static BGP route from routing table. */
40381db7 7289 if (pi) {
9bcb3eef
DS
7290 bgp_path_info_delete(dest, pi);
7291 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7292 }
7293 }
7294
9bcb3eef 7295 bgp_dest_unlock_node(dest);
c701010e
DS
7296}
7297
6aabb15d
RZ
7298/**
7299 * Check if the current path has different MED than other known paths.
7300 *
7301 * \returns `true` if the MED matched the others else `false`.
7302 */
7303static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7304 struct bgp *bgp, struct bgp_path_info *pi)
7305{
7306 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7307
7308 /* This is the first route being analyzed. */
7309 if (!aggregate->med_initialized) {
7310 aggregate->med_initialized = true;
7311 aggregate->med_mismatched = false;
7312 aggregate->med_matched_value = cur_med;
7313 } else {
7314 /* Check if routes with different MED showed up. */
7315 if (cur_med != aggregate->med_matched_value)
7316 aggregate->med_mismatched = true;
7317 }
7318
7319 return !aggregate->med_mismatched;
7320}
7321
7322/**
7323 * Initializes and tests all routes in the aggregate address path for MED
7324 * values.
7325 *
7326 * \returns `true` if all MEDs are the same otherwise `false`.
7327 */
7328static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7329 struct bgp *bgp, const struct prefix *p,
7330 afi_t afi, safi_t safi)
7331{
7332 struct bgp_table *table = bgp->rib[afi][safi];
7333 const struct prefix *dest_p;
7334 struct bgp_dest *dest, *top;
7335 struct bgp_path_info *pi;
7336 bool med_matched = true;
7337
7338 aggregate->med_initialized = false;
7339
7340 top = bgp_node_get(table, p);
7341 for (dest = bgp_node_get(table, p); dest;
7342 dest = bgp_route_next_until(dest, top)) {
7343 dest_p = bgp_dest_get_prefix(dest);
7344 if (dest_p->prefixlen <= p->prefixlen)
7345 continue;
7346
7347 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7348 if (BGP_PATH_HOLDDOWN(pi))
7349 continue;
7350 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7351 continue;
7352 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7353 med_matched = false;
7354 break;
7355 }
7356 }
7357 if (!med_matched)
7358 break;
7359 }
7360 bgp_dest_unlock_node(top);
7361
7362 return med_matched;
7363}
7364
7365/**
7366 * Toggles the route suppression status for this aggregate address
7367 * configuration.
7368 */
4056a5f6
RZ
7369void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7370 struct bgp *bgp, const struct prefix *p,
7371 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7372{
7373 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7374 const struct prefix *dest_p;
7375 struct bgp_dest *dest, *top;
7376 struct bgp_path_info *pi;
7377 bool toggle_suppression;
7378
7379 /* We've found a different MED we must revert any suppressed routes. */
7380 top = bgp_node_get(table, p);
7381 for (dest = bgp_node_get(table, p); dest;
7382 dest = bgp_route_next_until(dest, top)) {
7383 dest_p = bgp_dest_get_prefix(dest);
7384 if (dest_p->prefixlen <= p->prefixlen)
7385 continue;
7386
7387 toggle_suppression = false;
7388 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7389 if (BGP_PATH_HOLDDOWN(pi))
7390 continue;
7391 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7392 continue;
7393
6aabb15d
RZ
7394 /* We are toggling suppression back. */
7395 if (suppress) {
6aabb15d 7396 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7397 if (aggr_suppress_path(aggregate, pi))
7398 toggle_suppression = true;
6aabb15d
RZ
7399 continue;
7400 }
7401
6aabb15d 7402 /* Install route if there is no more suppression. */
4056a5f6 7403 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7404 toggle_suppression = true;
6aabb15d
RZ
7405 }
7406
7407 if (toggle_suppression)
7408 bgp_process(bgp, dest, afi, safi);
7409 }
7410 bgp_dest_unlock_node(top);
7411}
7412
7413/**
7414 * Aggregate address MED matching incremental test: this function is called
7415 * when the initial aggregation occurred and we are only testing a single
7416 * new path.
7417 *
7418 * In addition to testing and setting the MED validity it also installs back
7419 * suppressed routes (if summary is configured).
7420 *
7421 * Must not be called in `bgp_aggregate_route`.
7422 */
7423static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7424 struct bgp *bgp, const struct prefix *p,
7425 afi_t afi, safi_t safi,
7426 struct bgp_path_info *pi, bool is_adding)
7427{
7428 /* MED matching disabled. */
7429 if (!aggregate->match_med)
7430 return;
7431
7432 /* Aggregation with different MED, nothing to do. */
7433 if (aggregate->med_mismatched)
7434 return;
7435
7436 /*
7437 * Test the current entry:
7438 *
7439 * is_adding == true: if the new entry doesn't match then we must
7440 * install all suppressed routes.
7441 *
7442 * is_adding == false: if the entry being removed was the last
7443 * unmatching entry then we can suppress all routes.
7444 */
7445 if (!is_adding) {
7446 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7447 && aggregate->summary_only)
7448 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7449 safi, true);
7450 } else
7451 bgp_aggregate_med_match(aggregate, bgp, pi);
7452
7453 /* No mismatches, just quit. */
7454 if (!aggregate->med_mismatched)
7455 return;
7456
7457 /* Route summarization is disabled. */
7458 if (!aggregate->summary_only)
7459 return;
7460
7461 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7462}
7463
b5d58c32 7464/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7465void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7466 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7467{
7468 struct bgp_table *table;
9bcb3eef
DS
7469 struct bgp_dest *top;
7470 struct bgp_dest *dest;
d7c0a89a 7471 uint8_t origin;
d62a17ae 7472 struct aspath *aspath = NULL;
d62a17ae 7473 struct community *community = NULL;
3da2cc32 7474 struct ecommunity *ecommunity = NULL;
dd18c5a9 7475 struct lcommunity *lcommunity = NULL;
40381db7 7476 struct bgp_path_info *pi;
d62a17ae 7477 unsigned long match = 0;
d7c0a89a 7478 uint8_t atomic_aggregate = 0;
d62a17ae 7479
9f822fa2
S
7480 /* If the bgp instance is being deleted or self peer is deleted
7481 * then do not create aggregate route
7482 */
892fedb6
DA
7483 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7484 || (bgp->peer_self == NULL))
9f822fa2
S
7485 return;
7486
6aabb15d
RZ
7487 /* Initialize and test routes for MED difference. */
7488 if (aggregate->match_med)
7489 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7490
4056a5f6
RZ
7491 /*
7492 * Reset aggregate count: we might've been called from route map
7493 * update so in that case we must retest all more specific routes.
7494 *
7495 * \see `bgp_route_map_process_update`.
7496 */
7497 aggregate->count = 0;
7498 aggregate->incomplete_origin_count = 0;
7499 aggregate->incomplete_origin_count = 0;
7500 aggregate->egp_origin_count = 0;
7501
d62a17ae 7502 /* ORIGIN attribute: If at least one route among routes that are
7503 aggregated has ORIGIN with the value INCOMPLETE, then the
7504 aggregated route must have the ORIGIN attribute with the value
7505 INCOMPLETE. Otherwise, if at least one route among routes that
7506 are aggregated has ORIGIN with the value EGP, then the aggregated
7507 route must have the origin attribute with the value EGP. In all
7508 other case the value of the ORIGIN attribute of the aggregated
7509 route is INTERNAL. */
7510 origin = BGP_ORIGIN_IGP;
718e3744 7511
d62a17ae 7512 table = bgp->rib[afi][safi];
718e3744 7513
d62a17ae 7514 top = bgp_node_get(table, p);
9bcb3eef
DS
7515 for (dest = bgp_node_get(table, p); dest;
7516 dest = bgp_route_next_until(dest, top)) {
7517 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7518
9bcb3eef 7519 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7520 continue;
d62a17ae 7521
a77e2f4b
S
7522 /* If suppress fib is enabled and route not installed
7523 * in FIB, skip the route
7524 */
7525 if (!bgp_check_advertise(bgp, dest))
7526 continue;
7527
c2ff8b3e 7528 match = 0;
d62a17ae 7529
9bcb3eef 7530 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7531 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7532 continue;
718e3744 7533
40381db7 7534 if (pi->attr->flag
c2ff8b3e
DS
7535 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7536 atomic_aggregate = 1;
d62a17ae 7537
40381db7 7538 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7539 continue;
d62a17ae 7540
f273fef1
DS
7541 /*
7542 * summary-only aggregate route suppress
7543 * aggregated route announcements.
6aabb15d
RZ
7544 *
7545 * MED matching:
7546 * Don't create summaries if MED didn't match
7547 * otherwise neither the specific routes and the
7548 * aggregation will be announced.
f273fef1 7549 */
6aabb15d
RZ
7550 if (aggregate->summary_only
7551 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7552 if (aggr_suppress_path(aggregate, pi))
7553 match++;
d62a17ae 7554 }
c2ff8b3e 7555
365ab2e7
RZ
7556 /*
7557 * Suppress more specific routes that match the route
7558 * map results.
7559 *
7560 * MED matching:
7561 * Don't suppress routes if MED matching is enabled and
7562 * it mismatched otherwise we might end up with no
7563 * routes for this path.
7564 */
7565 if (aggregate->suppress_map_name
7566 && AGGREGATE_MED_VALID(aggregate)
7567 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7568 if (aggr_suppress_path(aggregate, pi))
7569 match++;
d62a17ae 7570 }
c2ff8b3e
DS
7571
7572 aggregate->count++;
7573
f273fef1
DS
7574 /*
7575 * If at least one route among routes that are
7576 * aggregated has ORIGIN with the value INCOMPLETE,
7577 * then the aggregated route MUST have the ORIGIN
7578 * attribute with the value INCOMPLETE. Otherwise, if
7579 * at least one route among routes that are aggregated
7580 * has ORIGIN with the value EGP, then the aggregated
7581 * route MUST have the ORIGIN attribute with the value
7582 * EGP.
7583 */
fc968841
NT
7584 switch (pi->attr->origin) {
7585 case BGP_ORIGIN_INCOMPLETE:
7586 aggregate->incomplete_origin_count++;
7587 break;
7588 case BGP_ORIGIN_EGP:
7589 aggregate->egp_origin_count++;
7590 break;
7591 default:
7592 /*Do nothing.
7593 */
7594 break;
7595 }
c2ff8b3e
DS
7596
7597 if (!aggregate->as_set)
7598 continue;
7599
f273fef1
DS
7600 /*
7601 * as-set aggregate route generate origin, as path,
7602 * and community aggregation.
7603 */
fc968841
NT
7604 /* Compute aggregate route's as-path.
7605 */
ef51a7d8 7606 bgp_compute_aggregate_aspath_hash(aggregate,
7607 pi->attr->aspath);
c2ff8b3e 7608
fc968841
NT
7609 /* Compute aggregate route's community.
7610 */
9a706b42 7611 if (bgp_attr_get_community(pi->attr))
21fec674 7612 bgp_compute_aggregate_community_hash(
9a706b42
DA
7613 aggregate,
7614 bgp_attr_get_community(pi->attr));
dd18c5a9 7615
fc968841
NT
7616 /* Compute aggregate route's extended community.
7617 */
b53e67a3 7618 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7619 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7620 aggregate,
7621 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7622
7623 /* Compute aggregate route's large community.
7624 */
1bcf3a96 7625 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7626 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7627 aggregate,
7628 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7629 }
c2ff8b3e 7630 if (match)
9bcb3eef 7631 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7632 }
21fec674 7633 if (aggregate->as_set) {
ef51a7d8 7634 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7635 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7636 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7637 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7638 }
7639
f1eb1f05 7640
9bcb3eef 7641 bgp_dest_unlock_node(top);
718e3744 7642
718e3744 7643
fc968841
NT
7644 if (aggregate->incomplete_origin_count > 0)
7645 origin = BGP_ORIGIN_INCOMPLETE;
7646 else if (aggregate->egp_origin_count > 0)
7647 origin = BGP_ORIGIN_EGP;
d62a17ae 7648
229757f1
DA
7649 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7650 origin = aggregate->origin;
7651
fc968841
NT
7652 if (aggregate->as_set) {
7653 if (aggregate->aspath)
7654 /* Retrieve aggregate route's as-path.
7655 */
7656 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7657
fc968841
NT
7658 if (aggregate->community)
7659 /* Retrieve aggregate route's community.
7660 */
7661 community = community_dup(aggregate->community);
3da2cc32 7662
fc968841
NT
7663 if (aggregate->ecommunity)
7664 /* Retrieve aggregate route's ecommunity.
7665 */
7666 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7667
fc968841
NT
7668 if (aggregate->lcommunity)
7669 /* Retrieve aggregate route's lcommunity.
7670 */
7671 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7672 }
718e3744 7673
c701010e 7674 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7675 ecommunity, lcommunity, atomic_aggregate,
7676 aggregate);
718e3744 7677}
7678
5f040085
DS
7679void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7680 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7681{
7682 struct bgp_table *table;
9bcb3eef
DS
7683 struct bgp_dest *top;
7684 struct bgp_dest *dest;
40381db7 7685 struct bgp_path_info *pi;
3b7db173
DS
7686 unsigned long match;
7687
7688 table = bgp->rib[afi][safi];
7689
7690 /* If routes exists below this node, generate aggregate routes. */
7691 top = bgp_node_get(table, p);
9bcb3eef
DS
7692 for (dest = bgp_node_get(table, p); dest;
7693 dest = bgp_route_next_until(dest, top)) {
7694 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7695
9bcb3eef 7696 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7697 continue;
7698 match = 0;
7699
9bcb3eef 7700 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7701 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7702 continue;
7703
40381db7 7704 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7705 continue;
7706
92b175bd
RZ
7707 /*
7708 * This route is suppressed: attempt to unsuppress it.
7709 *
7710 * `aggr_unsuppress_path` will fail if this particular
7711 * aggregate route was not the suppressor.
7712 */
7713 if (pi->extra && pi->extra->aggr_suppressors &&
7714 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7715 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7716 match++;
3b7db173 7717 }
365ab2e7 7718
3b7db173 7719 aggregate->count--;
fc968841
NT
7720
7721 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7722 aggregate->incomplete_origin_count--;
7723 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7724 aggregate->egp_origin_count--;
7725
7726 if (aggregate->as_set) {
7727 /* Remove as-path from aggregate.
7728 */
ef51a7d8 7729 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7730 aggregate,
7731 pi->attr->aspath);
7732
9a706b42 7733 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7734 /* Remove community from aggregate.
7735 */
21fec674 7736 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7737 aggregate,
7738 bgp_attr_get_community(
7739 pi->attr));
fc968841 7740
b53e67a3 7741 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7742 /* Remove ecommunity from aggregate.
7743 */
4edd83f9 7744 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7745 aggregate,
7746 bgp_attr_get_ecommunity(
7747 pi->attr));
fc968841 7748
1bcf3a96 7749 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7750 /* Remove lcommunity from aggregate.
7751 */
f1eb1f05 7752 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7753 aggregate,
7754 bgp_attr_get_lcommunity(
7755 pi->attr));
fc968841 7756 }
3b7db173
DS
7757 }
7758
7759 /* If this node was suppressed, process the change. */
7760 if (match)
9bcb3eef 7761 bgp_process(bgp, dest, afi, safi);
3b7db173 7762 }
f1eb1f05 7763 if (aggregate->as_set) {
ef51a7d8 7764 aspath_free(aggregate->aspath);
7765 aggregate->aspath = NULL;
21fec674 7766 if (aggregate->community)
7767 community_free(&aggregate->community);
4edd83f9 7768 if (aggregate->ecommunity)
7769 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7770 if (aggregate->lcommunity)
7771 lcommunity_free(&aggregate->lcommunity);
7772 }
7773
9bcb3eef 7774 bgp_dest_unlock_node(top);
3b7db173 7775}
718e3744 7776
5f040085
DS
7777static void bgp_add_route_to_aggregate(struct bgp *bgp,
7778 const struct prefix *aggr_p,
fc968841
NT
7779 struct bgp_path_info *pinew, afi_t afi,
7780 safi_t safi,
7781 struct bgp_aggregate *aggregate)
7782{
7783 uint8_t origin;
7784 struct aspath *aspath = NULL;
7785 uint8_t atomic_aggregate = 0;
7786 struct community *community = NULL;
7787 struct ecommunity *ecommunity = NULL;
7788 struct lcommunity *lcommunity = NULL;
7789
a4559740 7790 /* If the bgp instance is being deleted or self peer is deleted
7791 * then do not create aggregate route
7792 */
7793 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7794 || (bgp->peer_self == NULL))
7795 return;
7796
fc968841
NT
7797 /* ORIGIN attribute: If at least one route among routes that are
7798 * aggregated has ORIGIN with the value INCOMPLETE, then the
7799 * aggregated route must have the ORIGIN attribute with the value
7800 * INCOMPLETE. Otherwise, if at least one route among routes that
7801 * are aggregated has ORIGIN with the value EGP, then the aggregated
7802 * route must have the origin attribute with the value EGP. In all
7803 * other case the value of the ORIGIN attribute of the aggregated
7804 * route is INTERNAL.
7805 */
7806 origin = BGP_ORIGIN_IGP;
7807
7808 aggregate->count++;
7809
6aabb15d
RZ
7810 /*
7811 * This must be called before `summary` check to avoid
7812 * "suppressing" twice.
7813 */
7814 if (aggregate->match_med)
7815 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7816 pinew, true);
7817
7818 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7819 aggr_suppress_path(aggregate, pinew);
fc968841 7820
365ab2e7
RZ
7821 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7822 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7823 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7824
7825 switch (pinew->attr->origin) {
7826 case BGP_ORIGIN_INCOMPLETE:
7827 aggregate->incomplete_origin_count++;
7828 break;
7829 case BGP_ORIGIN_EGP:
7830 aggregate->egp_origin_count++;
7831 break;
7832 default:
7833 /* Do nothing.
7834 */
7835 break;
7836 }
7837
7838 if (aggregate->incomplete_origin_count > 0)
7839 origin = BGP_ORIGIN_INCOMPLETE;
7840 else if (aggregate->egp_origin_count > 0)
7841 origin = BGP_ORIGIN_EGP;
7842
229757f1
DA
7843 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7844 origin = aggregate->origin;
7845
fc968841
NT
7846 if (aggregate->as_set) {
7847 /* Compute aggregate route's as-path.
7848 */
7849 bgp_compute_aggregate_aspath(aggregate,
7850 pinew->attr->aspath);
7851
7852 /* Compute aggregate route's community.
7853 */
9a706b42 7854 if (bgp_attr_get_community(pinew->attr))
fc968841 7855 bgp_compute_aggregate_community(
9a706b42 7856 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7857
7858 /* Compute aggregate route's extended community.
7859 */
b53e67a3 7860 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7861 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7862 aggregate,
7863 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7864
7865 /* Compute aggregate route's large community.
7866 */
1bcf3a96 7867 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7868 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7869 aggregate,
7870 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7871
7872 /* Retrieve aggregate route's as-path.
7873 */
7874 if (aggregate->aspath)
7875 aspath = aspath_dup(aggregate->aspath);
7876
7877 /* Retrieve aggregate route's community.
7878 */
7879 if (aggregate->community)
7880 community = community_dup(aggregate->community);
7881
7882 /* Retrieve aggregate route's ecommunity.
7883 */
7884 if (aggregate->ecommunity)
7885 ecommunity = ecommunity_dup(aggregate->ecommunity);
7886
7887 /* Retrieve aggregate route's lcommunity.
7888 */
7889 if (aggregate->lcommunity)
7890 lcommunity = lcommunity_dup(aggregate->lcommunity);
7891 }
7892
7893 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7894 aspath, community, ecommunity,
7895 lcommunity, atomic_aggregate, aggregate);
7896}
7897
7898static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7899 safi_t safi,
7900 struct bgp_path_info *pi,
7901 struct bgp_aggregate *aggregate,
5f040085 7902 const struct prefix *aggr_p)
fc968841
NT
7903{
7904 uint8_t origin;
7905 struct aspath *aspath = NULL;
7906 uint8_t atomic_aggregate = 0;
7907 struct community *community = NULL;
7908 struct ecommunity *ecommunity = NULL;
7909 struct lcommunity *lcommunity = NULL;
7910 unsigned long match = 0;
7911
a4559740 7912 /* If the bgp instance is being deleted or self peer is deleted
7913 * then do not create aggregate route
7914 */
7915 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7916 || (bgp->peer_self == NULL))
7917 return;
7918
fc968841
NT
7919 if (BGP_PATH_HOLDDOWN(pi))
7920 return;
7921
7922 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7923 return;
7924
4056a5f6
RZ
7925 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7926 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7927 match++;
fc968841 7928
365ab2e7 7929 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7930 && aggr_suppress_map_test(bgp, aggregate, pi))
7931 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7932 match++;
fc968841 7933
6aabb15d 7934 /*
365ab2e7 7935 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7936 * "unsuppressing" twice.
7937 */
7938 if (aggregate->match_med)
7939 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7940 true);
7941
fc968841
NT
7942 if (aggregate->count > 0)
7943 aggregate->count--;
7944
7945 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7946 aggregate->incomplete_origin_count--;
7947 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7948 aggregate->egp_origin_count--;
7949
7950 if (aggregate->as_set) {
7951 /* Remove as-path from aggregate.
7952 */
7953 bgp_remove_aspath_from_aggregate(aggregate,
7954 pi->attr->aspath);
7955
9a706b42 7956 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7957 /* Remove community from aggregate.
7958 */
7959 bgp_remove_community_from_aggregate(
9a706b42 7960 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7961
b53e67a3 7962 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7963 /* Remove ecommunity from aggregate.
7964 */
7965 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7966 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7967
1bcf3a96 7968 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7969 /* Remove lcommunity from aggregate.
7970 */
7971 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7972 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7973 }
7974
7975 /* If this node was suppressed, process the change. */
7976 if (match)
7977 bgp_process(bgp, pi->net, afi, safi);
7978
7979 origin = BGP_ORIGIN_IGP;
7980 if (aggregate->incomplete_origin_count > 0)
7981 origin = BGP_ORIGIN_INCOMPLETE;
7982 else if (aggregate->egp_origin_count > 0)
7983 origin = BGP_ORIGIN_EGP;
7984
229757f1
DA
7985 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7986 origin = aggregate->origin;
7987
fc968841
NT
7988 if (aggregate->as_set) {
7989 /* Retrieve aggregate route's as-path.
7990 */
7991 if (aggregate->aspath)
7992 aspath = aspath_dup(aggregate->aspath);
7993
7994 /* Retrieve aggregate route's community.
7995 */
7996 if (aggregate->community)
7997 community = community_dup(aggregate->community);
7998
7999 /* Retrieve aggregate route's ecommunity.
8000 */
8001 if (aggregate->ecommunity)
8002 ecommunity = ecommunity_dup(aggregate->ecommunity);
8003
8004 /* Retrieve aggregate route's lcommunity.
8005 */
8006 if (aggregate->lcommunity)
8007 lcommunity = lcommunity_dup(aggregate->lcommunity);
8008 }
8009
8010 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8011 aspath, community, ecommunity,
8012 lcommunity, atomic_aggregate, aggregate);
8013}
8014
5a1ae2c2 8015void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8016 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8017{
9bcb3eef
DS
8018 struct bgp_dest *child;
8019 struct bgp_dest *dest;
d62a17ae 8020 struct bgp_aggregate *aggregate;
8021 struct bgp_table *table;
718e3744 8022
d62a17ae 8023 table = bgp->aggregate[afi][safi];
f018db83 8024
d62a17ae 8025 /* No aggregates configured. */
8026 if (bgp_table_top_nolock(table) == NULL)
8027 return;
f018db83 8028
d62a17ae 8029 if (p->prefixlen == 0)
8030 return;
718e3744 8031
40381db7 8032 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8033 return;
718e3744 8034
a77e2f4b
S
8035 /* If suppress fib is enabled and route not installed
8036 * in FIB, do not update the aggregate route
8037 */
8038 if (!bgp_check_advertise(bgp, pi->net))
8039 return;
8040
d62a17ae 8041 child = bgp_node_get(table, p);
718e3744 8042
d62a17ae 8043 /* Aggregate address configuration check. */
9bcb3eef
DS
8044 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8045 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8046
9bcb3eef
DS
8047 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8048 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8049 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8050 aggregate);
d62a17ae 8051 }
b1e62edd 8052 }
9bcb3eef 8053 bgp_dest_unlock_node(child);
718e3744 8054}
8055
5a1ae2c2 8056void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8057 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8058{
9bcb3eef
DS
8059 struct bgp_dest *child;
8060 struct bgp_dest *dest;
d62a17ae 8061 struct bgp_aggregate *aggregate;
8062 struct bgp_table *table;
718e3744 8063
d62a17ae 8064 table = bgp->aggregate[afi][safi];
718e3744 8065
d62a17ae 8066 /* No aggregates configured. */
8067 if (bgp_table_top_nolock(table) == NULL)
8068 return;
718e3744 8069
d62a17ae 8070 if (p->prefixlen == 0)
8071 return;
718e3744 8072
d62a17ae 8073 child = bgp_node_get(table, p);
718e3744 8074
d62a17ae 8075 /* Aggregate address configuration check. */
9bcb3eef
DS
8076 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8077 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8078
9bcb3eef
DS
8079 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8080 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8081 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8082 aggregate, dest_p);
d62a17ae 8083 }
b1e62edd 8084 }
9bcb3eef 8085 bgp_dest_unlock_node(child);
d62a17ae 8086}
718e3744 8087
718e3744 8088/* Aggregate route attribute. */
8089#define AGGREGATE_SUMMARY_ONLY 1
8090#define AGGREGATE_AS_SET 1
fb29348a 8091#define AGGREGATE_AS_UNSET 0
718e3744 8092
229757f1
DA
8093static const char *bgp_origin2str(uint8_t origin)
8094{
8095 switch (origin) {
8096 case BGP_ORIGIN_IGP:
8097 return "igp";
8098 case BGP_ORIGIN_EGP:
8099 return "egp";
8100 case BGP_ORIGIN_INCOMPLETE:
8101 return "incomplete";
8102 }
8103 return "n/a";
8104}
8105
fdeb5a81 8106static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8107{
8108 switch (v_state) {
fdeb5a81
DS
8109 case RPKI_NOT_BEING_USED:
8110 return "not used";
8111 case RPKI_VALID:
b5b99af8 8112 return "valid";
fdeb5a81 8113 case RPKI_NOTFOUND:
b5b99af8 8114 return "not found";
fdeb5a81 8115 case RPKI_INVALID:
b5b99af8 8116 return "invalid";
b5b99af8 8117 }
fdeb5a81
DS
8118
8119 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8120 return "ERROR";
8121}
8122
585f1adc
IR
8123static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8124 afi_t afi, safi_t safi)
718e3744 8125{
585f1adc
IR
8126 VTY_DECLVAR_CONTEXT(bgp, bgp);
8127 int ret;
8128 struct prefix p;
9bcb3eef 8129 struct bgp_dest *dest;
d62a17ae 8130 struct bgp_aggregate *aggregate;
718e3744 8131
585f1adc
IR
8132 /* Convert string to prefix structure. */
8133 ret = str2prefix(prefix_str, &p);
8134 if (!ret) {
8135 vty_out(vty, "Malformed prefix\n");
8136 return CMD_WARNING_CONFIG_FAILED;
8137 }
8138 apply_mask(&p);
a4559740 8139
d62a17ae 8140 /* Old configuration check. */
585f1adc 8141 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8142 if (!dest) {
585f1adc
IR
8143 vty_out(vty,
8144 "%% There is no aggregate-address configuration.\n");
8145 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8146 }
f6269b4f 8147
9bcb3eef 8148 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8149 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8150 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8151 NULL, NULL, 0, aggregate);
d62a17ae 8152
8153 /* Unlock aggregate address configuration. */
9bcb3eef 8154 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8155
8156 if (aggregate->community)
8157 community_free(&aggregate->community);
8158
8159 if (aggregate->community_hash) {
8160 /* Delete all communities in the hash.
8161 */
8162 hash_clean(aggregate->community_hash,
8163 bgp_aggr_community_remove);
8164 /* Free up the community_hash.
8165 */
8166 hash_free(aggregate->community_hash);
8167 }
8168
8169 if (aggregate->ecommunity)
8170 ecommunity_free(&aggregate->ecommunity);
8171
8172 if (aggregate->ecommunity_hash) {
8173 /* Delete all ecommunities in the hash.
8174 */
8175 hash_clean(aggregate->ecommunity_hash,
8176 bgp_aggr_ecommunity_remove);
8177 /* Free up the ecommunity_hash.
8178 */
8179 hash_free(aggregate->ecommunity_hash);
8180 }
8181
8182 if (aggregate->lcommunity)
8183 lcommunity_free(&aggregate->lcommunity);
8184
8185 if (aggregate->lcommunity_hash) {
8186 /* Delete all lcommunities in the hash.
8187 */
8188 hash_clean(aggregate->lcommunity_hash,
8189 bgp_aggr_lcommunity_remove);
8190 /* Free up the lcommunity_hash.
8191 */
8192 hash_free(aggregate->lcommunity_hash);
8193 }
8194
8195 if (aggregate->aspath)
8196 aspath_free(aggregate->aspath);
8197
8198 if (aggregate->aspath_hash) {
8199 /* Delete all as-paths in the hash.
8200 */
8201 hash_clean(aggregate->aspath_hash,
8202 bgp_aggr_aspath_remove);
8203 /* Free up the aspath_hash.
8204 */
8205 hash_free(aggregate->aspath_hash);
8206 }
8207
d62a17ae 8208 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8209 bgp_dest_unlock_node(dest);
8210 bgp_dest_unlock_node(dest);
d62a17ae 8211
585f1adc 8212 return CMD_SUCCESS;
d62a17ae 8213}
8214
585f1adc
IR
8215static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8216 safi_t safi, const char *rmap,
8217 uint8_t summary_only, uint8_t as_set,
8218 uint8_t origin, bool match_med,
8219 const char *suppress_map)
d62a17ae 8220{
585f1adc 8221 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8222 int ret;
585f1adc 8223 struct prefix p;
9bcb3eef 8224 struct bgp_dest *dest;
d62a17ae 8225 struct bgp_aggregate *aggregate;
fb29348a 8226 uint8_t as_set_new = as_set;
d62a17ae 8227
365ab2e7 8228 if (suppress_map && summary_only) {
585f1adc 8229 vty_out(vty,
365ab2e7 8230 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8231 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8232 }
8233
585f1adc
IR
8234 /* Convert string to prefix structure. */
8235 ret = str2prefix(prefix_str, &p);
8236 if (!ret) {
8237 vty_out(vty, "Malformed prefix\n");
8238 return CMD_WARNING_CONFIG_FAILED;
8239 }
8240 apply_mask(&p);
d62a17ae 8241
585f1adc
IR
8242 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8243 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8244 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8245 prefix_str);
8246 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8247 }
8248
d62a17ae 8249 /* Old configuration check. */
585f1adc 8250 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8251 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8252
20894f50 8253 if (aggregate) {
585f1adc 8254 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8255 /* try to remove the old entry */
585f1adc 8256 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8257 if (ret) {
585f1adc 8258 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8259 bgp_dest_unlock_node(dest);
585f1adc 8260 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8261 }
8262 }
718e3744 8263
d62a17ae 8264 /* Make aggregate address structure. */
8265 aggregate = bgp_aggregate_new();
8266 aggregate->summary_only = summary_only;
6aabb15d 8267 aggregate->match_med = match_med;
fb29348a
DA
8268
8269 /* Network operators MUST NOT locally generate any new
8270 * announcements containing AS_SET or AS_CONFED_SET. If they have
8271 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8272 * SHOULD withdraw those routes and re-announce routes for the
8273 * aggregate or component prefixes (i.e., the more-specific routes
8274 * subsumed by the previously aggregated route) without AS_SET
8275 * or AS_CONFED_SET in the updates.
8276 */
7f972cd8 8277 if (bgp->reject_as_sets) {
fb29348a
DA
8278 if (as_set == AGGREGATE_AS_SET) {
8279 as_set_new = AGGREGATE_AS_UNSET;
8280 zlog_warn(
63efca0e 8281 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8282 __func__);
585f1adc 8283 vty_out(vty,
fb29348a
DA
8284 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8285 }
8286 }
8287
8288 aggregate->as_set = as_set_new;
d62a17ae 8289 aggregate->safi = safi;
229757f1
DA
8290 /* Override ORIGIN attribute if defined.
8291 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8292 * to IGP which is not what rfc4271 says.
8293 * This enables the same behavior, optionally.
8294 */
8295 aggregate->origin = origin;
20894f50
DA
8296
8297 if (rmap) {
8298 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8299 route_map_counter_decrement(aggregate->rmap.map);
8300 aggregate->rmap.name =
8301 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8302 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8303 route_map_counter_increment(aggregate->rmap.map);
8304 }
365ab2e7
RZ
8305
8306 if (suppress_map) {
8307 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8308 route_map_counter_decrement(aggregate->suppress_map);
8309
8310 aggregate->suppress_map_name =
8311 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8312 aggregate->suppress_map =
8313 route_map_lookup_by_name(aggregate->suppress_map_name);
8314 route_map_counter_increment(aggregate->suppress_map);
8315 }
8316
9bcb3eef 8317 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8318
d62a17ae 8319 /* Aggregate address insert into BGP routing table. */
585f1adc 8320 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8321
585f1adc 8322 return CMD_SUCCESS;
718e3744 8323}
8324
585f1adc
IR
8325DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8326 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8327 "as-set$as_set_s"
8328 "|summary-only$summary_only"
cacba915 8329 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8330 "|origin <egp|igp|incomplete>$origin_s"
8331 "|matching-MED-only$match_med"
cacba915 8332 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8333 "}]",
8334 NO_STR
8335 "Configure BGP aggregate entries\n"
764402fe
DA
8336 "Aggregate prefix\n"
8337 "Aggregate address\n"
8338 "Aggregate mask\n"
585f1adc
IR
8339 "Generate AS set path information\n"
8340 "Filter more specific routes from updates\n"
8341 "Apply route map to aggregate network\n"
8342 "Route map name\n"
8343 "BGP origin code\n"
8344 "Remote EGP\n"
8345 "Local IGP\n"
8346 "Unknown heritage\n"
8347 "Only aggregate routes with matching MED\n"
8348 "Suppress the selected more specific routes\n"
8349 "Route map with the route selectors\n")
8350{
8351 const char *prefix_s = NULL;
554b3b10 8352 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8353 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8354 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8355 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8356
554b3b10 8357 if (addr_str) {
7533cad7
QY
8358 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8359 sizeof(prefix_buf))
554b3b10
RZ
8360 == 0) {
8361 vty_out(vty, "%% Inconsistent address and mask\n");
8362 return CMD_WARNING_CONFIG_FAILED;
8363 }
585f1adc
IR
8364 prefix_s = prefix_buf;
8365 } else
8366 prefix_s = prefix_str;
37a87b8f 8367
585f1adc
IR
8368 if (origin_s) {
8369 if (strcmp(origin_s, "egp") == 0)
8370 origin = BGP_ORIGIN_EGP;
8371 else if (strcmp(origin_s, "igp") == 0)
8372 origin = BGP_ORIGIN_IGP;
8373 else if (strcmp(origin_s, "incomplete") == 0)
8374 origin = BGP_ORIGIN_INCOMPLETE;
8375 }
90e21f35 8376
585f1adc
IR
8377 if (as_set_s)
8378 as_set = AGGREGATE_AS_SET;
554b3b10 8379
585f1adc 8380 /* Handle configuration removal, otherwise installation. */
554b3b10 8381 if (no)
585f1adc
IR
8382 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8383
8384 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8385 summary_only != NULL, as_set, origin,
8386 match_med != NULL, suppress_map);
8387}
8388
8389DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8390 "[no] aggregate-address X:X::X:X/M$prefix [{"
8391 "as-set$as_set_s"
8392 "|summary-only$summary_only"
cacba915 8393 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8394 "|origin <egp|igp|incomplete>$origin_s"
8395 "|matching-MED-only$match_med"
cacba915 8396 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8397 "}]",
8398 NO_STR
8399 "Configure BGP aggregate entries\n"
8400 "Aggregate prefix\n"
8401 "Generate AS set path information\n"
8402 "Filter more specific routes from updates\n"
8403 "Apply route map to aggregate network\n"
8404 "Route map name\n"
8405 "BGP origin code\n"
8406 "Remote EGP\n"
8407 "Local IGP\n"
8408 "Unknown heritage\n"
8409 "Only aggregate routes with matching MED\n"
8410 "Suppress the selected more specific routes\n"
8411 "Route map with the route selectors\n")
8412{
8413 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8414 int as_set = AGGREGATE_AS_UNSET;
8415
8416 if (origin_s) {
8417 if (strcmp(origin_s, "egp") == 0)
8418 origin = BGP_ORIGIN_EGP;
8419 else if (strcmp(origin_s, "igp") == 0)
8420 origin = BGP_ORIGIN_IGP;
8421 else if (strcmp(origin_s, "incomplete") == 0)
8422 origin = BGP_ORIGIN_INCOMPLETE;
8423 }
8424
8425 if (as_set_s)
8426 as_set = AGGREGATE_AS_SET;
8427
8428 /* Handle configuration removal, otherwise installation. */
554b3b10 8429 if (no)
585f1adc
IR
8430 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8431 SAFI_UNICAST);
554b3b10 8432
585f1adc
IR
8433 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8434 rmap_name, summary_only != NULL, as_set,
8435 origin, match_med != NULL, suppress_map);
718e3744 8436}
8437
718e3744 8438/* Redistribute route treatment. */
d62a17ae 8439void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8440 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8441 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8442 enum blackhole_type bhtype, uint32_t metric,
8443 uint8_t type, unsigned short instance,
8444 route_tag_t tag)
d62a17ae 8445{
4b7e6066 8446 struct bgp_path_info *new;
40381db7
DS
8447 struct bgp_path_info *bpi;
8448 struct bgp_path_info rmap_path;
9bcb3eef 8449 struct bgp_dest *bn;
d62a17ae 8450 struct attr attr;
8451 struct attr *new_attr;
8452 afi_t afi;
b68885f9 8453 route_map_result_t ret;
d62a17ae 8454 struct bgp_redist *red;
8455
8456 /* Make default attribute. */
0f05ea43 8457 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8458 /*
8459 * This must not be NULL to satisfy Coverity SA
8460 */
8461 assert(attr.aspath);
9de1f7ff 8462
a4d82a8a 8463 switch (nhtype) {
9de1f7ff
DS
8464 case NEXTHOP_TYPE_IFINDEX:
8465 break;
8466 case NEXTHOP_TYPE_IPV4:
8467 case NEXTHOP_TYPE_IPV4_IFINDEX:
8468 attr.nexthop = nexthop->ipv4;
7226bc40 8469 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8470 break;
8471 case NEXTHOP_TYPE_IPV6:
8472 case NEXTHOP_TYPE_IPV6_IFINDEX:
8473 attr.mp_nexthop_global = nexthop->ipv6;
8474 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8475 break;
8476 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8477 switch (p->family) {
8478 case AF_INET:
9de1f7ff 8479 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8480 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8481 break;
8482 case AF_INET6:
9de1f7ff
DS
8483 memset(&attr.mp_nexthop_global, 0,
8484 sizeof(attr.mp_nexthop_global));
74489921 8485 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8486 break;
74489921 8487 }
0789eb69 8488 attr.bh_type = bhtype;
9de1f7ff 8489 break;
d62a17ae 8490 }
0789eb69 8491 attr.nh_type = nhtype;
74489921 8492 attr.nh_ifindex = ifindex;
f04a80a5 8493
d62a17ae 8494 attr.med = metric;
957f74c3 8495 attr.distance = distance;
d62a17ae 8496 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8497 attr.tag = tag;
718e3744 8498
d62a17ae 8499 afi = family2afi(p->family);
6aeb9e78 8500
d62a17ae 8501 red = bgp_redist_lookup(bgp, afi, type, instance);
8502 if (red) {
8503 struct attr attr_new;
718e3744 8504
d62a17ae 8505 /* Copy attribute for modification. */
6f4f49b2 8506 attr_new = attr;
718e3744 8507
d62a17ae 8508 if (red->redist_metric_flag)
8509 attr_new.med = red->redist_metric;
718e3744 8510
d62a17ae 8511 /* Apply route-map. */
8512 if (red->rmap.name) {
6006b807 8513 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8514 rmap_path.peer = bgp->peer_self;
8515 rmap_path.attr = &attr_new;
718e3744 8516
d62a17ae 8517 SET_FLAG(bgp->peer_self->rmap_type,
8518 PEER_RMAP_TYPE_REDISTRIBUTE);
8519
1782514f 8520 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8521
8522 bgp->peer_self->rmap_type = 0;
8523
8524 if (ret == RMAP_DENYMATCH) {
8525 /* Free uninterned attribute. */
8526 bgp_attr_flush(&attr_new);
8527
8528 /* Unintern original. */
8529 aspath_unintern(&attr.aspath);
8530 bgp_redistribute_delete(bgp, p, type, instance);
8531 return;
8532 }
8533 }
8534
637e5ba4 8535 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8536 bgp_attr_add_gshut_community(&attr_new);
8537
d62a17ae 8538 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8539 SAFI_UNICAST, p, NULL);
8540
8541 new_attr = bgp_attr_intern(&attr_new);
8542
9bcb3eef 8543 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8544 if (bpi->peer == bgp->peer_self
8545 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8546 break;
8547
40381db7 8548 if (bpi) {
d62a17ae 8549 /* Ensure the (source route) type is updated. */
40381db7
DS
8550 bpi->type = type;
8551 if (attrhash_cmp(bpi->attr, new_attr)
8552 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8553 bgp_attr_unintern(&new_attr);
8554 aspath_unintern(&attr.aspath);
9bcb3eef 8555 bgp_dest_unlock_node(bn);
d62a17ae 8556 return;
8557 } else {
8558 /* The attribute is changed. */
40381db7 8559 bgp_path_info_set_flag(bn, bpi,
18ee8310 8560 BGP_PATH_ATTR_CHANGED);
d62a17ae 8561
8562 /* Rewrite BGP route information. */
40381db7
DS
8563 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8564 bgp_path_info_restore(bn, bpi);
d62a17ae 8565 else
40381db7
DS
8566 bgp_aggregate_decrement(
8567 bgp, p, bpi, afi, SAFI_UNICAST);
8568 bgp_attr_unintern(&bpi->attr);
8569 bpi->attr = new_attr;
083ec940 8570 bpi->uptime = monotime(NULL);
d62a17ae 8571
8572 /* Process change. */
40381db7 8573 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8574 SAFI_UNICAST);
8575 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8576 bgp_dest_unlock_node(bn);
d62a17ae 8577 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8578
8579 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8580 || (bgp->inst_type
8581 == BGP_INSTANCE_TYPE_DEFAULT)) {
8582
8583 vpn_leak_from_vrf_update(
40381db7 8584 bgp_get_default(), bgp, bpi);
ddb5b488 8585 }
d62a17ae 8586 return;
8587 }
8588 }
8589
8590 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8591 bgp->peer_self, new_attr, bn);
1defdda8 8592 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8593
8594 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8595 bgp_path_info_add(bn, new);
9bcb3eef 8596 bgp_dest_unlock_node(bn);
be785e35 8597 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8598 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8599
8600 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8601 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8602
8603 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8604 }
d62a17ae 8605 }
8606
8607 /* Unintern original. */
8608 aspath_unintern(&attr.aspath);
718e3744 8609}
8610
d7c0a89a
QY
8611void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8612 unsigned short instance)
718e3744 8613{
d62a17ae 8614 afi_t afi;
9bcb3eef 8615 struct bgp_dest *dest;
40381db7 8616 struct bgp_path_info *pi;
d62a17ae 8617 struct bgp_redist *red;
718e3744 8618
d62a17ae 8619 afi = family2afi(p->family);
718e3744 8620
d62a17ae 8621 red = bgp_redist_lookup(bgp, afi, type, instance);
8622 if (red) {
9bcb3eef
DS
8623 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8624 SAFI_UNICAST, p, NULL);
d62a17ae 8625
9bcb3eef 8626 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8627 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8628 break;
8629
40381db7 8630 if (pi) {
ddb5b488
PZ
8631 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8632 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8633
8634 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8635 bgp, pi);
ddb5b488 8636 }
40381db7 8637 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8638 bgp_path_info_delete(dest, pi);
8639 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8640 }
9bcb3eef 8641 bgp_dest_unlock_node(dest);
d62a17ae 8642 }
8643}
8644
8645/* Withdraw specified route type's route. */
8646void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8647 unsigned short instance)
d62a17ae 8648{
9bcb3eef 8649 struct bgp_dest *dest;
40381db7 8650 struct bgp_path_info *pi;
d62a17ae 8651 struct bgp_table *table;
8652
8653 table = bgp->rib[afi][SAFI_UNICAST];
8654
9bcb3eef
DS
8655 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8656 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8657 if (pi->peer == bgp->peer_self && pi->type == type
8658 && pi->instance == instance)
d62a17ae 8659 break;
8660
40381db7 8661 if (pi) {
ddb5b488
PZ
8662 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8663 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8664
8665 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8666 bgp, pi);
ddb5b488 8667 }
9bcb3eef 8668 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8669 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8670 bgp_path_info_delete(dest, pi);
8671 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8672 }
718e3744 8673 }
718e3744 8674}
6b0655a2 8675
718e3744 8676/* Static function to display route. */
7d3cae70
DA
8677static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8678 struct vty *vty, json_object *json, bool wide)
718e3744 8679{
be054588 8680 int len = 0;
d62a17ae 8681 char buf[BUFSIZ];
718e3744 8682
d62a17ae 8683 if (p->family == AF_INET) {
c6462ff4 8684 if (!json) {
8228a9a7 8685 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8686 } else {
8687 json_object_string_add(json, "prefix",
8688 inet_ntop(p->family,
8689 &p->u.prefix, buf,
8690 BUFSIZ));
8691 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8692 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8693 json_object_int_add(json, "version", dest->version);
c6462ff4 8694 }
d62a17ae 8695 } else if (p->family == AF_ETHERNET) {
8228a9a7 8696 len = vty_out(vty, "%pFX", p);
b03b8898 8697 } else if (p->family == AF_EVPN) {
57f7feb6 8698 if (!json)
2dbe669b 8699 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8700 else
60466a63 8701 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8702 } else if (p->family == AF_FLOWSPEC) {
8703 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8704 json ?
8705 NLRI_STRING_FORMAT_JSON_SIMPLE :
8706 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8707 } else {
c6462ff4 8708 if (!json)
8228a9a7 8709 len = vty_out(vty, "%pFX", p);
50e05855
AD
8710 else {
8711 json_object_string_add(json, "prefix",
8712 inet_ntop(p->family,
8713 &p->u.prefix, buf,
8714 BUFSIZ));
8715 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8716 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8717 json_object_int_add(json, "version", dest->version);
37d4e0df 8718 }
9c92b5f7 8719 }
d62a17ae 8720
9c92b5f7 8721 if (!json) {
ae248832 8722 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8723 if (len < 1)
8724 vty_out(vty, "\n%*s", 20, " ");
8725 else
8726 vty_out(vty, "%*s", len, " ");
8727 }
718e3744 8728}
8729
d62a17ae 8730enum bgp_display_type {
8731 normal_list,
718e3744 8732};
8733
1d7260a1 8734const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8735{
8736 switch (reason) {
8737 case bgp_path_selection_none:
8738 return "Nothing to Select";
8739 case bgp_path_selection_first:
8740 return "First path received";
8741 case bgp_path_selection_evpn_sticky_mac:
8742 return "EVPN Sticky Mac";
8743 case bgp_path_selection_evpn_seq:
8744 return "EVPN sequence number";
8745 case bgp_path_selection_evpn_lower_ip:
8746 return "EVPN lower IP";
8747 case bgp_path_selection_evpn_local_path:
8748 return "EVPN local ES path";
8749 case bgp_path_selection_evpn_non_proxy:
8750 return "EVPN non proxy";
8751 case bgp_path_selection_weight:
8752 return "Weight";
8753 case bgp_path_selection_local_pref:
8754 return "Local Pref";
8755 case bgp_path_selection_local_route:
8756 return "Local Route";
8757 case bgp_path_selection_confed_as_path:
8758 return "Confederation based AS Path";
8759 case bgp_path_selection_as_path:
8760 return "AS Path";
8761 case bgp_path_selection_origin:
8762 return "Origin";
8763 case bgp_path_selection_med:
8764 return "MED";
8765 case bgp_path_selection_peer:
8766 return "Peer Type";
8767 case bgp_path_selection_confed:
8768 return "Confed Peer Type";
8769 case bgp_path_selection_igp_metric:
8770 return "IGP Metric";
8771 case bgp_path_selection_older:
8772 return "Older Path";
8773 case bgp_path_selection_router_id:
8774 return "Router ID";
8775 case bgp_path_selection_cluster_length:
bcab253c 8776 return "Cluster length";
bbb46eb5
DA
8777 case bgp_path_selection_stale:
8778 return "Path Staleness";
8779 case bgp_path_selection_local_configured:
8780 return "Locally configured route";
8781 case bgp_path_selection_neighbor_ip:
8782 return "Neighbor IP";
8783 case bgp_path_selection_default:
8784 return "Nothing left to compare";
8785 }
8786 return "Invalid (internal error)";
8787}
8788
18ee8310 8789/* Print the short form route status for a bgp_path_info */
4b7e6066 8790static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8791 struct bgp_path_info *path,
82c298be 8792 const struct prefix *p,
d62a17ae 8793 json_object *json_path)
718e3744 8794{
82c298be
DA
8795 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8796
d62a17ae 8797 if (json_path) {
b05a1c8b 8798
d62a17ae 8799 /* Route status display. */
9b6d8fcf 8800 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8801 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8802
9b6d8fcf 8803 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8804 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8805
4056a5f6 8806 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8807 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8808
9b6d8fcf
DS
8809 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8810 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8811 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8812
d62a17ae 8813 /* Selected */
9b6d8fcf 8814 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8815 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8816
9b6d8fcf 8817 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8818 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8819
bbb46eb5 8820 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8821 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8822 json_object_string_add(json_path, "selectionReason",
8823 bgp_path_selection_reason2str(
8824 path->net->reason));
8825 }
b05a1c8b 8826
9b6d8fcf 8827 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8828 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8829
d62a17ae 8830 /* Internal route. */
9b6d8fcf
DS
8831 if ((path->peer->as)
8832 && (path->peer->as == path->peer->local_as))
d62a17ae 8833 json_object_string_add(json_path, "pathFrom",
8834 "internal");
8835 else
8836 json_object_string_add(json_path, "pathFrom",
8837 "external");
b05a1c8b 8838
d62a17ae 8839 return;
8840 }
b05a1c8b 8841
82c298be
DA
8842 /* RPKI validation state */
8843 rpki_state =
8844 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8845
8846 if (rpki_state == RPKI_VALID)
8847 vty_out(vty, "V");
8848 else if (rpki_state == RPKI_INVALID)
8849 vty_out(vty, "I");
8850 else if (rpki_state == RPKI_NOTFOUND)
8851 vty_out(vty, "N");
8852
d62a17ae 8853 /* Route status display. */
9b6d8fcf 8854 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8855 vty_out(vty, "R");
9b6d8fcf 8856 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8857 vty_out(vty, "S");
4056a5f6 8858 else if (bgp_path_suppressed(path))
d62a17ae 8859 vty_out(vty, "s");
9b6d8fcf
DS
8860 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8861 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8862 vty_out(vty, "*");
8863 else
8864 vty_out(vty, " ");
8865
8866 /* Selected */
9b6d8fcf 8867 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8868 vty_out(vty, "h");
9b6d8fcf 8869 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8870 vty_out(vty, "d");
9b6d8fcf 8871 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8872 vty_out(vty, ">");
9b6d8fcf 8873 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8874 vty_out(vty, "=");
8875 else
8876 vty_out(vty, " ");
718e3744 8877
d62a17ae 8878 /* Internal route. */
9b6d8fcf
DS
8879 if (path->peer && (path->peer->as)
8880 && (path->peer->as == path->peer->local_as))
d62a17ae 8881 vty_out(vty, "i");
8882 else
8883 vty_out(vty, " ");
b40d939b 8884}
8885
2ba93fd6
DA
8886static char *bgp_nexthop_hostname(struct peer *peer,
8887 struct bgp_nexthop_cache *bnc)
25b5da8d 8888{
892fedb6 8889 if (peer->hostname
aef999a2 8890 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8891 return peer->hostname;
8892 return NULL;
8893}
8894
b40d939b 8895/* called from terminal list command */
bd494ec5 8896void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8897 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8898 json_object *json_paths, bool wide)
d62a17ae 8899{
aef999a2 8900 int len;
515c2602 8901 struct attr *attr = path->attr;
d62a17ae 8902 json_object *json_path = NULL;
8903 json_object *json_nexthops = NULL;
8904 json_object *json_nexthop_global = NULL;
8905 json_object *json_nexthop_ll = NULL;
6f214dd3 8906 json_object *json_ext_community = NULL;
9df8b37c 8907 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8908 bool nexthop_self =
9b6d8fcf 8909 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8910 bool nexthop_othervrf = false;
43089216 8911 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8912 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8913 char *nexthop_hostname =
8914 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8915 char esi_buf[ESI_STR_LEN];
d62a17ae 8916
8917 if (json_paths)
8918 json_path = json_object_new_object();
8919
8920 /* short status lead text */
82c298be 8921 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8922
8923 if (!json_paths) {
8924 /* print prefix and mask */
8925 if (!display)
7d3cae70 8926 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8927 else
ae248832 8928 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8929 } else {
7d3cae70 8930 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8931 }
47fc97cc 8932
9df8b37c
PZ
8933 /*
8934 * If vrf id of nexthop is different from that of prefix,
8935 * set up printable string to append
8936 */
9b6d8fcf 8937 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8938 const char *self = "";
8939
8940 if (nexthop_self)
8941 self = "<";
8942
8943 nexthop_othervrf = true;
9b6d8fcf 8944 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8945
9b6d8fcf 8946 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8947 snprintf(vrf_id_str, sizeof(vrf_id_str),
8948 "@%s%s", VRFID_NONE_STR, self);
8949 else
8950 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8951 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8952
9b6d8fcf
DS
8953 if (path->extra->bgp_orig->inst_type
8954 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8955
9b6d8fcf 8956 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8957 } else {
8958 const char *self = "";
8959
8960 if (nexthop_self)
8961 self = "<";
8962
8963 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8964 }
8965
445c2480
DS
8966 /*
8967 * For ENCAP and EVPN routes, nexthop address family is not
8968 * neccessarily the same as the prefix address family.
8969 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8970 * EVPN routes are also exchanged with a MP nexthop. Currently,
8971 * this
8972 * is only IPv4, the value will be present in either
8973 * attr->nexthop or
8974 * attr->mp_nexthop_global_in
8975 */
8976 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8977 char buf[BUFSIZ];
8978 char nexthop[128];
8979 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8980
8981 switch (af) {
8982 case AF_INET:
772270f3
QY
8983 snprintf(nexthop, sizeof(nexthop), "%s",
8984 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8985 BUFSIZ));
445c2480
DS
8986 break;
8987 case AF_INET6:
772270f3
QY
8988 snprintf(nexthop, sizeof(nexthop), "%s",
8989 inet_ntop(af, &attr->mp_nexthop_global, buf,
8990 BUFSIZ));
445c2480
DS
8991 break;
8992 default:
772270f3 8993 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8994 break;
d62a17ae 8995 }
d62a17ae 8996
445c2480
DS
8997 if (json_paths) {
8998 json_nexthop_global = json_object_new_object();
8999
515c2602
DA
9000 json_object_string_add(json_nexthop_global, "ip",
9001 nexthop);
9002
939a97f4 9003 if (path->peer->hostname)
515c2602
DA
9004 json_object_string_add(json_nexthop_global,
9005 "hostname",
939a97f4 9006 path->peer->hostname);
515c2602
DA
9007
9008 json_object_string_add(json_nexthop_global, "afi",
9009 (af == AF_INET) ? "ipv4"
9010 : "ipv6");
445c2480
DS
9011 json_object_boolean_true_add(json_nexthop_global,
9012 "used");
aef999a2
DA
9013 } else {
9014 if (nexthop_hostname)
9015 len = vty_out(vty, "%s(%s)%s", nexthop,
9016 nexthop_hostname, vrf_id_str);
9017 else
9018 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9019
ae248832 9020 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9021 if (len < 1)
9022 vty_out(vty, "\n%*s", 36, " ");
9023 else
9024 vty_out(vty, "%*s", len, " ");
9025 }
445c2480
DS
9026 } else if (safi == SAFI_EVPN) {
9027 if (json_paths) {
9028 json_nexthop_global = json_object_new_object();
9029
c949c771 9030 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9031 "%pI4",
9032 &attr->mp_nexthop_global_in);
515c2602 9033
939a97f4 9034 if (path->peer->hostname)
515c2602
DA
9035 json_object_string_add(json_nexthop_global,
9036 "hostname",
939a97f4 9037 path->peer->hostname);
515c2602 9038
a4d82a8a
PZ
9039 json_object_string_add(json_nexthop_global, "afi",
9040 "ipv4");
445c2480
DS
9041 json_object_boolean_true_add(json_nexthop_global,
9042 "used");
aef999a2
DA
9043 } else {
9044 if (nexthop_hostname)
7226bc40
TA
9045 len = vty_out(vty, "%pI4(%s)%s",
9046 &attr->mp_nexthop_global_in,
aef999a2
DA
9047 nexthop_hostname, vrf_id_str);
9048 else
7226bc40
TA
9049 len = vty_out(vty, "%pI4%s",
9050 &attr->mp_nexthop_global_in,
aef999a2
DA
9051 vrf_id_str);
9052
ae248832 9053 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9054 if (len < 1)
9055 vty_out(vty, "\n%*s", 36, " ");
9056 else
9057 vty_out(vty, "%*s", len, " ");
9058 }
d33fc23b 9059 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9060 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9061 if (json_paths) {
9062 json_nexthop_global = json_object_new_object();
515c2602 9063
026b914a
PG
9064 json_object_string_add(json_nexthop_global,
9065 "afi", "ipv4");
c949c771
DA
9066 json_object_string_addf(json_nexthop_global,
9067 "ip", "%pI4",
9068 &attr->nexthop);
515c2602 9069
939a97f4 9070 if (path->peer->hostname)
515c2602
DA
9071 json_object_string_add(
9072 json_nexthop_global, "hostname",
939a97f4 9073 path->peer->hostname);
515c2602 9074
50e05855
AD
9075 json_object_boolean_true_add(
9076 json_nexthop_global,
026b914a
PG
9077 "used");
9078 } else {
aef999a2
DA
9079 if (nexthop_hostname)
9080 len = vty_out(vty, "%pI4(%s)%s",
9081 &attr->nexthop,
9082 nexthop_hostname,
9083 vrf_id_str);
9084 else
9085 len = vty_out(vty, "%pI4%s",
9086 &attr->nexthop,
9087 vrf_id_str);
9088
ae248832 9089 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9090 if (len < 1)
9091 vty_out(vty, "\n%*s", 36, " ");
9092 else
9093 vty_out(vty, "%*s", len, " ");
026b914a
PG
9094 }
9095 }
7226bc40 9096 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9097 if (json_paths) {
9098 json_nexthop_global = json_object_new_object();
d62a17ae 9099
c949c771
DA
9100 json_object_string_addf(json_nexthop_global, "ip",
9101 "%pI4", &attr->nexthop);
515c2602 9102
939a97f4 9103 if (path->peer->hostname)
515c2602
DA
9104 json_object_string_add(json_nexthop_global,
9105 "hostname",
939a97f4 9106 path->peer->hostname);
445c2480 9107
a4d82a8a
PZ
9108 json_object_string_add(json_nexthop_global, "afi",
9109 "ipv4");
445c2480
DS
9110 json_object_boolean_true_add(json_nexthop_global,
9111 "used");
9112 } else {
aef999a2
DA
9113 if (nexthop_hostname)
9114 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9115 nexthop_hostname, vrf_id_str);
9116 else
9117 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9118 vrf_id_str);
9df8b37c 9119
ae248832 9120 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9121 if (len < 1)
9122 vty_out(vty, "\n%*s", 36, " ");
9123 else
9124 vty_out(vty, "%*s", len, " ");
d62a17ae 9125 }
445c2480 9126 }
b05a1c8b 9127
445c2480 9128 /* IPv6 Next Hop */
7226bc40 9129 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9130 if (json_paths) {
9131 json_nexthop_global = json_object_new_object();
c949c771
DA
9132 json_object_string_addf(json_nexthop_global, "ip",
9133 "%pI6",
9134 &attr->mp_nexthop_global);
515c2602 9135
939a97f4 9136 if (path->peer->hostname)
515c2602
DA
9137 json_object_string_add(json_nexthop_global,
9138 "hostname",
939a97f4 9139 path->peer->hostname);
515c2602 9140
a4d82a8a
PZ
9141 json_object_string_add(json_nexthop_global, "afi",
9142 "ipv6");
9143 json_object_string_add(json_nexthop_global, "scope",
9144 "global");
445c2480
DS
9145
9146 /* We display both LL & GL if both have been
9147 * received */
0606039c
DA
9148 if ((attr->mp_nexthop_len
9149 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9150 || (path->peer->conf_if)) {
a4d82a8a 9151 json_nexthop_ll = json_object_new_object();
c949c771
DA
9152 json_object_string_addf(
9153 json_nexthop_ll, "ip", "%pI6",
9154 &attr->mp_nexthop_local);
515c2602 9155
939a97f4 9156 if (path->peer->hostname)
515c2602
DA
9157 json_object_string_add(
9158 json_nexthop_ll, "hostname",
939a97f4 9159 path->peer->hostname);
515c2602 9160
a4d82a8a
PZ
9161 json_object_string_add(json_nexthop_ll, "afi",
9162 "ipv6");
9163 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9164 "link-local");
d62a17ae 9165
a4d82a8a
PZ
9166 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9167 &attr->mp_nexthop_local)
445c2480
DS
9168 != 0)
9169 && !attr->mp_nexthop_prefer_global)
d62a17ae 9170 json_object_boolean_true_add(
a4d82a8a 9171 json_nexthop_ll, "used");
445c2480
DS
9172 else
9173 json_object_boolean_true_add(
a4d82a8a 9174 json_nexthop_global, "used");
445c2480
DS
9175 } else
9176 json_object_boolean_true_add(
9177 json_nexthop_global, "used");
9178 } else {
9179 /* Display LL if LL/Global both in table unless
9180 * prefer-global is set */
0606039c
DA
9181 if (((attr->mp_nexthop_len
9182 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9183 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9184 || (path->peer->conf_if)) {
9185 if (path->peer->conf_if) {
a4d82a8a 9186 len = vty_out(vty, "%s",
9b6d8fcf 9187 path->peer->conf_if);
ae248832
MK
9188 /* len of IPv6 addr + max len of def
9189 * ifname */
9190 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9191
9192 if (len < 1)
a4d82a8a 9193 vty_out(vty, "\n%*s", 36, " ");
445c2480 9194 else
a4d82a8a 9195 vty_out(vty, "%*s", len, " ");
d62a17ae 9196 } else {
aef999a2
DA
9197 if (nexthop_hostname)
9198 len = vty_out(
9199 vty, "%pI6(%s)%s",
9200 &attr->mp_nexthop_local,
9201 nexthop_hostname,
9202 vrf_id_str);
9203 else
9204 len = vty_out(
9205 vty, "%pI6%s",
9206 &attr->mp_nexthop_local,
9207 vrf_id_str);
9208
ae248832 9209 len = wide ? (41 - len) : (16 - len);
d62a17ae 9210
9211 if (len < 1)
a4d82a8a 9212 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9213 else
a4d82a8a 9214 vty_out(vty, "%*s", len, " ");
d62a17ae 9215 }
445c2480 9216 } else {
aef999a2
DA
9217 if (nexthop_hostname)
9218 len = vty_out(vty, "%pI6(%s)%s",
9219 &attr->mp_nexthop_global,
9220 nexthop_hostname,
9221 vrf_id_str);
9222 else
9223 len = vty_out(vty, "%pI6%s",
9224 &attr->mp_nexthop_global,
9225 vrf_id_str);
9226
ae248832 9227 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9228
9229 if (len < 1)
9230 vty_out(vty, "\n%*s", 36, " ");
9231 else
9232 vty_out(vty, "%*s", len, " ");
d62a17ae 9233 }
9234 }
445c2480 9235 }
718e3744 9236
445c2480
DS
9237 /* MED/Metric */
9238 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9239 if (json_paths)
50e05855 9240 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9241 else if (wide)
9242 vty_out(vty, "%7u", attr->med);
0fbac0b4 9243 else
445c2480 9244 vty_out(vty, "%10u", attr->med);
ae248832
MK
9245 else if (!json_paths) {
9246 if (wide)
9247 vty_out(vty, "%*s", 7, " ");
9248 else
9249 vty_out(vty, "%*s", 10, " ");
9250 }
d62a17ae 9251
445c2480
DS
9252 /* Local Pref */
9253 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9254 if (json_paths)
50e05855 9255 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9256 attr->local_pref);
9257 else
445c2480
DS
9258 vty_out(vty, "%7u", attr->local_pref);
9259 else if (!json_paths)
9260 vty_out(vty, " ");
d62a17ae 9261
445c2480
DS
9262 if (json_paths)
9263 json_object_int_add(json_path, "weight", attr->weight);
9264 else
9265 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9266
47e12884
DA
9267 if (json_paths)
9268 json_object_string_addf(json_path, "peerId", "%pSU",
9269 &path->peer->su);
b05a1c8b 9270
445c2480
DS
9271 /* Print aspath */
9272 if (attr->aspath) {
0fbac0b4 9273 if (json_paths)
50e05855 9274 json_object_string_add(json_path, "path",
0fbac0b4
DA
9275 attr->aspath->str);
9276 else
445c2480 9277 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9278 }
f1aa5d8a 9279
445c2480
DS
9280 /* Print origin */
9281 if (json_paths)
a4d82a8a
PZ
9282 json_object_string_add(json_path, "origin",
9283 bgp_origin_long_str[attr->origin]);
445c2480
DS
9284 else
9285 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9286
9df8b37c 9287 if (json_paths) {
d071f237 9288 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9289 json_object_string_add(json_path, "esi",
9290 esi_to_str(&attr->esi,
9291 esi_buf, sizeof(esi_buf)));
9292 }
6f214dd3
CS
9293 if (safi == SAFI_EVPN &&
9294 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9295 json_ext_community = json_object_new_object();
b53e67a3
DA
9296 json_object_string_add(
9297 json_ext_community, "string",
9298 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9299 json_object_object_add(json_path,
9300 "extendedCommunity",
9301 json_ext_community);
9302 }
9303
9df8b37c
PZ
9304 if (nexthop_self)
9305 json_object_boolean_true_add(json_path,
9306 "announceNexthopSelf");
9307 if (nexthop_othervrf) {
9308 json_object_string_add(json_path, "nhVrfName",
9309 nexthop_vrfname);
9310
9311 json_object_int_add(json_path, "nhVrfId",
9312 ((nexthop_vrfid == VRF_UNKNOWN)
9313 ? -1
9314 : (int)nexthop_vrfid));
9315 }
9316 }
9317
d62a17ae 9318 if (json_paths) {
9319 if (json_nexthop_global || json_nexthop_ll) {
9320 json_nexthops = json_object_new_array();
f1aa5d8a 9321
d62a17ae 9322 if (json_nexthop_global)
9323 json_object_array_add(json_nexthops,
9324 json_nexthop_global);
f1aa5d8a 9325
d62a17ae 9326 if (json_nexthop_ll)
9327 json_object_array_add(json_nexthops,
9328 json_nexthop_ll);
f1aa5d8a 9329
d62a17ae 9330 json_object_object_add(json_path, "nexthops",
9331 json_nexthops);
9332 }
9333
9334 json_object_array_add(json_paths, json_path);
9335 } else {
9336 vty_out(vty, "\n");
6f214dd3 9337
b5e140c8 9338 if (safi == SAFI_EVPN) {
d071f237 9339 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9340 /* XXX - add these params to the json out */
b5e140c8 9341 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9342 vty_out(vty, "ESI:%s",
9343 esi_to_str(&attr->esi, esi_buf,
9344 sizeof(esi_buf)));
60605cbc 9345
229587fb 9346 vty_out(vty, "\n");
b5e140c8
AK
9347 }
9348 if (attr->flag &
9349 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9350 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9351 vty_out(vty, "%s\n",
9352 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9353 }
6f214dd3
CS
9354 }
9355
49e5a4a0 9356#ifdef ENABLE_BGP_VNC
d62a17ae 9357 /* prints an additional line, indented, with VNC info, if
9358 * present */
9359 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9360 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9361#endif
d62a17ae 9362 }
9363}
718e3744 9364
9365/* called from terminal list command */
7d3cae70
DA
9366void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9367 const struct prefix *p, struct attr *attr, safi_t safi,
9368 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9369{
9370 json_object *json_status = NULL;
9371 json_object *json_net = NULL;
aef999a2 9372 int len;
d62a17ae 9373 char buff[BUFSIZ];
dc387b0f 9374
d62a17ae 9375 /* Route status display. */
9376 if (use_json) {
9377 json_status = json_object_new_object();
9378 json_net = json_object_new_object();
9379 } else {
9380 vty_out(vty, "*");
9381 vty_out(vty, ">");
9382 vty_out(vty, " ");
9383 }
718e3744 9384
d62a17ae 9385 /* print prefix and mask */
50e05855 9386 if (use_json) {
dc387b0f
LK
9387 if (safi == SAFI_EVPN)
9388 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9389 else if (p->family == AF_INET || p->family == AF_INET6) {
9390 json_object_string_add(
9391 json_net, "addrPrefix",
9392 inet_ntop(p->family, &p->u.prefix, buff,
9393 BUFSIZ));
9394 json_object_int_add(json_net, "prefixLen",
9395 p->prefixlen);
67d7e256 9396 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9397 }
50e05855 9398 } else
7d3cae70 9399 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9400
9401 /* Print attribute */
9402 if (attr) {
9403 if (use_json) {
7226bc40
TA
9404 if (p->family == AF_INET &&
9405 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9406 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9407 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9408 json_object_string_addf(
9409 json_net, "nextHop", "%pI4",
9410 &attr->mp_nexthop_global_in);
d62a17ae 9411 else
c949c771
DA
9412 json_object_string_addf(
9413 json_net, "nextHop", "%pI4",
9414 &attr->nexthop);
7226bc40
TA
9415 } else if (p->family == AF_INET6 ||
9416 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9417 json_object_string_addf(
9418 json_net, "nextHopGlobal", "%pI6",
9419 &attr->mp_nexthop_global);
7226bc40
TA
9420 } else if (p->family == AF_EVPN &&
9421 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9422 json_object_string_addf(
9423 json_net, "nextHop", "%pI4",
9424 &attr->mp_nexthop_global_in);
23d0a753 9425 }
d62a17ae 9426
9427 if (attr->flag
9428 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9429 json_object_int_add(json_net, "metric",
9430 attr->med);
9431
0fbac0b4 9432 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9433 json_object_int_add(json_net, "locPrf",
0fbac0b4 9434 attr->local_pref);
d62a17ae 9435
9436 json_object_int_add(json_net, "weight", attr->weight);
9437
9438 /* Print aspath */
0fbac0b4 9439 if (attr->aspath)
50e05855 9440 json_object_string_add(json_net, "path",
0fbac0b4 9441 attr->aspath->str);
d62a17ae 9442
9443 /* Print origin */
9444 json_object_string_add(json_net, "bgpOriginCode",
9445 bgp_origin_str[attr->origin]);
9446 } else {
7226bc40
TA
9447 if (p->family == AF_INET &&
9448 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9449 safi == SAFI_EVPN ||
9450 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9451 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9452 || safi == SAFI_EVPN)
23d0a753
DA
9453 vty_out(vty, "%-16pI4",
9454 &attr->mp_nexthop_global_in);
ae248832 9455 else if (wide)
23d0a753 9456 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9457 else
23d0a753 9458 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9459 } else if (p->family == AF_INET6 ||
9460 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
d62a17ae 9461 char buf[BUFSIZ];
9462
9463 len = vty_out(
9464 vty, "%s",
9465 inet_ntop(AF_INET6,
9466 &attr->mp_nexthop_global, buf,
9467 BUFSIZ));
ae248832 9468 len = wide ? (41 - len) : (16 - len);
d62a17ae 9469 if (len < 1)
9470 vty_out(vty, "\n%*s", 36, " ");
9471 else
9472 vty_out(vty, "%*s", len, " ");
9473 }
9474 if (attr->flag
9475 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9476 if (wide)
9477 vty_out(vty, "%7u", attr->med);
9478 else
9479 vty_out(vty, "%10u", attr->med);
9480 else if (wide)
9481 vty_out(vty, " ");
d62a17ae 9482 else
9483 vty_out(vty, " ");
718e3744 9484
d62a17ae 9485 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9486 vty_out(vty, "%7u", attr->local_pref);
9487 else
9488 vty_out(vty, " ");
9489
9490 vty_out(vty, "%7u ", attr->weight);
9491
9492 /* Print aspath */
9493 if (attr->aspath)
9494 aspath_print_vty(vty, "%s", attr->aspath, " ");
9495
9496 /* Print origin */
9497 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9498 }
9499 }
9500 if (use_json) {
9501 json_object_boolean_true_add(json_status, "*");
9502 json_object_boolean_true_add(json_status, ">");
9503 json_object_object_add(json_net, "appliedStatusSymbols",
9504 json_status);
511211bf 9505 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9506 } else
9507 vty_out(vty, "\n");
9508}
9509
bd494ec5 9510void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9511 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9512 json_object *json)
9513{
9514 json_object *json_out = NULL;
9515 struct attr *attr;
9516 mpls_label_t label = MPLS_INVALID_LABEL;
9517
9b6d8fcf 9518 if (!path->extra)
d62a17ae 9519 return;
9520
9521 if (json)
9522 json_out = json_object_new_object();
9523
9524 /* short status lead text */
82c298be 9525 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9526
9527 /* print prefix and mask */
9528 if (json == NULL) {
9529 if (!display)
7d3cae70 9530 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9531 else
9532 vty_out(vty, "%*s", 17, " ");
9533 }
9534
9535 /* Print attribute */
9b6d8fcf 9536 attr = path->attr;
7226bc40
TA
9537 if (((p->family == AF_INET) &&
9538 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9539 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9540 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9541 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9542 || safi == SAFI_EVPN) {
9543 if (json)
c949c771
DA
9544 json_object_string_addf(
9545 json_out, "mpNexthopGlobalIn", "%pI4",
9546 &attr->mp_nexthop_global_in);
05864da7 9547 else
23d0a753
DA
9548 vty_out(vty, "%-16pI4",
9549 &attr->mp_nexthop_global_in);
05864da7
DS
9550 } else {
9551 if (json)
c949c771
DA
9552 json_object_string_addf(json_out, "nexthop",
9553 "%pI4", &attr->nexthop);
05864da7 9554 else
23d0a753 9555 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9556 }
7226bc40
TA
9557 } else if (((p->family == AF_INET6) &&
9558 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9559 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9560 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9561 char buf_a[512];
9562
9563 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9564 if (json)
c949c771
DA
9565 json_object_string_addf(
9566 json_out, "mpNexthopGlobalIn", "%pI6",
9567 &attr->mp_nexthop_global);
05864da7
DS
9568 else
9569 vty_out(vty, "%s",
9570 inet_ntop(AF_INET6,
9571 &attr->mp_nexthop_global,
9572 buf_a, sizeof(buf_a)));
9573 } else if (attr->mp_nexthop_len
9574 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9575 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9576 &attr->mp_nexthop_global,
9577 &attr->mp_nexthop_local);
9578 if (json)
9579 json_object_string_add(json_out,
9580 "mpNexthopGlobalLocal",
9581 buf_a);
9582 else
9583 vty_out(vty, "%s", buf_a);
d62a17ae 9584 }
9585 }
9586
9b6d8fcf 9587 label = decode_label(&path->extra->label[0]);
d62a17ae 9588
9589 if (bgp_is_valid_label(&label)) {
9590 if (json) {
9591 json_object_int_add(json_out, "notag", label);
9592 json_object_array_add(json, json_out);
9593 } else {
9594 vty_out(vty, "notag/%d", label);
9595 vty_out(vty, "\n");
9596 }
700ddfed
PG
9597 } else if (!json)
9598 vty_out(vty, "\n");
d62a17ae 9599}
718e3744 9600
bd494ec5 9601void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9602 struct bgp_path_info *path, int display,
d62a17ae 9603 json_object *json_paths)
718e3744 9604{
d62a17ae 9605 struct attr *attr;
d62a17ae 9606 json_object *json_path = NULL;
14f51eba
LK
9607 json_object *json_nexthop = NULL;
9608 json_object *json_overlay = NULL;
856ca177 9609
9b6d8fcf 9610 if (!path->extra)
d62a17ae 9611 return;
718e3744 9612
14f51eba
LK
9613 if (json_paths) {
9614 json_path = json_object_new_object();
9615 json_overlay = json_object_new_object();
9616 json_nexthop = json_object_new_object();
9617 }
9618
d62a17ae 9619 /* short status lead text */
82c298be 9620 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9621
d62a17ae 9622 /* print prefix and mask */
9623 if (!display)
7d3cae70 9624 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9625 else
9626 vty_out(vty, "%*s", 17, " ");
9627
9628 /* Print attribute */
9b6d8fcf 9629 attr = path->attr;
05864da7 9630 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9631
05864da7
DS
9632 switch (af) {
9633 case AF_INET:
05864da7 9634 if (!json_path) {
db66cf7c 9635 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9636 } else {
db66cf7c
DA
9637 json_object_string_addf(json_nexthop, "ip", "%pI4",
9638 &attr->mp_nexthop_global_in);
14f51eba 9639
05864da7 9640 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9641
05864da7
DS
9642 json_object_object_add(json_path, "nexthop",
9643 json_nexthop);
9644 }
9645 break;
9646 case AF_INET6:
05864da7 9647 if (!json_path) {
db66cf7c
DA
9648 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9649 &attr->mp_nexthop_local);
05864da7 9650 } else {
db66cf7c
DA
9651 json_object_string_addf(json_nexthop, "ipv6Global",
9652 "%pI6",
9653 &attr->mp_nexthop_global);
14f51eba 9654
db66cf7c
DA
9655 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9656 "%pI6",
9657 &attr->mp_nexthop_local);
14f51eba 9658
05864da7 9659 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9660
05864da7
DS
9661 json_object_object_add(json_path, "nexthop",
9662 json_nexthop);
9663 }
9664 break;
9665 default:
9666 if (!json_path) {
9667 vty_out(vty, "?");
9668 } else {
9669 json_object_string_add(json_nexthop, "Error",
9670 "Unsupported address-family");
77a2f8e5
DA
9671 json_object_string_add(json_nexthop, "error",
9672 "Unsupported address-family");
d62a17ae 9673 }
05864da7 9674 }
988258b4 9675
6c924775
DS
9676 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9677
05864da7 9678 if (!json_path)
db66cf7c 9679 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9680 else
db66cf7c 9681 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9682
b53e67a3 9683 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9684 char *mac = NULL;
9685 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9686 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9687 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9688
9689 if (routermac)
9690 mac = ecom_mac2str((char *)routermac->val);
9691 if (mac) {
9692 if (!json_path) {
c4efd0f4 9693 vty_out(vty, "/%s", mac);
05864da7
DS
9694 } else {
9695 json_object_string_add(json_overlay, "rmac",
9696 mac);
988258b4 9697 }
05864da7 9698 XFREE(MTYPE_TMP, mac);
988258b4 9699 }
05864da7 9700 }
718e3744 9701
05864da7
DS
9702 if (!json_path) {
9703 vty_out(vty, "\n");
9704 } else {
9705 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9706
05864da7 9707 json_object_array_add(json_paths, json_path);
14f51eba 9708 }
d62a17ae 9709}
718e3744 9710
d62a17ae 9711/* dampening route */
5f040085
DS
9712static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9713 struct bgp_path_info *path, int display,
9714 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9715 json_object *json_paths)
d62a17ae 9716{
e5be8c1d 9717 struct attr *attr = path->attr;
d62a17ae 9718 int len;
9719 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9720 json_object *json_path = NULL;
9721
9722 if (use_json)
9723 json_path = json_object_new_object();
d62a17ae 9724
9725 /* short status lead text */
e5be8c1d 9726 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9727
9728 /* print prefix and mask */
9729 if (!use_json) {
9730 if (!display)
7d3cae70 9731 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9732 else
9733 vty_out(vty, "%*s", 17, " ");
d62a17ae 9734
e5be8c1d
DA
9735 len = vty_out(vty, "%s", path->peer->host);
9736 len = 17 - len;
9737
9738 if (len < 1)
d62a17ae 9739 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9740 else
9741 vty_out(vty, "%*s", len, " ");
d62a17ae 9742
9b6d8fcf
DS
9743 vty_out(vty, "%s ",
9744 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9745 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9746 use_json, NULL));
d62a17ae 9747
e5be8c1d 9748 if (attr->aspath)
05864da7 9749 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9750
05864da7
DS
9751 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9752
d62a17ae 9753 vty_out(vty, "\n");
e5be8c1d
DA
9754 } else {
9755 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9756 safi, use_json, json_path);
9757
9758 if (attr->aspath)
9759 json_object_string_add(json_path, "asPath",
9760 attr->aspath->str);
9761
9762 json_object_string_add(json_path, "origin",
9763 bgp_origin_str[attr->origin]);
9764 json_object_string_add(json_path, "peerHost", path->peer->host);
9765
9766 json_object_array_add(json_paths, json_path);
9767 }
d62a17ae 9768}
718e3744 9769
d62a17ae 9770/* flap route */
5f040085
DS
9771static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9772 struct bgp_path_info *path, int display,
9773 afi_t afi, safi_t safi, bool use_json,
31258046 9774 json_object *json_paths)
784d3a42 9775{
31258046 9776 struct attr *attr = path->attr;
d62a17ae 9777 struct bgp_damp_info *bdi;
9778 char timebuf[BGP_UPTIME_LEN];
9779 int len;
31258046 9780 json_object *json_path = NULL;
784d3a42 9781
9b6d8fcf 9782 if (!path->extra)
d62a17ae 9783 return;
784d3a42 9784
31258046
DA
9785 if (use_json)
9786 json_path = json_object_new_object();
9787
9b6d8fcf 9788 bdi = path->extra->damp_info;
784d3a42 9789
d62a17ae 9790 /* short status lead text */
31258046 9791 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9792
d62a17ae 9793 if (!use_json) {
9794 if (!display)
7d3cae70 9795 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9796 else
9797 vty_out(vty, "%*s", 17, " ");
784d3a42 9798
31258046
DA
9799 len = vty_out(vty, "%s", path->peer->host);
9800 len = 16 - len;
9801 if (len < 1)
d62a17ae 9802 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9803 else
9804 vty_out(vty, "%*s", len, " ");
784d3a42 9805
31258046
DA
9806 len = vty_out(vty, "%d", bdi->flap);
9807 len = 5 - len;
9808 if (len < 1)
d62a17ae 9809 vty_out(vty, " ");
d62a17ae 9810 else
9811 vty_out(vty, "%*s", len, " ");
d62a17ae 9812
996c9314
LB
9813 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9814 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9815
31258046
DA
9816 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9817 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9818 vty_out(vty, "%s ",
9b6d8fcf 9819 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9820 BGP_UPTIME_LEN, afi,
31258046
DA
9821 safi, use_json, NULL));
9822 else
d62a17ae 9823 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9824
31258046 9825 if (attr->aspath)
05864da7 9826 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9827
05864da7
DS
9828 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9829
d62a17ae 9830 vty_out(vty, "\n");
31258046
DA
9831 } else {
9832 json_object_string_add(json_path, "peerHost", path->peer->host);
9833 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9834
9835 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9836 json_path);
9837
9838 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9839 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9840 bgp_damp_reuse_time_vty(vty, path, timebuf,
9841 BGP_UPTIME_LEN, afi, safi,
9842 use_json, json_path);
9843
9844 if (attr->aspath)
9845 json_object_string_add(json_path, "asPath",
9846 attr->aspath->str);
9847
9848 json_object_string_add(json_path, "origin",
9849 bgp_origin_str[attr->origin]);
9850
9851 json_object_array_add(json_paths, json_path);
9852 }
d62a17ae 9853}
9854
9855static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9856 int *first, const char *header,
9857 json_object *json_adv_to)
9858{
d62a17ae 9859 json_object *json_peer = NULL;
9860
9861 if (json_adv_to) {
9862 /* 'advertised-to' is a dictionary of peers we have advertised
9863 * this
9864 * prefix too. The key is the peer's IP or swpX, the value is
9865 * the
9866 * hostname if we know it and "" if not.
9867 */
9868 json_peer = json_object_new_object();
9869
9870 if (peer->hostname)
9871 json_object_string_add(json_peer, "hostname",
9872 peer->hostname);
9873
9874 if (peer->conf_if)
9875 json_object_object_add(json_adv_to, peer->conf_if,
9876 json_peer);
9877 else
47e12884
DA
9878 json_object_object_addf(json_adv_to, json_peer, "%pSU",
9879 &peer->su);
d62a17ae 9880 } else {
9881 if (*first) {
9882 vty_out(vty, "%s", header);
9883 *first = 0;
9884 }
9885
9886 if (peer->hostname
892fedb6 9887 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9888 if (peer->conf_if)
9889 vty_out(vty, " %s(%s)", peer->hostname,
9890 peer->conf_if);
9891 else
47e12884
DA
9892 vty_out(vty, " %s(%pSU)", peer->hostname,
9893 &peer->su);
d62a17ae 9894 } else {
9895 if (peer->conf_if)
9896 vty_out(vty, " %s", peer->conf_if);
9897 else
47e12884 9898 vty_out(vty, " %pSU", &peer->su);
d62a17ae 9899 }
9900 }
784d3a42
PG
9901}
9902
dcc68b5e
MS
9903static void route_vty_out_tx_ids(struct vty *vty,
9904 struct bgp_addpath_info_data *d)
9905{
9906 int i;
9907
9908 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9909 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9910 d->addpath_tx_id[i],
9911 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9912 }
9913}
9914
5e4d4c8a 9915static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9916 struct bgp_path_info *pi,
9917 struct attr *attr,
9918 json_object *json_path)
5e4d4c8a
AK
9919{
9920 char esi_buf[ESI_STR_LEN];
9921 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9922 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9923 ATTR_ES_PEER_ROUTER);
9924 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9925 ATTR_ES_PEER_ACTIVE);
9926 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9927 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9928 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9929 if (json_path) {
9930 json_object *json_es_info = NULL;
9931
9932 json_object_string_add(
9933 json_path, "esi",
9934 esi_buf);
9935 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9936 json_es_info = json_object_new_object();
9937 if (es_local)
9938 json_object_boolean_true_add(
9939 json_es_info, "localEs");
9940 if (peer_active)
9941 json_object_boolean_true_add(
9942 json_es_info, "peerActive");
9943 if (peer_proxy)
9944 json_object_boolean_true_add(
9945 json_es_info, "peerProxy");
9946 if (peer_router)
9947 json_object_boolean_true_add(
9948 json_es_info, "peerRouter");
9949 if (attr->mm_sync_seqnum)
9950 json_object_int_add(
9951 json_es_info, "peerSeq",
9952 attr->mm_sync_seqnum);
9953 json_object_object_add(
9954 json_path, "es_info",
9955 json_es_info);
9956 }
9957 } else {
9958 if (bgp_evpn_attr_is_sync(attr))
9959 vty_out(vty,
9960 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9961 esi_buf,
9962 es_local ? "local-es":"",
9963 peer_proxy ? "proxy " : "",
9964 peer_active ? "active ":"",
9965 peer_router ? "router ":"",
9966 attr->mm_sync_seqnum);
9967 else
9968 vty_out(vty, " ESI %s %s\n",
9969 esi_buf,
9970 es_local ? "local-es":"");
9971 }
9972}
9973
4933eaaf
DS
9974void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9975 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9976 enum rpki_states rpki_curr_state,
9977 json_object *json_paths)
d62a17ae 9978{
9979 char buf[INET6_ADDRSTRLEN];
9980 char buf1[BUFSIZ];
515c2602 9981 struct attr *attr = path->attr;
d62a17ae 9982 time_t tbuf;
9983 json_object *json_bestpath = NULL;
9984 json_object *json_cluster_list = NULL;
9985 json_object *json_cluster_list_list = NULL;
9986 json_object *json_ext_community = NULL;
9987 json_object *json_last_update = NULL;
7fd077aa 9988 json_object *json_pmsi = NULL;
d62a17ae 9989 json_object *json_nexthop_global = NULL;
9990 json_object *json_nexthop_ll = NULL;
9991 json_object *json_nexthops = NULL;
9992 json_object *json_path = NULL;
9993 json_object *json_peer = NULL;
9994 json_object *json_string = NULL;
9995 json_object *json_adv_to = NULL;
9996 int first = 0;
9997 struct listnode *node, *nnode;
9998 struct peer *peer;
be92fc9f 9999 bool addpath_capable;
d62a17ae 10000 int has_adj;
10001 unsigned int first_as;
1defdda8 10002 bool nexthop_self =
9b6d8fcf 10003 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10004 int i;
2ba93fd6
DA
10005 char *nexthop_hostname =
10006 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10007 uint32_t ttl = 0;
10008 uint32_t bos = 0;
10009 uint32_t exp = 0;
10010 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 10011
10012 if (json_paths) {
10013 json_path = json_object_new_object();
10014 json_peer = json_object_new_object();
10015 json_nexthop_global = json_object_new_object();
10016 }
10017
8304dabf
AD
10018 if (safi == SAFI_EVPN) {
10019 if (!json_paths)
10020 vty_out(vty, " Route %pRN", bn);
10021 }
10022
44c69747 10023 if (path->extra) {
b57ba6d2 10024 char tag_buf[30];
d62a17ae 10025
d62a17ae 10026 tag_buf[0] = '\0';
9b6d8fcf
DS
10027 if (path->extra && path->extra->num_labels) {
10028 bgp_evpn_label2str(path->extra->label,
10029 path->extra->num_labels, tag_buf,
a4d82a8a 10030 sizeof(tag_buf));
d62a17ae 10031 }
d7325ee7 10032 if (safi == SAFI_EVPN) {
44c69747 10033 if (!json_paths) {
44c69747
LK
10034 if (tag_buf[0] != '\0')
10035 vty_out(vty, " VNI %s", tag_buf);
44c69747 10036 } else {
77a2f8e5 10037 if (tag_buf[0]) {
44c69747
LK
10038 json_object_string_add(json_path, "VNI",
10039 tag_buf);
77a2f8e5
DA
10040 json_object_string_add(json_path, "vni",
10041 tag_buf);
10042 }
44c69747 10043 }
d7325ee7
DD
10044 }
10045
44c69747 10046 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 10047 struct bgp_path_info *parent_ri;
9bcb3eef 10048 struct bgp_dest *dest, *pdest;
d62a17ae 10049
9b6d8fcf 10050 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
10051 dest = parent_ri->net;
10052 if (dest && dest->pdest) {
10053 pdest = dest->pdest;
10054 prefix_rd2str(
10055 (struct prefix_rd *)bgp_dest_get_prefix(
10056 pdest),
10057 buf1, sizeof(buf1));
d7325ee7 10058 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 10059 vty_out(vty,
58bff4d1 10060 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
10061 buf1,
10062 (struct prefix_evpn *)
10063 bgp_dest_get_prefix(
10064 dest),
10065 tag_buf);
58bff4d1
AK
10066 if (attr->es_flags & ATTR_ES_L3_NHG)
10067 vty_out(vty, ", L3NHG %s",
10068 (attr->es_flags
10069 & ATTR_ES_L3_NHG_ACTIVE)
10070 ? "active"
10071 : "inactive");
10072 vty_out(vty, "\n");
10073
d7325ee7 10074 } else
2dbe669b
DA
10075 vty_out(vty,
10076 " Imported from %s:%pFX\n",
10077 buf1,
10078 (struct prefix_evpn *)
10079 bgp_dest_get_prefix(
10080 dest));
d62a17ae 10081 }
10082 }
10083 }
d62a17ae 10084
8304dabf
AD
10085 if (safi == SAFI_EVPN
10086 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10087 char gwip_buf[INET6_ADDRSTRLEN];
10088
860e740b
IR
10089 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10090 sizeof(gwip_buf));
8304dabf
AD
10091
10092 if (json_paths)
10093 json_object_string_add(json_path, "gatewayIP",
10094 gwip_buf);
10095 else
10096 vty_out(vty, " Gateway IP %s", gwip_buf);
10097 }
10098
2bf9780b 10099 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10100 vty_out(vty, "\n");
10101
05864da7
DS
10102 /* Line1 display AS-path, Aggregator */
10103 if (attr->aspath) {
10104 if (json_paths) {
10105 if (!attr->aspath->json)
10106 aspath_str_update(attr->aspath, true);
10107 json_object_lock(attr->aspath->json);
10108 json_object_object_add(json_path, "aspath",
10109 attr->aspath->json);
10110 } else {
10111 if (attr->aspath->segments)
10112 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10113 else
05864da7 10114 vty_out(vty, " Local");
d62a17ae 10115 }
05864da7 10116 }
d62a17ae 10117
05864da7
DS
10118 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10119 if (json_paths)
10120 json_object_boolean_true_add(json_path, "removed");
10121 else
10122 vty_out(vty, ", (removed)");
10123 }
d62a17ae 10124
05864da7
DS
10125 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10126 if (json_paths)
10127 json_object_boolean_true_add(json_path, "stale");
10128 else
10129 vty_out(vty, ", (stale)");
10130 }
d62a17ae 10131
05864da7
DS
10132 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10133 if (json_paths) {
10134 json_object_int_add(json_path, "aggregatorAs",
10135 attr->aggregator_as);
c949c771
DA
10136 json_object_string_addf(json_path, "aggregatorId",
10137 "%pI4", &attr->aggregator_addr);
05864da7 10138 } else {
88d495a9
DA
10139 vty_out(vty, ", (aggregated by %u %pI4)",
10140 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10141 }
05864da7 10142 }
d62a17ae 10143
05864da7
DS
10144 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10145 PEER_FLAG_REFLECTOR_CLIENT)) {
10146 if (json_paths)
10147 json_object_boolean_true_add(json_path,
10148 "rxedFromRrClient");
10149 else
10150 vty_out(vty, ", (Received from a RR-client)");
10151 }
d62a17ae 10152
05864da7
DS
10153 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10154 PEER_FLAG_RSERVER_CLIENT)) {
10155 if (json_paths)
10156 json_object_boolean_true_add(json_path,
10157 "rxedFromRsClient");
10158 else
10159 vty_out(vty, ", (Received from a RS-client)");
10160 }
d62a17ae 10161
05864da7
DS
10162 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10163 if (json_paths)
10164 json_object_boolean_true_add(json_path,
10165 "dampeningHistoryEntry");
10166 else
10167 vty_out(vty, ", (history entry)");
10168 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10169 if (json_paths)
10170 json_object_boolean_true_add(json_path,
10171 "dampeningSuppressed");
10172 else
10173 vty_out(vty, ", (suppressed due to dampening)");
10174 }
d62a17ae 10175
05864da7
DS
10176 if (!json_paths)
10177 vty_out(vty, "\n");
d62a17ae 10178
05864da7
DS
10179 /* Line2 display Next-hop, Neighbor, Router-id */
10180 /* Display the nexthop */
9bcb3eef 10181 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0 10182
7226bc40
TA
10183 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
10184 bn_p->family == AF_EVPN) &&
10185 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10186 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10187 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10188 || safi == SAFI_EVPN) {
515c2602 10189 if (json_paths) {
c949c771
DA
10190 json_object_string_addf(
10191 json_nexthop_global, "ip", "%pI4",
10192 &attr->mp_nexthop_global_in);
515c2602 10193
939a97f4 10194 if (path->peer->hostname)
515c2602
DA
10195 json_object_string_add(
10196 json_nexthop_global, "hostname",
939a97f4 10197 path->peer->hostname);
aef999a2
DA
10198 } else {
10199 if (nexthop_hostname)
10200 vty_out(vty, " %pI4(%s)",
10201 &attr->mp_nexthop_global_in,
10202 nexthop_hostname);
10203 else
10204 vty_out(vty, " %pI4",
10205 &attr->mp_nexthop_global_in);
10206 }
d62a17ae 10207 } else {
515c2602 10208 if (json_paths) {
c949c771
DA
10209 json_object_string_addf(json_nexthop_global,
10210 "ip", "%pI4",
10211 &attr->nexthop);
515c2602 10212
939a97f4 10213 if (path->peer->hostname)
515c2602
DA
10214 json_object_string_add(
10215 json_nexthop_global, "hostname",
939a97f4 10216 path->peer->hostname);
aef999a2
DA
10217 } else {
10218 if (nexthop_hostname)
10219 vty_out(vty, " %pI4(%s)",
10220 &attr->nexthop,
10221 nexthop_hostname);
10222 else
10223 vty_out(vty, " %pI4",
10224 &attr->nexthop);
10225 }
d62a17ae 10226 }
10227
05864da7
DS
10228 if (json_paths)
10229 json_object_string_add(json_nexthop_global, "afi",
10230 "ipv4");
10231 } else {
10232 if (json_paths) {
c949c771
DA
10233 json_object_string_addf(json_nexthop_global, "ip",
10234 "%pI6",
10235 &attr->mp_nexthop_global);
515c2602 10236
939a97f4 10237 if (path->peer->hostname)
515c2602
DA
10238 json_object_string_add(json_nexthop_global,
10239 "hostname",
939a97f4 10240 path->peer->hostname);
515c2602 10241
05864da7
DS
10242 json_object_string_add(json_nexthop_global, "afi",
10243 "ipv6");
10244 json_object_string_add(json_nexthop_global, "scope",
10245 "global");
10246 } else {
aef999a2
DA
10247 if (nexthop_hostname)
10248 vty_out(vty, " %pI6(%s)",
10249 &attr->mp_nexthop_global,
10250 nexthop_hostname);
10251 else
10252 vty_out(vty, " %pI6",
10253 &attr->mp_nexthop_global);
d62a17ae 10254 }
05864da7 10255 }
d62a17ae 10256
05864da7
DS
10257 /* Display the IGP cost or 'inaccessible' */
10258 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10259 if (json_paths)
10260 json_object_boolean_false_add(json_nexthop_global,
10261 "accessible");
10262 else
10263 vty_out(vty, " (inaccessible)");
10264 } else {
10265 if (path->extra && path->extra->igpmetric) {
d62a17ae 10266 if (json_paths)
05864da7
DS
10267 json_object_int_add(json_nexthop_global,
10268 "metric",
10269 path->extra->igpmetric);
d62a17ae 10270 else
05864da7
DS
10271 vty_out(vty, " (metric %u)",
10272 path->extra->igpmetric);
d62a17ae 10273 }
10274
05864da7 10275 /* IGP cost is 0, display this only for json */
d62a17ae 10276 else {
d62a17ae 10277 if (json_paths)
05864da7
DS
10278 json_object_int_add(json_nexthop_global,
10279 "metric", 0);
d62a17ae 10280 }
d62a17ae 10281
05864da7
DS
10282 if (json_paths)
10283 json_object_boolean_true_add(json_nexthop_global,
10284 "accessible");
10285 }
d62a17ae 10286
05864da7
DS
10287 /* Display peer "from" output */
10288 /* This path was originated locally */
10289 if (path->peer == bgp->peer_self) {
d62a17ae 10290
7226bc40
TA
10291 if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
10292 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10293 if (json_paths)
05864da7
DS
10294 json_object_string_add(json_peer, "peerId",
10295 "0.0.0.0");
d62a17ae 10296 else
05864da7
DS
10297 vty_out(vty, " from 0.0.0.0 ");
10298 } else {
d62a17ae 10299 if (json_paths)
05864da7
DS
10300 json_object_string_add(json_peer, "peerId",
10301 "::");
d62a17ae 10302 else
05864da7 10303 vty_out(vty, " from :: ");
d62a17ae 10304 }
d62a17ae 10305
4e9a9863 10306 if (json_paths)
c949c771
DA
10307 json_object_string_addf(json_peer, "routerId", "%pI4",
10308 &bgp->router_id);
4e9a9863 10309 else
23d0a753 10310 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10311 }
d62a17ae 10312
05864da7
DS
10313 /* We RXed this path from one of our peers */
10314 else {
10315
10316 if (json_paths) {
47e12884
DA
10317 json_object_string_addf(json_peer, "peerId", "%pSU",
10318 &path->peer->su);
c949c771
DA
10319 json_object_string_addf(json_peer, "routerId", "%pI4",
10320 &path->peer->remote_id);
05864da7
DS
10321
10322 if (path->peer->hostname)
10323 json_object_string_add(json_peer, "hostname",
10324 path->peer->hostname);
10325
10326 if (path->peer->domainname)
10327 json_object_string_add(json_peer, "domainname",
10328 path->peer->domainname);
10329
10330 if (path->peer->conf_if)
10331 json_object_string_add(json_peer, "interface",
10332 path->peer->conf_if);
10333 } else {
10334 if (path->peer->conf_if) {
10335 if (path->peer->hostname
892fedb6
DA
10336 && CHECK_FLAG(path->peer->bgp->flags,
10337 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10338 vty_out(vty, " from %s(%s)",
10339 path->peer->hostname,
10340 path->peer->conf_if);
d62a17ae 10341 else
05864da7 10342 vty_out(vty, " from %s",
9b6d8fcf 10343 path->peer->conf_if);
d62a17ae 10344 } else {
05864da7 10345 if (path->peer->hostname
892fedb6
DA
10346 && CHECK_FLAG(path->peer->bgp->flags,
10347 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10348 vty_out(vty, " from %s(%s)",
10349 path->peer->hostname,
10350 path->peer->host);
d62a17ae 10351 else
47e12884
DA
10352 vty_out(vty, " from %pSU",
10353 &path->peer->su);
d62a17ae 10354 }
d62a17ae 10355
05864da7 10356 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10357 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10358 else
10359 vty_out(vty, " (%s)",
10360 inet_ntop(AF_INET,
10361 &path->peer->remote_id, buf1,
10362 sizeof(buf1)));
d62a17ae 10363 }
05864da7 10364 }
9df8b37c 10365
05864da7
DS
10366 /*
10367 * Note when vrfid of nexthop is different from that of prefix
10368 */
10369 if (path->extra && path->extra->bgp_orig) {
10370 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10371
05864da7
DS
10372 if (json_paths) {
10373 const char *vn;
9df8b37c 10374
05864da7
DS
10375 if (path->extra->bgp_orig->inst_type
10376 == BGP_INSTANCE_TYPE_DEFAULT)
10377 vn = VRF_DEFAULT_NAME;
10378 else
10379 vn = path->extra->bgp_orig->name;
9df8b37c 10380
05864da7 10381 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10382
05864da7
DS
10383 if (nexthop_vrfid == VRF_UNKNOWN) {
10384 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10385 } else {
05864da7
DS
10386 json_object_int_add(json_path, "nhVrfId",
10387 (int)nexthop_vrfid);
9df8b37c 10388 }
05864da7
DS
10389 } else {
10390 if (nexthop_vrfid == VRF_UNKNOWN)
10391 vty_out(vty, " vrf ?");
137147c6
DS
10392 else {
10393 struct vrf *vrf;
10394
10395 vrf = vrf_lookup_by_id(nexthop_vrfid);
10396 vty_out(vty, " vrf %s(%u)",
10397 VRF_LOGNAME(vrf), nexthop_vrfid);
10398 }
9df8b37c 10399 }
05864da7 10400 }
9df8b37c 10401
05864da7
DS
10402 if (nexthop_self) {
10403 if (json_paths) {
10404 json_object_boolean_true_add(json_path,
10405 "announceNexthopSelf");
10406 } else {
10407 vty_out(vty, " announce-nh-self");
9df8b37c 10408 }
05864da7 10409 }
9df8b37c 10410
05864da7
DS
10411 if (!json_paths)
10412 vty_out(vty, "\n");
d62a17ae 10413
05864da7
DS
10414 /* display the link-local nexthop */
10415 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10416 if (json_paths) {
10417 json_nexthop_ll = json_object_new_object();
c949c771
DA
10418 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10419 &attr->mp_nexthop_local);
515c2602 10420
939a97f4 10421 if (path->peer->hostname)
515c2602
DA
10422 json_object_string_add(json_nexthop_ll,
10423 "hostname",
939a97f4 10424 path->peer->hostname);
515c2602 10425
05864da7
DS
10426 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10427 json_object_string_add(json_nexthop_ll, "scope",
10428 "link-local");
d62a17ae 10429
05864da7
DS
10430 json_object_boolean_true_add(json_nexthop_ll,
10431 "accessible");
d62a17ae 10432
05864da7 10433 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10434 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10435 "used");
10436 else
10437 json_object_boolean_true_add(
10438 json_nexthop_global, "used");
10439 } else {
10440 vty_out(vty, " (%s) %s\n",
10441 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10442 buf, INET6_ADDRSTRLEN),
10443 attr->mp_nexthop_prefer_global
10444 ? "(prefer-global)"
10445 : "(used)");
d62a17ae 10446 }
05864da7
DS
10447 }
10448 /* If we do not have a link-local nexthop then we must flag the
10449 global as "used" */
10450 else {
10451 if (json_paths)
10452 json_object_boolean_true_add(json_nexthop_global,
10453 "used");
10454 }
d62a17ae 10455
b5e140c8 10456 if (safi == SAFI_EVPN &&
5e4d4c8a 10457 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10458 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10459 }
10460
05864da7
DS
10461 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10462 * Int/Ext/Local, Atomic, best */
10463 if (json_paths)
10464 json_object_string_add(json_path, "origin",
10465 bgp_origin_long_str[attr->origin]);
10466 else
10467 vty_out(vty, " Origin %s",
10468 bgp_origin_long_str[attr->origin]);
9df8b37c 10469
05864da7 10470 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10471 if (json_paths)
05864da7 10472 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10473 else
05864da7
DS
10474 vty_out(vty, ", metric %u", attr->med);
10475 }
9df8b37c 10476
05864da7
DS
10477 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10478 if (json_paths)
0fbac0b4 10479 json_object_int_add(json_path, "locPrf",
05864da7
DS
10480 attr->local_pref);
10481 else
10482 vty_out(vty, ", localpref %u", attr->local_pref);
10483 }
9df8b37c 10484
05864da7
DS
10485 if (attr->weight != 0) {
10486 if (json_paths)
10487 json_object_int_add(json_path, "weight", attr->weight);
10488 else
10489 vty_out(vty, ", weight %u", attr->weight);
10490 }
9df8b37c 10491
05864da7
DS
10492 if (attr->tag != 0) {
10493 if (json_paths)
10494 json_object_int_add(json_path, "tag", attr->tag);
10495 else
10496 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10497 }
9df8b37c 10498
05864da7
DS
10499 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10500 if (json_paths)
10501 json_object_boolean_false_add(json_path, "valid");
10502 else
10503 vty_out(vty, ", invalid");
10504 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10505 if (json_paths)
10506 json_object_boolean_true_add(json_path, "valid");
10507 else
10508 vty_out(vty, ", valid");
10509 }
9df8b37c 10510
7d3cae70
DA
10511 if (json_paths)
10512 json_object_int_add(json_path, "version", bn->version);
10513
05864da7
DS
10514 if (path->peer != bgp->peer_self) {
10515 if (path->peer->as == path->peer->local_as) {
10516 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10517 if (json_paths)
10518 json_object_string_add(
10519 json_peer, "type",
10520 "confed-internal");
d62a17ae 10521 else
05864da7 10522 vty_out(vty, ", confed-internal");
d62a17ae 10523 } else {
05864da7
DS
10524 if (json_paths)
10525 json_object_string_add(
10526 json_peer, "type", "internal");
10527 else
10528 vty_out(vty, ", internal");
9df8b37c 10529 }
05864da7
DS
10530 } else {
10531 if (bgp_confederation_peers_check(bgp,
10532 path->peer->as)) {
10533 if (json_paths)
10534 json_object_string_add(
10535 json_peer, "type",
10536 "confed-external");
d62a17ae 10537 else
05864da7 10538 vty_out(vty, ", confed-external");
d62a17ae 10539 } else {
05864da7
DS
10540 if (json_paths)
10541 json_object_string_add(
10542 json_peer, "type", "external");
10543 else
10544 vty_out(vty, ", external");
d62a17ae 10545 }
10546 }
05864da7
DS
10547 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10548 if (json_paths) {
10549 json_object_boolean_true_add(json_path, "aggregated");
10550 json_object_boolean_true_add(json_path, "local");
10551 } else {
10552 vty_out(vty, ", aggregated, local");
10553 }
10554 } else if (path->type != ZEBRA_ROUTE_BGP) {
10555 if (json_paths)
10556 json_object_boolean_true_add(json_path, "sourced");
10557 else
10558 vty_out(vty, ", sourced");
10559 } else {
10560 if (json_paths) {
10561 json_object_boolean_true_add(json_path, "sourced");
10562 json_object_boolean_true_add(json_path, "local");
10563 } else {
10564 vty_out(vty, ", sourced, local");
d62a17ae 10565 }
05864da7 10566 }
718e3744 10567
05864da7 10568 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10569 if (json_paths)
05864da7
DS
10570 json_object_boolean_true_add(json_path,
10571 "atomicAggregate");
d62a17ae 10572 else
05864da7
DS
10573 vty_out(vty, ", atomic-aggregate");
10574 }
d62a17ae 10575
d864dd9e
EB
10576 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10577 if (json_paths)
10578 json_object_int_add(json_path, "otc", attr->otc);
10579 else
10580 vty_out(vty, ", otc %u", attr->otc);
10581 }
10582
05864da7
DS
10583 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10584 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10585 && bgp_path_info_mpath_count(path))) {
10586 if (json_paths)
10587 json_object_boolean_true_add(json_path, "multipath");
10588 else
10589 vty_out(vty, ", multipath");
10590 }
50e05855 10591
05864da7
DS
10592 // Mark the bestpath(s)
10593 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10594 first_as = aspath_get_first_as(attr->aspath);
718e3744 10595
05864da7
DS
10596 if (json_paths) {
10597 if (!json_bestpath)
10598 json_bestpath = json_object_new_object();
10599 json_object_int_add(json_bestpath, "bestpathFromAs",
10600 first_as);
10601 } else {
10602 if (first_as)
10603 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10604 else
05864da7 10605 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10606 }
05864da7 10607 }
718e3744 10608
05864da7
DS
10609 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10610 if (json_paths) {
10611 if (!json_bestpath)
10612 json_bestpath = json_object_new_object();
10613 json_object_boolean_true_add(json_bestpath, "overall");
10614 json_object_string_add(
10615 json_bestpath, "selectionReason",
10616 bgp_path_selection_reason2str(bn->reason));
10617 } else {
10618 vty_out(vty, ", best");
10619 vty_out(vty, " (%s)",
10620 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10621 }
05864da7 10622 }
718e3744 10623
4027d19b 10624 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10625 if (json_paths)
10626 json_object_string_add(
10627 json_path, "rpkiValidationState",
4027d19b 10628 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10629 else
1d327209 10630 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10631 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10632 }
10633
05864da7
DS
10634 if (json_bestpath)
10635 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10636
05864da7
DS
10637 if (!json_paths)
10638 vty_out(vty, "\n");
10639
10640 /* Line 4 display Community */
29e72930 10641 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10642 if (json_paths) {
9a706b42
DA
10643 if (!bgp_attr_get_community(attr)->json)
10644 community_str(bgp_attr_get_community(attr),
c0945b78 10645 true, true);
9a706b42
DA
10646 json_object_lock(bgp_attr_get_community(attr)->json);
10647 json_object_object_add(
10648 json_path, "community",
10649 bgp_attr_get_community(attr)->json);
05864da7
DS
10650 } else {
10651 vty_out(vty, " Community: %s\n",
9a706b42 10652 bgp_attr_get_community(attr)->str);
d62a17ae 10653 }
05864da7 10654 }
718e3744 10655
05864da7
DS
10656 /* Line 5 display Extended-community */
10657 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10658 if (json_paths) {
10659 json_ext_community = json_object_new_object();
b53e67a3
DA
10660 json_object_string_add(
10661 json_ext_community, "string",
10662 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10663 json_object_object_add(json_path, "extendedCommunity",
10664 json_ext_community);
d62a17ae 10665 } else {
05864da7 10666 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10667 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10668 }
05864da7 10669 }
718e3744 10670
05864da7
DS
10671 /* Line 6 display Large community */
10672 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10673 if (json_paths) {
1bcf3a96
DA
10674 if (!bgp_attr_get_lcommunity(attr)->json)
10675 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10676 true, true);
1bcf3a96
DA
10677 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10678 json_object_object_add(
10679 json_path, "largeCommunity",
10680 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10681 } else {
10682 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10683 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10684 }
05864da7 10685 }
718e3744 10686
05864da7
DS
10687 /* Line 7 display Originator, Cluster-id */
10688 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10689 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10690 char buf[BUFSIZ] = {0};
10691
05864da7 10692 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10693 if (json_paths)
c949c771
DA
10694 json_object_string_addf(json_path,
10695 "originatorId", "%pI4",
10696 &attr->originator_id);
d62a17ae 10697 else
23d0a753
DA
10698 vty_out(vty, " Originator: %pI4",
10699 &attr->originator_id);
d62a17ae 10700 }
856ca177 10701
05864da7 10702 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10703 struct cluster_list *cluster =
10704 bgp_attr_get_cluster(attr);
05864da7 10705 int i;
d62a17ae 10706
10707 if (json_paths) {
05864da7
DS
10708 json_cluster_list = json_object_new_object();
10709 json_cluster_list_list =
10710 json_object_new_array();
10711
779fee93 10712 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10713 json_string = json_object_new_string(
779fee93
DS
10714 inet_ntop(AF_INET,
10715 &cluster->list[i],
10716 buf, sizeof(buf)));
05864da7
DS
10717 json_object_array_add(
10718 json_cluster_list_list,
10719 json_string);
10720 }
718e3744 10721
05864da7
DS
10722 /*
10723 * struct cluster_list does not have
10724 * "str" variable like aspath and community
10725 * do. Add this someday if someone asks
10726 * for it.
10727 * json_object_string_add(json_cluster_list,
779fee93 10728 * "string", cluster->str);
05864da7
DS
10729 */
10730 json_object_object_add(json_cluster_list,
10731 "list",
10732 json_cluster_list_list);
10733 json_object_object_add(json_path, "clusterList",
10734 json_cluster_list);
0dc8ee70 10735 } else {
05864da7
DS
10736 vty_out(vty, ", Cluster list: ");
10737
779fee93 10738 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10739 vty_out(vty, "%pI4 ",
779fee93 10740 &cluster->list[i]);
05864da7 10741 }
0dc8ee70 10742 }
d62a17ae 10743 }
718e3744 10744
d62a17ae 10745 if (!json_paths)
10746 vty_out(vty, "\n");
05864da7 10747 }
d62a17ae 10748
05864da7 10749 if (path->extra && path->extra->damp_info)
b4f7f45b 10750 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10751
05864da7
DS
10752 /* Remote Label */
10753 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10754 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10755 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10756 &bos);
d62a17ae 10757
05864da7
DS
10758 if (json_paths)
10759 json_object_int_add(json_path, "remoteLabel", label);
10760 else
10761 vty_out(vty, " Remote label: %d\n", label);
10762 }
d62a17ae 10763
e496b420
HS
10764 /* Remote SID */
10765 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10766 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10767 if (json_paths)
10768 json_object_string_add(json_path, "remoteSid", buf);
10769 else
10770 vty_out(vty, " Remote SID: %s\n", buf);
10771 }
10772
05864da7
DS
10773 /* Label Index */
10774 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10775 if (json_paths)
10776 json_object_int_add(json_path, "labelIndex",
10777 attr->label_index);
10778 else
10779 vty_out(vty, " Label Index: %d\n",
10780 attr->label_index);
10781 }
d62a17ae 10782
05864da7
DS
10783 /* Line 8 display Addpath IDs */
10784 if (path->addpath_rx_id
10785 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10786 if (json_paths) {
10787 json_object_int_add(json_path, "addpathRxId",
10788 path->addpath_rx_id);
d62a17ae 10789
05864da7
DS
10790 /* Keep backwards compatibility with the old API
10791 * by putting TX All's ID in the old field
10792 */
10793 json_object_int_add(
10794 json_path, "addpathTxId",
10795 path->tx_addpath
10796 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10797
05864da7
DS
10798 /* ... but create a specific field for each
10799 * strategy
10800 */
10801 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10802 json_object_int_add(
10803 json_path,
10804 bgp_addpath_names(i)->id_json_name,
10805 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10806 }
05864da7
DS
10807 } else {
10808 vty_out(vty, " AddPath ID: RX %u, ",
10809 path->addpath_rx_id);
d62a17ae 10810
05864da7 10811 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10812 }
05864da7 10813 }
520d5d76 10814
05864da7
DS
10815 /* If we used addpath to TX a non-bestpath we need to display
10816 * "Advertised to" on a path-by-path basis
10817 */
10818 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10819 first = 1;
dcc68b5e 10820
05864da7
DS
10821 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10822 addpath_capable =
10823 bgp_addpath_encode_tx(peer, afi, safi);
10824 has_adj = bgp_adj_out_lookup(
10825 peer, path->net,
10826 bgp_addpath_id_for_peer(peer, afi, safi,
10827 &path->tx_addpath));
10828
10829 if ((addpath_capable && has_adj)
10830 || (!addpath_capable && has_adj
10831 && CHECK_FLAG(path->flags,
10832 BGP_PATH_SELECTED))) {
10833 if (json_path && !json_adv_to)
10834 json_adv_to = json_object_new_object();
dcc68b5e 10835
05864da7
DS
10836 route_vty_out_advertised_to(
10837 vty, peer, &first,
10838 " Advertised to:", json_adv_to);
d62a17ae 10839 }
10840 }
718e3744 10841
05864da7
DS
10842 if (json_path) {
10843 if (json_adv_to) {
10844 json_object_object_add(
10845 json_path, "advertisedTo", json_adv_to);
d62a17ae 10846 }
05864da7
DS
10847 } else {
10848 if (!first) {
10849 vty_out(vty, "\n");
d62a17ae 10850 }
10851 }
05864da7 10852 }
b05a1c8b 10853
05864da7 10854 /* Line 9 display Uptime */
083ec940 10855 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
10856 if (json_paths) {
10857 json_last_update = json_object_new_object();
10858 json_object_int_add(json_last_update, "epoch", tbuf);
10859 json_object_string_add(json_last_update, "string",
10860 ctime(&tbuf));
10861 json_object_object_add(json_path, "lastUpdate",
10862 json_last_update);
10863 } else
10864 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10865
05864da7
DS
10866 /* Line 10 display PMSI tunnel attribute, if present */
10867 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10868 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10869 bgp_attr_get_pmsi_tnl_type(attr),
10870 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10871
05864da7
DS
10872 if (json_paths) {
10873 json_pmsi = json_object_new_object();
10874 json_object_string_add(json_pmsi, "tunnelType", str);
10875 json_object_int_add(json_pmsi, "label",
10876 label2vni(&attr->label));
10877 json_object_object_add(json_path, "pmsi", json_pmsi);
10878 } else
10879 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10880 str, label2vni(&attr->label));
d62a17ae 10881 }
f1aa5d8a 10882
848e8cf6
DA
10883 if (path->peer->t_gr_restart &&
10884 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10885 unsigned long gr_remaining =
10886 thread_timer_remain_second(path->peer->t_gr_restart);
10887
10888 if (json_paths) {
10889 json_object_int_add(json_path,
10890 "gracefulRestartSecondsRemaining",
10891 gr_remaining);
10892 } else
10893 vty_out(vty,
10894 " Time until Graceful Restart stale route deleted: %lu\n",
10895 gr_remaining);
10896 }
10897
9a706b42
DA
10898 if (path->peer->t_llgr_stale[afi][safi] &&
10899 bgp_attr_get_community(attr) &&
10900 community_include(bgp_attr_get_community(attr),
10901 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10902 unsigned long llgr_remaining = thread_timer_remain_second(
10903 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10904
48ebba04
DA
10905 if (json_paths) {
10906 json_object_int_add(json_path, "llgrSecondsRemaining",
10907 llgr_remaining);
10908 } else
10909 vty_out(vty,
10910 " Time until Long-lived stale route deleted: %lu\n",
10911 llgr_remaining);
10912 }
10913
92269aa2
DS
10914 /* Output some debug about internal state of the dest flags */
10915 if (json_paths) {
10916 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10917 json_object_boolean_true_add(json_path, "processScheduled");
10918 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10919 json_object_boolean_true_add(json_path, "userCleared");
10920 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10921 json_object_boolean_true_add(json_path, "labelChanged");
10922 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10923 json_object_boolean_true_add(json_path, "registeredForLabel");
10924 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10925 json_object_boolean_true_add(json_path, "selectDefered");
10926 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10927 json_object_boolean_true_add(json_path, "fibInstalled");
10928 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10929 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10930
d62a17ae 10931 if (json_nexthop_global || json_nexthop_ll) {
10932 json_nexthops = json_object_new_array();
f1aa5d8a 10933
d62a17ae 10934 if (json_nexthop_global)
10935 json_object_array_add(json_nexthops,
10936 json_nexthop_global);
f1aa5d8a 10937
d62a17ae 10938 if (json_nexthop_ll)
10939 json_object_array_add(json_nexthops,
10940 json_nexthop_ll);
f1aa5d8a 10941
d62a17ae 10942 json_object_object_add(json_path, "nexthops",
10943 json_nexthops);
10944 }
10945
10946 json_object_object_add(json_path, "peer", json_peer);
10947 json_object_array_add(json_paths, json_path);
05864da7 10948 }
b366b518
BB
10949}
10950
96ade3ed 10951#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10952#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10953#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10954
a4d82a8a 10955static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10956 afi_t afi, safi_t safi, enum bgp_show_type type,
10957 bool use_json);
7f323236
DW
10958static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10959 const char *comstr, int exact, afi_t afi,
96c81f66 10960 safi_t safi, uint16_t show_flags);
d62a17ae 10961
1ae44dfc 10962static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10963 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10964 void *output_arg, const char *rd, int is_last,
96f3485c 10965 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10966 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10967 enum rpki_states rpki_target_state)
d62a17ae 10968{
40381db7 10969 struct bgp_path_info *pi;
9bcb3eef 10970 struct bgp_dest *dest;
2aad8c42
MS
10971 bool header = true;
10972 bool json_detail_header = false;
d62a17ae 10973 int display;
1ae44dfc
LB
10974 unsigned long output_count = 0;
10975 unsigned long total_count = 0;
d62a17ae 10976 struct prefix *p;
d62a17ae 10977 json_object *json_paths = NULL;
10978 int first = 1;
96f3485c
MK
10979 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10980 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10981 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10982
1ae44dfc 10983 if (output_cum && *output_cum != 0)
2aad8c42 10984 header = false;
1ae44dfc 10985
9386b588 10986 if (use_json && !*json_header_depth) {
96f3485c
MK
10987 if (all)
10988 *json_header_depth = 1;
10989 else {
10990 vty_out(vty, "{\n");
10991 *json_header_depth = 2;
10992 }
10993
d62a17ae 10994 vty_out(vty,
23d0a753
DA
10995 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10996 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10997 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10998 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10999 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11000 ? VRF_DEFAULT_NAME
11001 : bgp->name,
11002 table->version, &bgp->router_id,
01eced22 11003 bgp->default_local_pref, bgp->as);
9386b588 11004 if (rd) {
445c2480 11005 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11006 ++*json_header_depth;
11007 }
d62a17ae 11008 }
718e3744 11009
445c2480
DS
11010 if (use_json && rd) {
11011 vty_out(vty, " \"%s\" : { ", rd);
11012 }
11013
2aad8c42
MS
11014 /* Check for 'json detail', where we need header output once per dest */
11015 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
11016 type != bgp_show_type_dampend_paths &&
11017 type != bgp_show_type_damp_neighbor &&
11018 type != bgp_show_type_flap_statistics &&
11019 type != bgp_show_type_flap_neighbor)
11020 json_detail_header = true;
11021
d62a17ae 11022 /* Start processing of routes. */
9bcb3eef
DS
11023 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11024 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11025 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11026 bool json_detail = json_detail_header;
b54892e0 11027
9bcb3eef 11028 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11029 if (pi == NULL)
98ce9a06 11030 continue;
d62a17ae 11031
98ce9a06 11032 display = 0;
98ce9a06
DS
11033 if (use_json)
11034 json_paths = json_object_new_array();
11035 else
11036 json_paths = NULL;
d62a17ae 11037
6f94b685 11038 for (; pi; pi = pi->next) {
9a706b42
DA
11039 struct community *picomm = NULL;
11040
11041 picomm = bgp_attr_get_community(pi->attr);
11042
98ce9a06 11043 total_count++;
1e2ce4f1 11044
7d3cae70
DA
11045 if (type == bgp_show_type_prefix_version) {
11046 uint32_t version =
11047 strtoul(output_arg, NULL, 10);
11048 if (dest->version < version)
11049 continue;
11050 }
11051
a70a28a5
DA
11052 if (type == bgp_show_type_community_alias) {
11053 char *alias = output_arg;
11054 char **communities;
11055 int num;
11056 bool found = false;
11057
9a706b42
DA
11058 if (picomm) {
11059 frrstr_split(picomm->str, " ",
11060 &communities, &num);
a70a28a5
DA
11061 for (int i = 0; i < num; i++) {
11062 const char *com2alias =
11063 bgp_community2alias(
11064 communities[i]);
cd9cc0e6
IR
11065 if (!found
11066 && strcmp(alias, com2alias)
11067 == 0)
a70a28a5 11068 found = true;
cd9cc0e6
IR
11069 XFREE(MTYPE_TMP,
11070 communities[i]);
a70a28a5 11071 }
cd9cc0e6 11072 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11073 }
11074
1bcf3a96
DA
11075 if (!found &&
11076 bgp_attr_get_lcommunity(pi->attr)) {
11077 frrstr_split(bgp_attr_get_lcommunity(
11078 pi->attr)
11079 ->str,
a70a28a5
DA
11080 " ", &communities, &num);
11081 for (int i = 0; i < num; i++) {
11082 const char *com2alias =
11083 bgp_community2alias(
11084 communities[i]);
cd9cc0e6
IR
11085 if (!found
11086 && strcmp(alias, com2alias)
11087 == 0)
a70a28a5 11088 found = true;
cd9cc0e6
IR
11089 XFREE(MTYPE_TMP,
11090 communities[i]);
a70a28a5 11091 }
cd9cc0e6 11092 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11093 }
11094
11095 if (!found)
11096 continue;
11097 }
11098
1e2ce4f1
DS
11099 if (type == bgp_show_type_rpki) {
11100 if (dest_p->family == AF_INET
11101 || dest_p->family == AF_INET6)
4027d19b 11102 rpki_curr_state = hook_call(
1e2ce4f1
DS
11103 bgp_rpki_prefix_status,
11104 pi->peer, pi->attr, dest_p);
4027d19b
DS
11105 if (rpki_target_state != RPKI_NOT_BEING_USED
11106 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11107 continue;
11108 }
11109
98ce9a06
DS
11110 if (type == bgp_show_type_flap_statistics
11111 || type == bgp_show_type_flap_neighbor
11112 || type == bgp_show_type_dampend_paths
11113 || type == bgp_show_type_damp_neighbor) {
40381db7 11114 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11115 continue;
11116 }
11117 if (type == bgp_show_type_regexp) {
11118 regex_t *regex = output_arg;
d62a17ae 11119
40381db7 11120 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11121 == REG_NOMATCH)
11122 continue;
11123 }
11124 if (type == bgp_show_type_prefix_list) {
11125 struct prefix_list *plist = output_arg;
d62a17ae 11126
9bcb3eef 11127 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11128 != PREFIX_PERMIT)
11129 continue;
11130 }
ed126382
DA
11131 if (type == bgp_show_type_access_list) {
11132 struct access_list *alist = output_arg;
11133
11134 if (access_list_apply(alist, dest_p) !=
11135 FILTER_PERMIT)
11136 continue;
11137 }
98ce9a06
DS
11138 if (type == bgp_show_type_filter_list) {
11139 struct as_list *as_list = output_arg;
d62a17ae 11140
40381db7 11141 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11142 != AS_FILTER_PERMIT)
11143 continue;
11144 }
11145 if (type == bgp_show_type_route_map) {
11146 struct route_map *rmap = output_arg;
9b6d8fcf 11147 struct bgp_path_info path;
98ce9a06 11148 struct attr dummy_attr;
b68885f9 11149 route_map_result_t ret;
d62a17ae 11150
6f4f49b2 11151 dummy_attr = *pi->attr;
d62a17ae 11152
40381db7 11153 path.peer = pi->peer;
9b6d8fcf 11154 path.attr = &dummy_attr;
d62a17ae 11155
1782514f 11156 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11157 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11158 if (ret == RMAP_DENYMATCH)
11159 continue;
11160 }
11161 if (type == bgp_show_type_neighbor
11162 || type == bgp_show_type_flap_neighbor
11163 || type == bgp_show_type_damp_neighbor) {
11164 union sockunion *su = output_arg;
11165
40381db7
DS
11166 if (pi->peer == NULL
11167 || pi->peer->su_remote == NULL
11168 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11169 continue;
11170 }
11171 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11172 uint32_t destination;
d62a17ae 11173
9bcb3eef 11174 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11175 if (IN_CLASSC(destination)
9bcb3eef 11176 && dest_p->prefixlen == 24)
98ce9a06
DS
11177 continue;
11178 if (IN_CLASSB(destination)
9bcb3eef 11179 && dest_p->prefixlen == 16)
98ce9a06
DS
11180 continue;
11181 if (IN_CLASSA(destination)
9bcb3eef 11182 && dest_p->prefixlen == 8)
98ce9a06
DS
11183 continue;
11184 }
11185 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11186 p = output_arg;
9bcb3eef 11187 if (!prefix_match(p, dest_p))
98ce9a06
DS
11188 continue;
11189 }
11190 if (type == bgp_show_type_community_all) {
9a706b42 11191 if (!picomm)
98ce9a06
DS
11192 continue;
11193 }
11194 if (type == bgp_show_type_community) {
11195 struct community *com = output_arg;
d62a17ae 11196
9a706b42 11197 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11198 continue;
11199 }
11200 if (type == bgp_show_type_community_exact) {
11201 struct community *com = output_arg;
d62a17ae 11202
9a706b42 11203 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11204 continue;
11205 }
11206 if (type == bgp_show_type_community_list) {
11207 struct community_list *list = output_arg;
d62a17ae 11208
9a706b42 11209 if (!community_list_match(picomm, list))
98ce9a06
DS
11210 continue;
11211 }
a4d82a8a 11212 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11213 struct community_list *list = output_arg;
d62a17ae 11214
9a706b42 11215 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11216 continue;
11217 }
11218 if (type == bgp_show_type_lcommunity) {
11219 struct lcommunity *lcom = output_arg;
d62a17ae 11220
1bcf3a96
DA
11221 if (!bgp_attr_get_lcommunity(pi->attr) ||
11222 !lcommunity_match(
11223 bgp_attr_get_lcommunity(pi->attr),
11224 lcom))
98ce9a06
DS
11225 continue;
11226 }
36a206db 11227
11228 if (type == bgp_show_type_lcommunity_exact) {
11229 struct lcommunity *lcom = output_arg;
11230
1bcf3a96
DA
11231 if (!bgp_attr_get_lcommunity(pi->attr) ||
11232 !lcommunity_cmp(
11233 bgp_attr_get_lcommunity(pi->attr),
11234 lcom))
36a206db 11235 continue;
11236 }
98ce9a06
DS
11237 if (type == bgp_show_type_lcommunity_list) {
11238 struct community_list *list = output_arg;
d62a17ae 11239
1bcf3a96
DA
11240 if (!lcommunity_list_match(
11241 bgp_attr_get_lcommunity(pi->attr),
11242 list))
98ce9a06
DS
11243 continue;
11244 }
36a206db 11245 if (type
11246 == bgp_show_type_lcommunity_list_exact) {
11247 struct community_list *list = output_arg;
11248
11249 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11250 bgp_attr_get_lcommunity(pi->attr),
11251 list))
36a206db 11252 continue;
11253 }
98ce9a06 11254 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11255 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11256 continue;
11257 }
11258 if (type == bgp_show_type_dampend_paths
11259 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11260 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11261 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11262 continue;
11263 }
11264
11265 if (!use_json && header) {
23d0a753
DA
11266 vty_out(vty,
11267 "BGP table version is %" PRIu64
11268 ", local router ID is %pI4, vrf id ",
11269 table->version, &bgp->router_id);
9df8b37c
PZ
11270 if (bgp->vrf_id == VRF_UNKNOWN)
11271 vty_out(vty, "%s", VRFID_NONE_STR);
11272 else
11273 vty_out(vty, "%u", bgp->vrf_id);
11274 vty_out(vty, "\n");
01eced22
AD
11275 vty_out(vty, "Default local pref %u, ",
11276 bgp->default_local_pref);
11277 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11278 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11279 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11280 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11281 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11282 if (type == bgp_show_type_dampend_paths
11283 || type == bgp_show_type_damp_neighbor)
98ce9a06 11284 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11285 else if (type == bgp_show_type_flap_statistics
11286 || type == bgp_show_type_flap_neighbor)
98ce9a06 11287 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11288 else
ae248832
MK
11289 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11290 : BGP_SHOW_HEADER));
2aad8c42
MS
11291 header = false;
11292
11293 } else if (json_detail && json_paths != NULL) {
11294 const struct prefix_rd *prd;
11295 json_object *jtemp;
11296
11297 /* Use common detail header, for most types;
11298 * need a json 'object'.
11299 */
11300
11301 jtemp = json_object_new_object();
11302 prd = bgp_rd_from_dest(dest, safi);
11303
11304 route_vty_out_detail_header(
11305 vty, bgp, dest, prd, table->afi,
11306 safi, jtemp);
11307
11308 json_object_array_add(json_paths, jtemp);
11309
11310 json_detail = false;
d62a17ae 11311 }
2aad8c42 11312
98ce9a06
DS
11313 if (rd != NULL && !display && !output_count) {
11314 if (!use_json)
11315 vty_out(vty,
11316 "Route Distinguisher: %s\n",
11317 rd);
d62a17ae 11318 }
98ce9a06
DS
11319 if (type == bgp_show_type_dampend_paths
11320 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11321 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11322 AFI_IP, safi, use_json,
11323 json_paths);
98ce9a06
DS
11324 else if (type == bgp_show_type_flap_statistics
11325 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11326 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11327 AFI_IP, safi, use_json,
11328 json_paths);
f280c93b
DA
11329 else {
11330 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11331 route_vty_out_detail(
11332 vty, bgp, dest, pi,
11333 family2afi(dest_p->family),
11334 safi, RPKI_NOT_BEING_USED,
11335 json_paths);
11336 else
11337 route_vty_out(vty, dest_p, pi, display,
11338 safi, json_paths, wide);
11339 }
98ce9a06 11340 display++;
d62a17ae 11341 }
11342
98ce9a06
DS
11343 if (display) {
11344 output_count++;
11345 if (!use_json)
11346 continue;
11347
625d2931 11348 /* encode prefix */
9bcb3eef 11349 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11350 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11351
1840384b 11352
b54892e0
DS
11353 bgp_fs_nlri_get_string(
11354 (unsigned char *)
9bcb3eef
DS
11355 dest_p->u.prefix_flowspec.ptr,
11356 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11357 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11358 family2afi(dest_p->u
11359 .prefix_flowspec.family));
625d2931 11360 if (first)
b54892e0 11361 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11362 dest_p->u.prefix_flowspec
b54892e0 11363 .prefixlen);
625d2931 11364 else
b54892e0 11365 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11366 dest_p->u.prefix_flowspec
b54892e0 11367 .prefixlen);
625d2931 11368 } else {
625d2931 11369 if (first)
1b78780b 11370 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11371 else
1b78780b 11372 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11373 }
3757f964 11374 vty_json(vty, json_paths);
449feb8e 11375 json_paths = NULL;
98ce9a06 11376 first = 0;
1f83ed02
DS
11377 } else
11378 json_object_free(json_paths);
98ce9a06
DS
11379 }
11380
1ae44dfc
LB
11381 if (output_cum) {
11382 output_count += *output_cum;
11383 *output_cum = output_count;
11384 }
11385 if (total_cum) {
11386 total_count += *total_cum;
11387 *total_cum = total_count;
11388 }
d62a17ae 11389 if (use_json) {
9386b588 11390 if (rd) {
a4d82a8a 11391 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11392 }
11393 if (is_last) {
a4d82a8a
PZ
11394 unsigned long i;
11395 for (i = 0; i < *json_header_depth; ++i)
11396 vty_out(vty, " } ");
96f3485c
MK
11397 if (!all)
11398 vty_out(vty, "\n");
9386b588 11399 }
d62a17ae 11400 } else {
1ae44dfc
LB
11401 if (is_last) {
11402 /* No route is displayed */
11403 if (output_count == 0) {
11404 if (type == bgp_show_type_normal)
11405 vty_out(vty,
11406 "No BGP prefixes displayed, %ld exist\n",
11407 total_count);
11408 } else
d62a17ae 11409 vty_out(vty,
1ae44dfc
LB
11410 "\nDisplayed %ld routes and %ld total paths\n",
11411 output_count, total_count);
11412 }
d62a17ae 11413 }
718e3744 11414
d62a17ae 11415 return CMD_SUCCESS;
718e3744 11416}
11417
1ae44dfc
LB
11418int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11419 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11420 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11421{
9bcb3eef 11422 struct bgp_dest *dest, *next;
1ae44dfc
LB
11423 unsigned long output_cum = 0;
11424 unsigned long total_cum = 0;
9386b588 11425 unsigned long json_header_depth = 0;
67009e22 11426 struct bgp_table *itable;
0136788c 11427 bool show_msg;
96c81f66 11428 uint16_t show_flags = 0;
0136788c
LB
11429
11430 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11431
96f3485c
MK
11432 if (use_json)
11433 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11434
9bcb3eef
DS
11435 for (dest = bgp_table_top(table); dest; dest = next) {
11436 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11437
9bcb3eef
DS
11438 next = bgp_route_next(dest);
11439 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11440 continue;
67009e22 11441
9bcb3eef 11442 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11443 if (itable != NULL) {
1ae44dfc 11444 struct prefix_rd prd;
06b9f471 11445 char rd[RD_ADDRSTRLEN];
1ae44dfc 11446
9bcb3eef 11447 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11448 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11449 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11450 rd, next == NULL, &output_cum,
11451 &total_cum, &json_header_depth,
1e2ce4f1 11452 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11453 if (next == NULL)
11454 show_msg = false;
1ae44dfc
LB
11455 }
11456 }
0136788c
LB
11457 if (show_msg) {
11458 if (output_cum == 0)
11459 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11460 total_cum);
11461 else
11462 vty_out(vty,
11463 "\nDisplayed %ld routes and %ld total paths\n",
11464 output_cum, total_cum);
11465 }
1ae44dfc
LB
11466 return CMD_SUCCESS;
11467}
2aad8c42 11468
d62a17ae 11469static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11470 enum bgp_show_type type, void *output_arg,
96c81f66 11471 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11472{
d62a17ae 11473 struct bgp_table *table;
9386b588 11474 unsigned long json_header_depth = 0;
96f3485c 11475 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11476
d62a17ae 11477 if (bgp == NULL) {
11478 bgp = bgp_get_default();
11479 }
fee0f4c6 11480
d62a17ae 11481 if (bgp == NULL) {
11482 if (!use_json)
11483 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11484 else
11485 vty_out(vty, "{}\n");
d62a17ae 11486 return CMD_WARNING;
11487 }
4dd6177e 11488
cd8c2a27
MS
11489 /* Labeled-unicast routes live in the unicast table. */
11490 if (safi == SAFI_LABELED_UNICAST)
11491 safi = SAFI_UNICAST;
11492
1ae44dfc 11493 table = bgp->rib[afi][safi];
d62a17ae 11494 /* use MPLS and ENCAP specific shows until they are merged */
11495 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11496 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11497 output_arg, use_json);
d62a17ae 11498 }
dba3c1d3
PG
11499
11500 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11501 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11502 output_arg, use_json,
11503 1, NULL, NULL);
11504 }
fee0f4c6 11505
96f3485c 11506 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11507 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11508 rpki_target_state);
fee0f4c6 11509}
11510
d62a17ae 11511static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11512 safi_t safi, uint16_t show_flags)
f186de26 11513{
d62a17ae 11514 struct listnode *node, *nnode;
11515 struct bgp *bgp;
11516 int is_first = 1;
9f049418 11517 bool route_output = false;
96f3485c 11518 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11519
d62a17ae 11520 if (use_json)
11521 vty_out(vty, "{\n");
9f689658 11522
d62a17ae 11523 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11524 route_output = true;
d62a17ae 11525 if (use_json) {
11526 if (!is_first)
11527 vty_out(vty, ",\n");
11528 else
11529 is_first = 0;
11530
11531 vty_out(vty, "\"%s\":",
11532 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11533 ? VRF_DEFAULT_NAME
d62a17ae 11534 : bgp->name);
11535 } else {
11536 vty_out(vty, "\nInstance %s:\n",
11537 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11538 ? VRF_DEFAULT_NAME
d62a17ae 11539 : bgp->name);
11540 }
11541 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11542 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11543 }
9f689658 11544
d62a17ae 11545 if (use_json)
11546 vty_out(vty, "}\n");
9f049418
DS
11547 else if (!route_output)
11548 vty_out(vty, "%% BGP instance not found\n");
f186de26 11549}
11550
718e3744 11551/* Header of detailed BGP route information */
d62a17ae 11552void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11553 struct bgp_dest *dest,
11554 const struct prefix_rd *prd,
d62a17ae 11555 afi_t afi, safi_t safi, json_object *json)
11556{
40381db7 11557 struct bgp_path_info *pi;
b54892e0 11558 const struct prefix *p;
d62a17ae 11559 struct peer *peer;
11560 struct listnode *node, *nnode;
06b9f471 11561 char buf1[RD_ADDRSTRLEN];
d62a17ae 11562 int count = 0;
11563 int best = 0;
11564 int suppress = 0;
c5f1e1b2
C
11565 int accept_own = 0;
11566 int route_filter_translated_v4 = 0;
11567 int route_filter_v4 = 0;
11568 int route_filter_translated_v6 = 0;
11569 int route_filter_v6 = 0;
11570 int llgr_stale = 0;
11571 int no_llgr = 0;
11572 int accept_own_nexthop = 0;
11573 int blackhole = 0;
d62a17ae 11574 int no_export = 0;
11575 int no_advertise = 0;
11576 int local_as = 0;
c5f1e1b2 11577 int no_peer = 0;
d62a17ae 11578 int first = 1;
11579 int has_valid_label = 0;
11580 mpls_label_t label = 0;
11581 json_object *json_adv_to = NULL;
67f67ba4
DA
11582 uint32_t ttl = 0;
11583 uint32_t bos = 0;
11584 uint32_t exp = 0;
9bedbb1e 11585
67f67ba4 11586 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11587
67f67ba4
DA
11588 p = bgp_dest_get_prefix(dest);
11589 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11590
44c69747 11591 if (safi == SAFI_EVPN) {
44c69747 11592 if (!json) {
2dbe669b 11593 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11594 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11595 : "",
2dbe669b 11596 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11597 } else {
11598 json_object_string_add(json, "rd",
11599 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11600 "");
11601 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11602 }
11603 } else {
11604 if (!json) {
9119ef3a
DA
11605 vty_out(vty,
11606 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11607 "\n",
d62a17ae 11608 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11609 ? prefix_rd2str(prd, buf1,
11610 sizeof(buf1))
11611 : ""),
9119ef3a
DA
11612 safi == SAFI_MPLS_VPN ? ":" : "", p,
11613 dest->version);
cd1964ff 11614
9119ef3a 11615 } else {
67d7e256 11616 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11617 json_object_int_add(json, "version", dest->version);
11618
11619 }
44c69747
LK
11620 }
11621
11622 if (has_valid_label) {
11623 if (json)
11624 json_object_int_add(json, "localLabel", label);
11625 else
d62a17ae 11626 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11627 }
11628
11629 if (!json)
d62a17ae 11630 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11631 vty_out(vty, "not allocated\n");
718e3744 11632
9bcb3eef 11633 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11634 struct community *picomm = NULL;
11635
11636 picomm = bgp_attr_get_community(pi->attr);
11637
d62a17ae 11638 count++;
40381db7 11639 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11640 best = count;
4056a5f6 11641 if (bgp_path_suppressed(pi))
d62a17ae 11642 suppress = 1;
cee9c031 11643
9a706b42 11644 if (!picomm)
cee9c031
QY
11645 continue;
11646
11647 no_advertise += community_include(
9a706b42
DA
11648 picomm, COMMUNITY_NO_ADVERTISE);
11649 no_export +=
11650 community_include(picomm, COMMUNITY_NO_EXPORT);
11651 local_as +=
11652 community_include(picomm, COMMUNITY_LOCAL_AS);
11653 accept_own +=
11654 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11655 route_filter_translated_v4 += community_include(
9a706b42 11656 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11657 route_filter_translated_v6 += community_include(
9a706b42 11658 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11659 route_filter_v4 += community_include(
9a706b42 11660 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11661 route_filter_v6 += community_include(
9a706b42
DA
11662 picomm, COMMUNITY_ROUTE_FILTER_v6);
11663 llgr_stale +=
11664 community_include(picomm, COMMUNITY_LLGR_STALE);
11665 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11666 accept_own_nexthop += community_include(
11667 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11668 blackhole +=
11669 community_include(picomm, COMMUNITY_BLACKHOLE);
11670 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11671 }
718e3744 11672 }
718e3744 11673
d62a17ae 11674 if (!json) {
11675 vty_out(vty, "Paths: (%d available", count);
11676 if (best) {
11677 vty_out(vty, ", best #%d", best);
b84060bb
PG
11678 if (safi == SAFI_UNICAST) {
11679 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11680 vty_out(vty, ", table %s",
11681 VRF_DEFAULT_NAME);
11682 else
11683 vty_out(vty, ", vrf %s",
11684 bgp->name);
11685 }
d62a17ae 11686 } else
11687 vty_out(vty, ", no best path");
11688
c5f1e1b2
C
11689 if (accept_own)
11690 vty_out(vty,
11691 ", accept own local route exported and imported in different VRF");
11692 else if (route_filter_translated_v4)
11693 vty_out(vty,
11694 ", mark translated RTs for VPNv4 route filtering");
11695 else if (route_filter_v4)
11696 vty_out(vty,
11697 ", attach RT as-is for VPNv4 route filtering");
11698 else if (route_filter_translated_v6)
11699 vty_out(vty,
11700 ", mark translated RTs for VPNv6 route filtering");
11701 else if (route_filter_v6)
11702 vty_out(vty,
11703 ", attach RT as-is for VPNv6 route filtering");
11704 else if (llgr_stale)
11705 vty_out(vty,
1479ed2f 11706 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11707 else if (no_llgr)
11708 vty_out(vty,
11709 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11710 else if (accept_own_nexthop)
11711 vty_out(vty,
11712 ", accept local nexthop");
11713 else if (blackhole)
11714 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11715 else if (no_export)
11716 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11717 else if (no_advertise)
11718 vty_out(vty, ", not advertised to any peer");
d62a17ae 11719 else if (local_as)
11720 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11721 else if (no_peer)
11722 vty_out(vty,
11723 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11724
11725 if (suppress)
11726 vty_out(vty,
11727 ", Advertisements suppressed by an aggregate.");
11728 vty_out(vty, ")\n");
11729 }
718e3744 11730
d62a17ae 11731 /* If we are not using addpath then we can display Advertised to and
11732 * that will
11733 * show what peers we advertised the bestpath to. If we are using
11734 * addpath
11735 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11736 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11737 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11738 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11739 if (json && !json_adv_to)
11740 json_adv_to = json_object_new_object();
11741
11742 route_vty_out_advertised_to(
11743 vty, peer, &first,
11744 " Advertised to non peer-group peers:\n ",
11745 json_adv_to);
11746 }
11747 }
11748
11749 if (json) {
11750 if (json_adv_to) {
11751 json_object_object_add(json, "advertisedTo",
11752 json_adv_to);
11753 }
11754 } else {
11755 if (first)
11756 vty_out(vty, " Not advertised to any peer");
11757 vty_out(vty, "\n");
11758 }
11759 }
718e3744 11760}
11761
edfee30d 11762static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11763 struct bgp_dest *bgp_node, struct vty *vty,
11764 struct bgp *bgp, afi_t afi, safi_t safi,
11765 json_object *json, enum bgp_path_type pathtype,
4027d19b 11766 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11767{
11768 struct bgp_path_info *pi;
11769 int header = 1;
11770 char rdbuf[RD_ADDRSTRLEN];
11771 json_object *json_header = NULL;
11772 json_object *json_paths = NULL;
4933eaaf 11773 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11774
9bcb3eef 11775 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11776 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11777
11778 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11779 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11780 pi->peer, pi->attr, p);
4933eaaf 11781
4027d19b
DS
11782 if (rpki_target_state != RPKI_NOT_BEING_USED
11783 && rpki_curr_state != rpki_target_state)
4933eaaf 11784 continue;
44c69747
LK
11785
11786 if (json && !json_paths) {
11787 /* Instantiate json_paths only if path is valid */
11788 json_paths = json_object_new_array();
11789 if (pfx_rd) {
11790 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11791 json_header = json_object_new_object();
11792 } else
11793 json_header = json;
11794 }
11795
11796 if (header) {
11797 route_vty_out_detail_header(
11798 vty, bgp, bgp_node, pfx_rd,
11799 AFI_IP, safi, json_header);
11800 header = 0;
11801 }
11802 (*display)++;
11803
11804 if (pathtype == BGP_PATH_SHOW_ALL
11805 || (pathtype == BGP_PATH_SHOW_BESTPATH
11806 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11807 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11808 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11809 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11810 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11811 safi, rpki_curr_state, json_paths);
44c69747
LK
11812 }
11813
11814 if (json && json_paths) {
11815 json_object_object_add(json_header, "paths", json_paths);
11816
11817 if (pfx_rd)
11818 json_object_object_add(json, rdbuf, json_header);
11819 }
11820}
11821
2aad8c42
MS
11822/*
11823 * Return rd based on safi
11824 */
11825static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11826 safi_t safi)
11827{
11828 switch (safi) {
11829 case SAFI_MPLS_VPN:
11830 case SAFI_ENCAP:
11831 case SAFI_EVPN:
11832 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11833 default:
11834 return NULL;
11835
11836 }
11837}
11838
718e3744 11839/* Display specified route of BGP table. */
d62a17ae 11840static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11841 struct bgp_table *rib, const char *ip_str,
11842 afi_t afi, safi_t safi,
4027d19b 11843 enum rpki_states rpki_target_state,
d62a17ae 11844 struct prefix_rd *prd, int prefix_check,
9f049418 11845 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11846{
11847 int ret;
d62a17ae 11848 int display = 0;
11849 struct prefix match;
9bcb3eef
DS
11850 struct bgp_dest *dest;
11851 struct bgp_dest *rm;
d62a17ae 11852 struct bgp_table *table;
11853 json_object *json = NULL;
11854 json_object *json_paths = NULL;
11855
11856 /* Check IP address argument. */
11857 ret = str2prefix(ip_str, &match);
11858 if (!ret) {
11859 vty_out(vty, "address is malformed\n");
11860 return CMD_WARNING;
11861 }
718e3744 11862
d62a17ae 11863 match.family = afi2family(afi);
b05a1c8b 11864
44c69747 11865 if (use_json)
d62a17ae 11866 json = json_object_new_object();
718e3744 11867
44c69747 11868 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11869 for (dest = bgp_table_top(rib); dest;
11870 dest = bgp_route_next(dest)) {
11871 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11872
9bcb3eef 11873 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11874 continue;
9bcb3eef 11875 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11876 if (!table)
ea47320b 11877 continue;
d62a17ae 11878
4953391b
DA
11879 rm = bgp_node_match(table, &match);
11880 if (rm == NULL)
ea47320b 11881 continue;
d62a17ae 11882
9bcb3eef 11883 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11884 if (prefix_check
b54892e0 11885 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11886 bgp_dest_unlock_node(rm);
ea47320b
DL
11887 continue;
11888 }
d62a17ae 11889
9bcb3eef 11890 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11891 bgp, afi, safi, json, pathtype,
4027d19b 11892 &display, rpki_target_state);
44c69747 11893
9bcb3eef 11894 bgp_dest_unlock_node(rm);
44c69747
LK
11895 }
11896 } else if (safi == SAFI_EVPN) {
9bcb3eef 11897 struct bgp_dest *longest_pfx;
cded3b72 11898 bool is_exact_pfxlen_match = false;
44c69747 11899
9bcb3eef
DS
11900 for (dest = bgp_table_top(rib); dest;
11901 dest = bgp_route_next(dest)) {
11902 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11903
9bcb3eef 11904 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11905 continue;
9bcb3eef 11906 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11907 if (!table)
11908 continue;
11909
11910 longest_pfx = NULL;
cded3b72 11911 is_exact_pfxlen_match = false;
44c69747
LK
11912 /*
11913 * Search through all the prefixes for a match. The
11914 * pfx's are enumerated in ascending order of pfxlens.
11915 * So, the last pfx match is the longest match. Set
11916 * is_exact_pfxlen_match when we get exact pfxlen match
11917 */
11918 for (rm = bgp_table_top(table); rm;
11919 rm = bgp_route_next(rm)) {
b54892e0 11920 const struct prefix *rm_p =
9bcb3eef 11921 bgp_dest_get_prefix(rm);
44c69747
LK
11922 /*
11923 * Get prefixlen of the ip-prefix within type5
11924 * evpn route
11925 */
b54892e0
DS
11926 if (evpn_type5_prefix_match(rm_p, &match)
11927 && rm->info) {
44c69747
LK
11928 longest_pfx = rm;
11929 int type5_pfxlen =
b54892e0
DS
11930 bgp_evpn_get_type5_prefixlen(
11931 rm_p);
44c69747 11932 if (type5_pfxlen == match.prefixlen) {
cded3b72 11933 is_exact_pfxlen_match = true;
9bcb3eef 11934 bgp_dest_unlock_node(rm);
44c69747
LK
11935 break;
11936 }
d62a17ae 11937 }
11938 }
ea47320b 11939
44c69747
LK
11940 if (!longest_pfx)
11941 continue;
11942
11943 if (prefix_check && !is_exact_pfxlen_match)
11944 continue;
11945
11946 rm = longest_pfx;
9bcb3eef 11947 bgp_dest_lock_node(rm);
44c69747 11948
9bcb3eef 11949 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11950 bgp, afi, safi, json, pathtype,
4027d19b 11951 &display, rpki_target_state);
44c69747 11952
9bcb3eef 11953 bgp_dest_unlock_node(rm);
d62a17ae 11954 }
98a9dbc7 11955 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11956 if (use_json)
11957 json_paths = json_object_new_array();
11958
63a0b7a9
PG
11959 display = bgp_flowspec_display_match_per_ip(afi, rib,
11960 &match, prefix_check,
11961 vty,
11962 use_json,
11963 json_paths);
d5f20468
SP
11964 if (use_json) {
11965 if (display)
11966 json_object_object_add(json, "paths",
11967 json_paths);
11968 else
11969 json_object_free(json_paths);
11970 }
d62a17ae 11971 } else {
4953391b
DA
11972 dest = bgp_node_match(rib, &match);
11973 if (dest != NULL) {
9bcb3eef 11974 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11975 if (!prefix_check
9bcb3eef
DS
11976 || dest_p->prefixlen == match.prefixlen) {
11977 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11978 safi, json, pathtype,
4027d19b 11979 &display, rpki_target_state);
d62a17ae 11980 }
11981
9bcb3eef 11982 bgp_dest_unlock_node(dest);
d62a17ae 11983 }
11984 }
e5eee9af 11985
d62a17ae 11986 if (use_json) {
75eeda93 11987 vty_json(vty, json);
d62a17ae 11988 } else {
11989 if (!display) {
11990 vty_out(vty, "%% Network not in table\n");
11991 return CMD_WARNING;
11992 }
11993 }
b05a1c8b 11994
d62a17ae 11995 return CMD_SUCCESS;
718e3744 11996}
11997
fee0f4c6 11998/* Display specified route of Main RIB */
d62a17ae 11999static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12000 afi_t afi, safi_t safi, struct prefix_rd *prd,
12001 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12002 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12003{
9b86009a 12004 if (!bgp) {
d62a17ae 12005 bgp = bgp_get_default();
9b86009a
RW
12006 if (!bgp) {
12007 if (!use_json)
12008 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12009 else
12010 vty_out(vty, "{}\n");
9b86009a
RW
12011 return CMD_WARNING;
12012 }
12013 }
d62a17ae 12014
12015 /* labeled-unicast routes live in the unicast table */
12016 if (safi == SAFI_LABELED_UNICAST)
12017 safi = SAFI_UNICAST;
12018
12019 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12020 afi, safi, rpki_target_state, prd,
8aa22bbb 12021 prefix_check, pathtype, use_json);
d62a17ae 12022}
12023
12024static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12025 struct cmd_token **argv, bool exact, afi_t afi,
12026 safi_t safi, bool uj)
d62a17ae 12027{
12028 struct lcommunity *lcom;
12029 struct buffer *b;
12030 int i;
12031 char *str;
12032 int first = 0;
96c81f66 12033 uint16_t show_flags = 0;
4f28b2b5 12034 int ret;
96f3485c
MK
12035
12036 if (uj)
12037 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12038
12039 b = buffer_new(1024);
12040 for (i = 0; i < argc; i++) {
12041 if (first)
12042 buffer_putc(b, ' ');
12043 else {
12044 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12045 first = 1;
12046 buffer_putstr(b, argv[i]->arg);
12047 }
12048 }
12049 }
12050 buffer_putc(b, '\0');
57d187bc 12051
d62a17ae 12052 str = buffer_getstr(b);
12053 buffer_free(b);
57d187bc 12054
d62a17ae 12055 lcom = lcommunity_str2com(str);
12056 XFREE(MTYPE_TMP, str);
12057 if (!lcom) {
12058 vty_out(vty, "%% Large-community malformed\n");
12059 return CMD_WARNING;
12060 }
57d187bc 12061
4f28b2b5 12062 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12063 (exact ? bgp_show_type_lcommunity_exact
12064 : bgp_show_type_lcommunity),
12065 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12066
12067 lcommunity_free(&lcom);
12068 return ret;
57d187bc
JS
12069}
12070
d62a17ae 12071static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12072 const char *lcom, bool exact, afi_t afi,
12073 safi_t safi, bool uj)
57d187bc 12074{
d62a17ae 12075 struct community_list *list;
96c81f66 12076 uint16_t show_flags = 0;
96f3485c
MK
12077
12078 if (uj)
12079 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12080
57d187bc 12081
e237b0d2 12082 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12083 LARGE_COMMUNITY_LIST_MASTER);
12084 if (list == NULL) {
12085 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12086 lcom);
12087 return CMD_WARNING;
12088 }
57d187bc 12089
36a206db 12090 return bgp_show(vty, bgp, afi, safi,
12091 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12092 : bgp_show_type_lcommunity_list),
1e2ce4f1 12093 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12094}
12095
52951b63
DS
12096DEFUN (show_ip_bgp_large_community_list,
12097 show_ip_bgp_large_community_list_cmd,
77a3a95e 12098 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
52951b63
DS
12099 SHOW_STR
12100 IP_STR
12101 BGP_STR
12102 BGP_INSTANCE_HELP_STR
9bedbb1e 12103 BGP_AFI_HELP_STR
4dd6177e 12104 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12105 "Display routes matching the large-community-list\n"
12106 "large-community-list number\n"
12107 "large-community-list name\n"
36a206db 12108 "Exact match of the large-communities\n"
52951b63
DS
12109 JSON_STR)
12110{
d62a17ae 12111 afi_t afi = AFI_IP6;
12112 safi_t safi = SAFI_UNICAST;
12113 int idx = 0;
36a206db 12114 bool exact_match = 0;
4d678463 12115 struct bgp *bgp = NULL;
9f049418 12116 bool uj = use_json(argc, argv);
d62a17ae 12117
ef3364f0
DA
12118 if (uj)
12119 argc--;
4d678463 12120
ef3364f0
DA
12121 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12122 &bgp, uj);
12123 if (!idx)
12124 return CMD_WARNING;
d62a17ae 12125
12126 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12127
12128 const char *clist_number_or_name = argv[++idx]->arg;
12129
12130 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12131 exact_match = 1;
12132
12133 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12134 exact_match, afi, safi, uj);
52951b63
DS
12135}
12136DEFUN (show_ip_bgp_large_community,
12137 show_ip_bgp_large_community_cmd,
36a206db 12138 "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
12139 SHOW_STR
12140 IP_STR
12141 BGP_STR
12142 BGP_INSTANCE_HELP_STR
9bedbb1e 12143 BGP_AFI_HELP_STR
4dd6177e 12144 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12145 "Display routes matching the large-communities\n"
12146 "List of large-community numbers\n"
36a206db 12147 "Exact match of the large-communities\n"
52951b63
DS
12148 JSON_STR)
12149{
d62a17ae 12150 afi_t afi = AFI_IP6;
12151 safi_t safi = SAFI_UNICAST;
12152 int idx = 0;
36a206db 12153 bool exact_match = 0;
4d678463 12154 struct bgp *bgp = NULL;
9f049418 12155 bool uj = use_json(argc, argv);
96c81f66 12156 uint16_t show_flags = 0;
d62a17ae 12157
96f3485c
MK
12158 if (uj) {
12159 argc--;
12160 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12161 }
4d678463 12162
96f3485c
MK
12163 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12164 &bgp, uj);
12165 if (!idx)
12166 return CMD_WARNING;
d62a17ae 12167
36a206db 12168 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12169 if (argv_find(argv, argc, "exact-match", &idx))
12170 exact_match = 1;
12171 return bgp_show_lcommunity(vty, bgp, argc, argv,
12172 exact_match, afi, safi, uj);
12173 } else
d62a17ae 12174 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12175 bgp_show_type_lcommunity_all, NULL, show_flags,
12176 RPKI_NOT_BEING_USED);
52951b63
DS
12177}
12178
71f1613a
DA
12179static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12180 safi_t safi, struct json_object *json_array);
d62a17ae 12181static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12182 safi_t safi, struct json_object *json);
e01ca200 12183
7b2ff250 12184
9ab0cf58
PG
12185DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12186 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12187 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12188 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12189{
12190 bool uj = use_json(argc, argv);
12191 struct bgp *bgp = NULL;
ec76a1d1
DA
12192 safi_t safi = SAFI_UNICAST;
12193 afi_t afi = AFI_IP6;
4265b261 12194 int idx = 0;
6c9d22e2
PG
12195 struct json_object *json_all = NULL;
12196 struct json_object *json_afi_safi = NULL;
4265b261
PG
12197
12198 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12199 &bgp, false);
71f1613a 12200 if (!idx)
4265b261 12201 return CMD_WARNING;
6c9d22e2 12202
4265b261 12203 if (uj)
6c9d22e2 12204 json_all = json_object_new_object();
4265b261 12205
9ab0cf58
PG
12206 FOREACH_AFI_SAFI (afi, safi) {
12207 /*
12208 * So limit output to those afi/safi pairs that
12209 * actually have something interesting in them
12210 */
12211 if (strmatch(get_afi_safi_str(afi, safi, true),
12212 "Unknown")) {
12213 continue;
12214 }
12215 if (uj) {
12216 json_afi_safi = json_object_new_array();
12217 json_object_object_add(
12218 json_all,
12219 get_afi_safi_str(afi, safi, true),
12220 json_afi_safi);
12221 } else {
12222 json_afi_safi = NULL;
6c9d22e2 12223 }
9ab0cf58
PG
12224
12225 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12226 }
6c9d22e2 12227
3757f964
DA
12228 if (uj)
12229 vty_json(vty, json_all);
6c9d22e2 12230
4265b261
PG
12231 return CMD_SUCCESS;
12232}
12233
7b2ff250 12234/* BGP route print out function without JSON */
14718643
PG
12235DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12236 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12237 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12238 SHOW_STR
12239 IP_STR
12240 BGP_STR
12241 BGP_INSTANCE_HELP_STR
12242 L2VPN_HELP_STR
12243 EVPN_HELP_STR
12244 "BGP RIB advertisement statistics\n"
12245 JSON_STR)
12246{
ec76a1d1
DA
12247 afi_t afi = AFI_IP6;
12248 safi_t safi = SAFI_UNICAST;
14718643
PG
12249 struct bgp *bgp = NULL;
12250 int idx = 0, ret;
12251 bool uj = use_json(argc, argv);
12252 struct json_object *json_afi_safi = NULL, *json = NULL;
12253
12254 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12255 &bgp, false);
12256 if (!idx)
12257 return CMD_WARNING;
12258
12259 if (uj)
12260 json_afi_safi = json_object_new_array();
12261 else
12262 json_afi_safi = NULL;
12263
12264 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12265
12266 if (uj) {
12267 json = json_object_new_object();
12268 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12269 json_afi_safi);
3757f964 12270 vty_json(vty, json);
14718643
PG
12271 }
12272 return ret;
12273}
12274
893cccd0 12275/* BGP route print out function without JSON */
9ab0cf58
PG
12276DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12277 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12278 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12279 "]]\
893cccd0 12280 statistics [json]",
9ab0cf58
PG
12281 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12282 BGP_SAFI_WITH_LABEL_HELP_STR
12283 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12284{
ec76a1d1
DA
12285 afi_t afi = AFI_IP6;
12286 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12287 struct bgp *bgp = NULL;
12288 int idx = 0, ret;
12289 bool uj = use_json(argc, argv);
6c9d22e2 12290 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12291
12292 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12293 &bgp, false);
12294 if (!idx)
12295 return CMD_WARNING;
6c9d22e2 12296
893cccd0 12297 if (uj)
6c9d22e2
PG
12298 json_afi_safi = json_object_new_array();
12299 else
12300 json_afi_safi = NULL;
12301
12302 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12303
12304 if (uj) {
12305 json = json_object_new_object();
12306 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12307 json_afi_safi);
3757f964 12308 vty_json(vty, json);
893cccd0
PG
12309 }
12310 return ret;
893cccd0 12311}
7b2ff250 12312
fe0f234d 12313DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12314 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12315 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12316 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12317 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12318 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12319 "Display the entries for all address families\n"
9ab0cf58
PG
12320 "Display detailed information about dampening\n"
12321 "Display detail of configured dampening parameters\n"
fe0f234d 12322 JSON_STR)
718e3744 12323{
d62a17ae 12324 afi_t afi = AFI_IP6;
12325 safi_t safi = SAFI_UNICAST;
d62a17ae 12326 struct bgp *bgp = NULL;
12327 int idx = 0;
96c81f66 12328 uint16_t show_flags = 0;
fe0f234d
RW
12329 bool uj = use_json(argc, argv);
12330
12331 if (uj) {
12332 argc--;
12333 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12334 }
96f3485c
MK
12335
12336 /* [<ipv4|ipv6> [all]] */
12337 if (all) {
12338 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12339 if (argv_find(argv, argc, "ipv4", &idx))
12340 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12341
12342 if (argv_find(argv, argc, "ipv6", &idx))
12343 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12344 }
d62a17ae 12345
12346 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12347 &bgp, false);
d62a17ae 12348 if (!idx)
12349 return CMD_WARNING;
12350
fe0f234d 12351 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12352}
12353
fe0f234d
RW
12354/* BGP route print out function */
12355DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12356 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12357 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12358 "]]\
96f3485c 12359 [all$all]\
cf4898bc
QY
12360 [cidr-only\
12361 |dampening <flap-statistics|dampened-paths>\
12362 |community [AA:NN|local-AS|no-advertise|no-export\
12363 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12364 |accept-own|accept-own-nexthop|route-filter-v6\
12365 |route-filter-v4|route-filter-translated-v6\
12366 |route-filter-translated-v4] [exact-match]\
70799983 12367 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12368 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12369 |prefix-list WORD\
ed126382 12370 |access-list ACCESSLIST_NAME\
70dd370f 12371 |route-map RMAP_NAME\
1e2ce4f1 12372 |rpki <invalid|valid|notfound>\
7d3cae70 12373 |version (1-4294967295)\
b4ad2fae 12374 |alias ALIAS_NAME\
39c3c736
RW
12375 |A.B.C.D/M longer-prefixes\
12376 |X:X::X:X/M longer-prefixes\
f280c93b 12377 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12378 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12379 BGP_SAFI_WITH_LABEL_HELP_STR
12380 "Display the entries for all address families\n"
12381 "Display only routes with non-natural netmasks\n"
12382 "Display detailed information about dampening\n"
12383 "Display flap statistics of routes\n"
12384 "Display paths suppressed due to dampening\n"
12385 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12386 "Do not send outside local AS (well-known community)\n"
12387 "Do not advertise to any peer (well-known community)\n"
12388 "Do not export to next AS (well-known community)\n"
12389 "Graceful shutdown (well-known community)\n"
12390 "Do not export to any peer (well-known community)\n"
12391 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12392 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12393 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12394 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12395 "Should accept VPN route with local nexthop (well-known community)\n"
12396 "RT VPNv6 route filtering (well-known community)\n"
12397 "RT VPNv4 route filtering (well-known community)\n"
12398 "RT translated VPNv6 route filtering (well-known community)\n"
12399 "RT translated VPNv4 route filtering (well-known community)\n"
12400 "Exact match of the communities\n"
70799983
RW
12401 "Community-list number\n"
12402 "Community-list name\n"
12403 "Display routes matching the community-list\n"
12404 "Exact match of the communities\n"
a7129347
RW
12405 "Display routes conforming to the filter-list\n"
12406 "Regular expression access list name\n"
6deaf579
RW
12407 "Display routes conforming to the prefix-list\n"
12408 "Prefix-list name\n"
ed126382
DA
12409 "Display routes conforming to the access-list\n"
12410 "Access-list name\n"
bf1a944a
RW
12411 "Display routes matching the route-map\n"
12412 "A route-map to match on\n"
a70a28a5
DA
12413 "RPKI route types\n"
12414 "A valid path as determined by rpki\n"
12415 "A invalid path as determined by rpki\n"
12416 "A path that has no rpki data\n"
12417 "Display prefixes with matching version numbers\n"
12418 "Version number and above\n"
12419 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12420 "BGP community alias\n"
12421 "IPv4 prefix\n"
12422 "Display route and more specific routes\n"
12423 "IPv6 prefix\n"
12424 "Display route and more specific routes\n"
12425 JSON_STR
a70a28a5
DA
12426 "Display detailed version of JSON output\n"
12427 "Increase table width for longer prefixes\n")
7b2ff250
DW
12428{
12429 afi_t afi = AFI_IP6;
12430 safi_t safi = SAFI_UNICAST;
12431 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12432 void *output_arg = NULL;
7b2ff250
DW
12433 struct bgp *bgp = NULL;
12434 int idx = 0;
d0086e8e 12435 int exact_match = 0;
96f3485c
MK
12436 char *community = NULL;
12437 bool first = true;
96c81f66 12438 uint16_t show_flags = 0;
4027d19b 12439 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12440 struct prefix p;
96f3485c
MK
12441
12442 if (uj) {
9f049418 12443 argc--;
96f3485c
MK
12444 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12445 }
12446
f280c93b
DA
12447 if (detail)
12448 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12449
96f3485c
MK
12450 /* [<ipv4|ipv6> [all]] */
12451 if (all) {
12452 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12453
12454 if (argv_find(argv, argc, "ipv4", &idx))
12455 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12456
12457 if (argv_find(argv, argc, "ipv6", &idx))
12458 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12459 }
12460
12461 if (wide)
12462 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12463
12464 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12465 &bgp, uj);
7b2ff250
DW
12466 if (!idx)
12467 return CMD_WARNING;
12468
7b2ff250 12469 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12470 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12471
12472 if (argv_find(argv, argc, "dampening", &idx)) {
12473 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12474 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12475 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12476 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12477 }
12478
12479 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12480 char *maybecomm = NULL;
d0086e8e 12481
79bc257a
RW
12482 if (idx + 1 < argc) {
12483 if (argv[idx + 1]->type == VARIABLE_TKN)
12484 maybecomm = argv[idx + 1]->arg;
12485 else
12486 maybecomm = argv[idx + 1]->text;
12487 }
12488
cf4898bc
QY
12489 if (maybecomm && !strmatch(maybecomm, "json")
12490 && !strmatch(maybecomm, "exact-match"))
12491 community = maybecomm;
d0086e8e 12492
cf4898bc
QY
12493 if (argv_find(argv, argc, "exact-match", &idx))
12494 exact_match = 1;
d0086e8e 12495
96f3485c
MK
12496 if (!community)
12497 sh_type = bgp_show_type_community_all;
12498 }
12499
70799983
RW
12500 if (argv_find(argv, argc, "community-list", &idx)) {
12501 const char *clist_number_or_name = argv[++idx]->arg;
12502 struct community_list *list;
12503
12504 if (argv_find(argv, argc, "exact-match", &idx))
12505 exact_match = 1;
12506
12507 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12508 COMMUNITY_LIST_MASTER);
12509 if (list == NULL) {
606d49a4 12510 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12511 clist_number_or_name);
12512 return CMD_WARNING;
12513 }
12514
12515 if (exact_match)
12516 sh_type = bgp_show_type_community_list_exact;
12517 else
12518 sh_type = bgp_show_type_community_list;
12519 output_arg = list;
12520 }
12521
a7129347
RW
12522 if (argv_find(argv, argc, "filter-list", &idx)) {
12523 const char *filter = argv[++idx]->arg;
12524 struct as_list *as_list;
12525
12526 as_list = as_list_lookup(filter);
12527 if (as_list == NULL) {
606d49a4 12528 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12529 filter);
12530 return CMD_WARNING;
12531 }
12532
12533 sh_type = bgp_show_type_filter_list;
12534 output_arg = as_list;
12535 }
12536
6deaf579
RW
12537 if (argv_find(argv, argc, "prefix-list", &idx)) {
12538 const char *prefix_list_str = argv[++idx]->arg;
12539 struct prefix_list *plist;
12540
12541 plist = prefix_list_lookup(afi, prefix_list_str);
12542 if (plist == NULL) {
606d49a4 12543 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12544 prefix_list_str);
12545 return CMD_WARNING;
12546 }
12547
12548 sh_type = bgp_show_type_prefix_list;
12549 output_arg = plist;
12550 }
12551
ed126382
DA
12552 if (argv_find(argv, argc, "access-list", &idx)) {
12553 const char *access_list_str = argv[++idx]->arg;
12554 struct access_list *alist;
12555
12556 alist = access_list_lookup(afi, access_list_str);
12557 if (!alist) {
606d49a4 12558 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12559 access_list_str);
12560 return CMD_WARNING;
12561 }
12562
12563 sh_type = bgp_show_type_access_list;
12564 output_arg = alist;
12565 }
12566
bf1a944a
RW
12567 if (argv_find(argv, argc, "route-map", &idx)) {
12568 const char *rmap_str = argv[++idx]->arg;
12569 struct route_map *rmap;
12570
12571 rmap = route_map_lookup_by_name(rmap_str);
12572 if (!rmap) {
606d49a4 12573 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12574 return CMD_WARNING;
12575 }
12576
12577 sh_type = bgp_show_type_route_map;
12578 output_arg = rmap;
12579 }
12580
1e2ce4f1
DS
12581 if (argv_find(argv, argc, "rpki", &idx)) {
12582 sh_type = bgp_show_type_rpki;
12583 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12584 rpki_target_state = RPKI_VALID;
1e2ce4f1 12585 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12586 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12587 }
12588
7d3cae70
DA
12589 /* Display prefixes with matching version numbers */
12590 if (argv_find(argv, argc, "version", &idx)) {
12591 sh_type = bgp_show_type_prefix_version;
2391833e 12592 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12593 }
12594
a70a28a5
DA
12595 /* Display prefixes with matching BGP community alias */
12596 if (argv_find(argv, argc, "alias", &idx)) {
12597 sh_type = bgp_show_type_community_alias;
2391833e 12598 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12599 }
12600
39c3c736
RW
12601 /* prefix-longer */
12602 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12603 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12604 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12605
12606 if (!str2prefix(prefix_str, &p)) {
12607 vty_out(vty, "%% Malformed Prefix\n");
12608 return CMD_WARNING;
12609 }
12610
12611 sh_type = bgp_show_type_prefix_longer;
12612 output_arg = &p;
a70a28a5
DA
12613 }
12614
96f3485c
MK
12615 if (!all) {
12616 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12617 if (community)
12618 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12619 exact_match, afi, safi,
12620 show_flags);
2391833e 12621 else
a70a28a5 12622 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12623 output_arg, show_flags,
a70a28a5 12624 rpki_target_state);
96f3485c 12625 } else {
fa5ac378
DA
12626 struct listnode *node;
12627 struct bgp *abgp;
96f3485c
MK
12628 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12629 * AFI_IP6 */
12630
12631 if (uj)
12632 vty_out(vty, "{\n");
12633
12634 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12635 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12636 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12637 ? AFI_IP
12638 : AFI_IP6;
fa5ac378
DA
12639 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12640 FOREACH_SAFI (safi) {
12641 if (!bgp_afi_safi_peer_exists(abgp, afi,
12642 safi))
12643 continue;
96f3485c 12644
fa5ac378
DA
12645 if (uj) {
12646 if (first)
12647 first = false;
12648 else
12649 vty_out(vty, ",\n");
12650 vty_out(vty, "\"%s\":{\n",
12651 get_afi_safi_str(afi,
12652 safi,
12653 true));
12654 } else
12655 vty_out(vty,
12656 "\nFor address family: %s\n",
12657 get_afi_safi_str(
12658 afi, safi,
12659 false));
12660
12661 if (community)
12662 bgp_show_community(
12663 vty, abgp, community,
12664 exact_match, afi, safi,
12665 show_flags);
96f3485c 12666 else
fa5ac378
DA
12667 bgp_show(vty, abgp, afi, safi,
12668 sh_type, output_arg,
12669 show_flags,
12670 rpki_target_state);
12671 if (uj)
12672 vty_out(vty, "}\n");
12673 }
96f3485c
MK
12674 }
12675 } else {
12676 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12677 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12678 FOREACH_AFI_SAFI (afi, safi) {
12679 if (!bgp_afi_safi_peer_exists(abgp, afi,
12680 safi))
12681 continue;
96f3485c 12682
fa5ac378
DA
12683 if (uj) {
12684 if (first)
12685 first = false;
12686 else
12687 vty_out(vty, ",\n");
12688
12689 vty_out(vty, "\"%s\":{\n",
12690 get_afi_safi_str(afi,
12691 safi,
12692 true));
12693 } else
12694 vty_out(vty,
12695 "\nFor address family: %s\n",
12696 get_afi_safi_str(
12697 afi, safi,
12698 false));
12699
12700 if (community)
12701 bgp_show_community(
12702 vty, abgp, community,
12703 exact_match, afi, safi,
12704 show_flags);
96f3485c 12705 else
fa5ac378
DA
12706 bgp_show(vty, abgp, afi, safi,
12707 sh_type, output_arg,
12708 show_flags,
12709 rpki_target_state);
12710 if (uj)
12711 vty_out(vty, "}\n");
12712 }
96f3485c
MK
12713 }
12714 }
12715 if (uj)
12716 vty_out(vty, "}\n");
12717 }
12718 return CMD_SUCCESS;
a636c635 12719}
47fc97cc 12720
718e3744 12721DEFUN (show_ip_bgp_route,
12722 show_ip_bgp_route_cmd,
8aa22bbb 12723 "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 12724 SHOW_STR
12725 IP_STR
12726 BGP_STR
a636c635 12727 BGP_INSTANCE_HELP_STR
4f280b15 12728 BGP_AFI_HELP_STR
4dd6177e 12729 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12730 "Network in the BGP routing table to display\n"
0c7b1b01 12731 "IPv4 prefix\n"
8c3deaae 12732 "Network in the BGP routing table to display\n"
0c7b1b01 12733 "IPv6 prefix\n"
4092b06c 12734 "Display only the bestpath\n"
b05a1c8b 12735 "Display only multipaths\n"
8aa22bbb
DS
12736 "Display only paths that match the specified rpki state\n"
12737 "A valid path as determined by rpki\n"
12738 "A invalid path as determined by rpki\n"
12739 "A path that has no rpki data\n"
9973d184 12740 JSON_STR)
4092b06c 12741{
d62a17ae 12742 int prefix_check = 0;
ae19d7dd 12743
d62a17ae 12744 afi_t afi = AFI_IP6;
12745 safi_t safi = SAFI_UNICAST;
12746 char *prefix = NULL;
12747 struct bgp *bgp = NULL;
12748 enum bgp_path_type path_type;
9f049418 12749 bool uj = use_json(argc, argv);
b05a1c8b 12750
d62a17ae 12751 int idx = 0;
ae19d7dd 12752
d62a17ae 12753 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12754 &bgp, uj);
d62a17ae 12755 if (!idx)
12756 return CMD_WARNING;
c41247f5 12757
d62a17ae 12758 if (!bgp) {
12759 vty_out(vty,
12760 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12761 return CMD_WARNING;
12762 }
a636c635 12763
d62a17ae 12764 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12765 if (argv_find(argv, argc, "A.B.C.D", &idx)
12766 || argv_find(argv, argc, "X:X::X:X", &idx))
12767 prefix_check = 0;
12768 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12769 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12770 prefix_check = 1;
12771
12772 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12773 && afi != AFI_IP6) {
12774 vty_out(vty,
12775 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12776 return CMD_WARNING;
12777 }
12778 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12779 && afi != AFI_IP) {
12780 vty_out(vty,
12781 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12782 return CMD_WARNING;
12783 }
12784
12785 prefix = argv[idx]->arg;
12786
12787 /* [<bestpath|multipath>] */
12788 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12789 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12790 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12791 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12792 else
360660c6 12793 path_type = BGP_PATH_SHOW_ALL;
a636c635 12794
d62a17ae 12795 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12796 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12797}
12798
8c3deaae
QY
12799DEFUN (show_ip_bgp_regexp,
12800 show_ip_bgp_regexp_cmd,
3e5b31b3 12801 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12802 SHOW_STR
12803 IP_STR
12804 BGP_STR
b00b230a 12805 BGP_INSTANCE_HELP_STR
4f280b15 12806 BGP_AFI_HELP_STR
4dd6177e 12807 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12808 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12809 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12810 JSON_STR)
8c3deaae 12811{
d62a17ae 12812 afi_t afi = AFI_IP6;
12813 safi_t safi = SAFI_UNICAST;
12814 struct bgp *bgp = NULL;
3e5b31b3
DA
12815 bool uj = use_json(argc, argv);
12816 char *regstr = NULL;
8c3deaae 12817
d62a17ae 12818 int idx = 0;
12819 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12820 &bgp, false);
d62a17ae 12821 if (!idx)
12822 return CMD_WARNING;
8c3deaae 12823
d62a17ae 12824 // get index of regex
3e5b31b3
DA
12825 if (argv_find(argv, argc, "REGEX", &idx))
12826 regstr = argv[idx]->arg;
8c3deaae 12827
5f71d11c 12828 assert(regstr);
3e5b31b3
DA
12829 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12830 bgp_show_type_regexp, uj);
8c3deaae
QY
12831}
12832
ae248832 12833DEFPY (show_ip_bgp_instance_all,
a636c635 12834 show_ip_bgp_instance_all_cmd,
ae248832 12835 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12836 SHOW_STR
a636c635 12837 IP_STR
4092b06c 12838 BGP_STR
a636c635 12839 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12840 BGP_AFI_HELP_STR
4dd6177e 12841 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12842 JSON_STR
12843 "Increase table width for longer prefixes\n")
4092b06c 12844{
54d05dea 12845 afi_t afi = AFI_IP6;
d62a17ae 12846 safi_t safi = SAFI_UNICAST;
12847 struct bgp *bgp = NULL;
d62a17ae 12848 int idx = 0;
96c81f66 12849 uint16_t show_flags = 0;
ae19d7dd 12850
96f3485c 12851 if (uj) {
d62a17ae 12852 argc--;
96f3485c
MK
12853 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12854 }
12855
12856 if (wide)
12857 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12858
9f049418
DS
12859 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12860 &bgp, uj);
12861 if (!idx)
12862 return CMD_WARNING;
12863
96f3485c 12864 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12865 return CMD_SUCCESS;
e3e29b32
LB
12866}
12867
a4d82a8a 12868static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12869 afi_t afi, safi_t safi, enum bgp_show_type type,
12870 bool use_json)
718e3744 12871{
d62a17ae 12872 regex_t *regex;
12873 int rc;
96c81f66 12874 uint16_t show_flags = 0;
96f3485c
MK
12875
12876 if (use_json)
12877 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12878
c3900853 12879 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12880 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12881 regstr);
12882 return CMD_WARNING_CONFIG_FAILED;
12883 }
12884
d62a17ae 12885 regex = bgp_regcomp(regstr);
12886 if (!regex) {
12887 vty_out(vty, "Can't compile regexp %s\n", regstr);
12888 return CMD_WARNING;
12889 }
a636c635 12890
1e2ce4f1
DS
12891 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12892 RPKI_NOT_BEING_USED);
d62a17ae 12893 bgp_regex_free(regex);
12894 return rc;
e3e29b32
LB
12895}
12896
7f323236
DW
12897static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12898 const char *comstr, int exact, afi_t afi,
96c81f66 12899 safi_t safi, uint16_t show_flags)
d62a17ae 12900{
12901 struct community *com;
d62a17ae 12902 int ret = 0;
12903
7f323236 12904 com = community_str2com(comstr);
d62a17ae 12905 if (!com) {
7f323236 12906 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12907 return CMD_WARNING;
12908 }
12909
12910 ret = bgp_show(vty, bgp, afi, safi,
12911 (exact ? bgp_show_type_community_exact
12912 : bgp_show_type_community),
1e2ce4f1 12913 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12914 community_free(&com);
46c3ce83 12915
d62a17ae 12916 return ret;
718e3744 12917}
12918
d62a17ae 12919enum bgp_stats {
12920 BGP_STATS_MAXBITLEN = 0,
12921 BGP_STATS_RIB,
12922 BGP_STATS_PREFIXES,
12923 BGP_STATS_TOTPLEN,
12924 BGP_STATS_UNAGGREGATEABLE,
12925 BGP_STATS_MAX_AGGREGATEABLE,
12926 BGP_STATS_AGGREGATES,
12927 BGP_STATS_SPACE,
12928 BGP_STATS_ASPATH_COUNT,
12929 BGP_STATS_ASPATH_MAXHOPS,
12930 BGP_STATS_ASPATH_TOTHOPS,
12931 BGP_STATS_ASPATH_MAXSIZE,
12932 BGP_STATS_ASPATH_TOTSIZE,
12933 BGP_STATS_ASN_HIGHEST,
12934 BGP_STATS_MAX,
a636c635 12935};
2815e61f 12936
9ab0cf58 12937#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12938#define TABLE_STATS_IDX_JSON 1
12939
12940static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12941 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12942 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12943 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12944 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12945 "unaggregateablePrefixes"},
12946 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12947 "maximumAggregateablePrefixes"},
12948 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12949 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12950 [BGP_STATS_SPACE] = {"Address space advertised",
12951 "addressSpaceAdvertised"},
9ab0cf58
PG
12952 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12953 "advertisementsWithPaths"},
12954 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12955 "longestAsPath"},
12956 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12957 "largestAsPath"},
12958 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12959 "averageAsPathLengthHops"},
12960 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12961 "averageAsPathSizeBytes"},
12962 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12963 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12964};
2815e61f 12965
d62a17ae 12966struct bgp_table_stats {
12967 struct bgp_table *table;
12968 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
12969
12970 unsigned long long
12971 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
12972 1];
12973
8d0ab76d 12974 double total_space;
ff7924f6
PJ
12975};
12976
9bcb3eef 12977static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12978 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12979{
9bcb3eef 12980 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12981 struct bgp_path_info *pi;
b54892e0 12982 const struct prefix *rn_p;
d62a17ae 12983
9bcb3eef 12984 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12985 return;
d62a17ae 12986
9bcb3eef 12987 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12988 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12989 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12990
0747643e 12991 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 12992 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12993 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12994 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12995
9bcb3eef 12996 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12997 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12998 /* announced address space */
12999 if (space)
b54892e0 13000 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13001 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13002 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13003
9c14ec72 13004
9bcb3eef 13005 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13006 ts->counts[BGP_STATS_RIB]++;
13007
05864da7
DS
13008 if (CHECK_FLAG(pi->attr->flag,
13009 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13010 ts->counts[BGP_STATS_AGGREGATES]++;
13011
13012 /* as-path stats */
05864da7 13013 if (pi->attr->aspath) {
9c14ec72
RW
13014 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13015 unsigned int size = aspath_size(pi->attr->aspath);
13016 as_t highest = aspath_highest(pi->attr->aspath);
13017
13018 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13019
13020 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13021 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13022
13023 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13024 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13025
13026 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13027 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13028 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13029 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13030 }
13031 }
13032}
13033
cc9f21da 13034static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13035{
9bcb3eef
DS
13036 struct bgp_dest *dest, *ndest;
13037 struct bgp_dest *top;
9c14ec72
RW
13038 struct bgp_table_stats *ts = THREAD_ARG(t);
13039 unsigned int space = 0;
13040
13041 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13042 return;
9c14ec72
RW
13043
13044 switch (ts->table->afi) {
13045 case AFI_IP:
13046 space = IPV4_MAX_BITLEN;
13047 break;
13048 case AFI_IP6:
13049 space = IPV6_MAX_BITLEN;
13050 break;
3ba7b4af
TA
13051 case AFI_L2VPN:
13052 space = EVPN_ROUTE_PREFIXLEN;
13053 break;
9c14ec72 13054 default:
cc9f21da 13055 return;
9c14ec72
RW
13056 }
13057
13058 ts->counts[BGP_STATS_MAXBITLEN] = space;
13059
9bcb3eef 13060 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13061 if (ts->table->safi == SAFI_MPLS_VPN
13062 || ts->table->safi == SAFI_ENCAP
13063 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13064 struct bgp_table *table;
13065
9bcb3eef 13066 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13067 if (!table)
13068 continue;
13069
13070 top = bgp_table_top(table);
9bcb3eef
DS
13071 for (ndest = bgp_table_top(table); ndest;
13072 ndest = bgp_route_next(ndest))
13073 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13074 } else {
9bcb3eef 13075 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13076 }
13077 }
2815e61f 13078}
ff7924f6 13079
71f1613a
DA
13080static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13081 struct json_object *json_array)
13082{
13083 struct listnode *node, *nnode;
13084 struct bgp *bgp;
13085
13086 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13087 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13088}
13089
13090static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13091 safi_t safi, struct json_object *json_array)
2815e61f 13092{
d62a17ae 13093 struct bgp_table_stats ts;
13094 unsigned int i;
893cccd0
PG
13095 int ret = CMD_SUCCESS;
13096 char temp_buf[20];
6c9d22e2 13097 struct json_object *json = NULL;
0747643e
AQ
13098 uint32_t bitlen = 0;
13099 struct json_object *json_bitlen;
6c9d22e2
PG
13100
13101 if (json_array)
13102 json = json_object_new_object();
019386c2 13103
d62a17ae 13104 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13105 char warning_msg[50];
13106
13107 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13108 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13109 safi);
6c9d22e2
PG
13110
13111 if (!json)
893cccd0
PG
13112 vty_out(vty, "%s\n", warning_msg);
13113 else
9ab0cf58 13114 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13115
893cccd0
PG
13116 ret = CMD_WARNING;
13117 goto end_table_stats;
d62a17ae 13118 }
019386c2 13119
893cccd0 13120 if (!json)
5290ceab
DA
13121 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13122 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13123 else
13124 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13125
d62a17ae 13126 /* labeled-unicast routes live in the unicast table */
13127 if (safi == SAFI_LABELED_UNICAST)
13128 safi = SAFI_UNICAST;
019386c2 13129
d62a17ae 13130 memset(&ts, 0, sizeof(ts));
13131 ts.table = bgp->rib[afi][safi];
13132 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13133
d62a17ae 13134 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13135 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13136 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13137 continue;
13138
13139 switch (i) {
d62a17ae 13140 case BGP_STATS_ASPATH_TOTHOPS:
13141 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13142 if (!json) {
9ab0cf58
PG
13143 snprintf(
13144 temp_buf, sizeof(temp_buf), "%12.2f",
13145 ts.counts[i]
13146 ? (float)ts.counts[i]
13147 / (float)ts.counts
13148 [BGP_STATS_ASPATH_COUNT]
13149 : 0);
893cccd0 13150 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13151 table_stats_strs[i]
13152 [TABLE_STATS_IDX_VTY],
893cccd0 13153 temp_buf);
9ab0cf58
PG
13154 } else {
13155 json_object_double_add(
13156 json,
13157 table_stats_strs[i]
13158 [TABLE_STATS_IDX_JSON],
13159 ts.counts[i]
13160 ? (double)ts.counts[i]
13161 / (double)ts.counts
d62a17ae 13162 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13163 : 0);
13164 }
d62a17ae 13165 break;
13166 case BGP_STATS_TOTPLEN:
6c9d22e2 13167 if (!json) {
9ab0cf58
PG
13168 snprintf(
13169 temp_buf, sizeof(temp_buf), "%12.2f",
13170 ts.counts[i]
13171 ? (float)ts.counts[i]
13172 / (float)ts.counts
13173 [BGP_STATS_PREFIXES]
13174 : 0);
893cccd0 13175 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13176 table_stats_strs[i]
13177 [TABLE_STATS_IDX_VTY],
893cccd0 13178 temp_buf);
9ab0cf58
PG
13179 } else {
13180 json_object_double_add(
13181 json,
13182 table_stats_strs[i]
13183 [TABLE_STATS_IDX_JSON],
13184 ts.counts[i]
13185 ? (double)ts.counts[i]
13186 / (double)ts.counts
d62a17ae 13187 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13188 : 0);
13189 }
d62a17ae 13190 break;
13191 case BGP_STATS_SPACE:
6c9d22e2
PG
13192 if (!json) {
13193 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13194 ts.total_space);
893cccd0 13195 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13196 table_stats_strs[i]
13197 [TABLE_STATS_IDX_VTY],
893cccd0 13198 temp_buf);
9ab0cf58
PG
13199 } else {
13200 json_object_double_add(
13201 json,
13202 table_stats_strs[i]
13203 [TABLE_STATS_IDX_JSON],
13204 (double)ts.total_space);
13205 }
8d0ab76d 13206 if (afi == AFI_IP6) {
6c9d22e2
PG
13207 if (!json) {
13208 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13209 "%12g",
13210 ts.total_space
13211 * pow(2.0, -128 + 32));
6c9d22e2
PG
13212 vty_out(vty, "%30s: %s\n",
13213 "/32 equivalent %s\n",
13214 temp_buf);
9ab0cf58
PG
13215 } else {
13216 json_object_double_add(
13217 json, "/32equivalent",
13218 (double)(ts.total_space
13219 * pow(2.0,
13220 -128 + 32)));
13221 }
6c9d22e2
PG
13222 if (!json) {
13223 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13224 "%12g",
13225 ts.total_space
13226 * pow(2.0, -128 + 48));
6c9d22e2
PG
13227 vty_out(vty, "%30s: %s\n",
13228 "/48 equivalent %s\n",
13229 temp_buf);
9ab0cf58
PG
13230 } else {
13231 json_object_double_add(
13232 json, "/48equivalent",
13233 (double)(ts.total_space
13234 * pow(2.0,
13235 -128 + 48)));
13236 }
8d0ab76d 13237 } else {
6c9d22e2
PG
13238 if (!json) {
13239 snprintf(temp_buf, sizeof(temp_buf),
13240 "%12.2f",
9ab0cf58
PG
13241 ts.total_space * 100.
13242 * pow(2.0, -32));
6c9d22e2 13243 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13244 "% announced ", temp_buf);
13245 } else {
13246 json_object_double_add(
13247 json, "%announced",
13248 (double)(ts.total_space * 100.
13249 * pow(2.0, -32)));
13250 }
6c9d22e2
PG
13251 if (!json) {
13252 snprintf(temp_buf, sizeof(temp_buf),
13253 "%12.2f",
9ab0cf58
PG
13254 ts.total_space
13255 * pow(2.0, -32 + 8));
6c9d22e2
PG
13256 vty_out(vty, "%30s: %s\n",
13257 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13258 } else {
13259 json_object_double_add(
13260 json, "/8equivalent",
13261 (double)(ts.total_space
13262 * pow(2.0, -32 + 8)));
13263 }
6c9d22e2
PG
13264 if (!json) {
13265 snprintf(temp_buf, sizeof(temp_buf),
13266 "%12.2f",
9ab0cf58
PG
13267 ts.total_space
13268 * pow(2.0, -32 + 24));
6c9d22e2 13269 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13270 "/24 equivalent ", temp_buf);
13271 } else {
13272 json_object_double_add(
13273 json, "/24equivalent",
13274 (double)(ts.total_space
13275 * pow(2.0, -32 + 24)));
13276 }
8d0ab76d 13277 }
d62a17ae 13278 break;
13279 default:
6c9d22e2
PG
13280 if (!json) {
13281 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13282 ts.counts[i]);
893cccd0 13283 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13284 table_stats_strs[i]
13285 [TABLE_STATS_IDX_VTY],
13286 temp_buf);
13287 } else {
13288 json_object_int_add(
13289 json,
13290 table_stats_strs[i]
13291 [TABLE_STATS_IDX_JSON],
13292 ts.counts[i]);
13293 }
d62a17ae 13294 }
893cccd0
PG
13295 if (!json)
13296 vty_out(vty, "\n");
d62a17ae 13297 }
0747643e
AQ
13298
13299 switch (afi) {
13300 case AFI_IP:
13301 bitlen = IPV4_MAX_BITLEN;
13302 break;
13303 case AFI_IP6:
13304 bitlen = IPV6_MAX_BITLEN;
13305 break;
13306 case AFI_L2VPN:
13307 bitlen = EVPN_ROUTE_PREFIXLEN;
13308 break;
13309 default:
13310 break;
13311 }
13312
13313 if (json) {
13314 json_bitlen = json_object_new_array();
13315
13316 for (i = 0; i <= bitlen; i++) {
13317 struct json_object *ind_bit = json_object_new_object();
13318
13319 if (!ts.prefix_len_count[i])
13320 continue;
13321
13322 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13323 json_object_int_add(ind_bit, temp_buf,
13324 ts.prefix_len_count[i]);
13325 json_object_array_add(json_bitlen, ind_bit);
13326 }
13327 json_object_object_add(json, "prefixLength", json_bitlen);
13328 }
13329
9ab0cf58 13330end_table_stats:
6c9d22e2
PG
13331 if (json)
13332 json_object_array_add(json_array, json);
893cccd0 13333 return ret;
d62a17ae 13334}
13335
71f1613a
DA
13336static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13337 safi_t safi, struct json_object *json_array)
13338{
13339 if (!bgp) {
13340 bgp_table_stats_all(vty, afi, safi, json_array);
13341 return CMD_SUCCESS;
13342 }
13343
13344 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13345}
13346
d62a17ae 13347enum bgp_pcounts {
13348 PCOUNT_ADJ_IN = 0,
13349 PCOUNT_DAMPED,
13350 PCOUNT_REMOVED,
13351 PCOUNT_HISTORY,
13352 PCOUNT_STALE,
13353 PCOUNT_VALID,
13354 PCOUNT_ALL,
13355 PCOUNT_COUNTED,
7e3d9632 13356 PCOUNT_BPATH_SELECTED,
d62a17ae 13357 PCOUNT_PFCNT, /* the figure we display to users */
13358 PCOUNT_MAX,
a636c635 13359};
718e3744 13360
2b64873d 13361static const char *const pcount_strs[] = {
9d303b37
DL
13362 [PCOUNT_ADJ_IN] = "Adj-in",
13363 [PCOUNT_DAMPED] = "Damped",
13364 [PCOUNT_REMOVED] = "Removed",
13365 [PCOUNT_HISTORY] = "History",
13366 [PCOUNT_STALE] = "Stale",
13367 [PCOUNT_VALID] = "Valid",
13368 [PCOUNT_ALL] = "All RIB",
13369 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13370 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13371 [PCOUNT_PFCNT] = "Useable",
13372 [PCOUNT_MAX] = NULL,
a636c635 13373};
718e3744 13374
d62a17ae 13375struct peer_pcounts {
13376 unsigned int count[PCOUNT_MAX];
13377 const struct peer *peer;
13378 const struct bgp_table *table;
54317cba 13379 safi_t safi;
a636c635 13380};
47fc97cc 13381
9bcb3eef 13382static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13383{
54317cba
JW
13384 const struct bgp_adj_in *ain;
13385 const struct bgp_path_info *pi;
d62a17ae 13386 const struct peer *peer = pc->peer;
13387
54317cba
JW
13388 for (ain = rn->adj_in; ain; ain = ain->next)
13389 if (ain->peer == peer)
13390 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13391
9bcb3eef 13392 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13393
54317cba
JW
13394 if (pi->peer != peer)
13395 continue;
d62a17ae 13396
54317cba 13397 pc->count[PCOUNT_ALL]++;
d62a17ae 13398
54317cba
JW
13399 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13400 pc->count[PCOUNT_DAMPED]++;
13401 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13402 pc->count[PCOUNT_HISTORY]++;
13403 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13404 pc->count[PCOUNT_REMOVED]++;
13405 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13406 pc->count[PCOUNT_STALE]++;
13407 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13408 pc->count[PCOUNT_VALID]++;
13409 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13410 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13411 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13412 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13413
13414 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13415 pc->count[PCOUNT_COUNTED]++;
13416 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13417 flog_err(
13418 EC_LIB_DEVELOPMENT,
13419 "Attempting to count but flags say it is unusable");
13420 } else {
40381db7 13421 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13422 flog_err(
13423 EC_LIB_DEVELOPMENT,
13424 "Not counted but flags say we should");
d62a17ae 13425 }
13426 }
54317cba
JW
13427}
13428
cc9f21da 13429static void bgp_peer_count_walker(struct thread *t)
54317cba 13430{
9bcb3eef 13431 struct bgp_dest *rn, *rm;
54317cba
JW
13432 const struct bgp_table *table;
13433 struct peer_pcounts *pc = THREAD_ARG(t);
13434
13435 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13436 || pc->safi == SAFI_EVPN) {
13437 /* Special handling for 2-level routing tables. */
13438 for (rn = bgp_table_top(pc->table); rn;
13439 rn = bgp_route_next(rn)) {
9bcb3eef 13440 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13441 if (table != NULL)
13442 for (rm = bgp_table_top(table); rm;
13443 rm = bgp_route_next(rm))
13444 bgp_peer_count_proc(rm, pc);
13445 }
13446 } else
13447 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13448 bgp_peer_count_proc(rn, pc);
718e3744 13449}
13450
d62a17ae 13451static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13452 safi_t safi, bool use_json)
856ca177 13453{
d62a17ae 13454 struct peer_pcounts pcounts = {.peer = peer};
13455 unsigned int i;
13456 json_object *json = NULL;
13457 json_object *json_loop = NULL;
856ca177 13458
d62a17ae 13459 if (use_json) {
13460 json = json_object_new_object();
13461 json_loop = json_object_new_object();
13462 }
718e3744 13463
d62a17ae 13464 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13465 || !peer->bgp->rib[afi][safi]) {
13466 if (use_json) {
13467 json_object_string_add(
13468 json, "warning",
13469 "No such neighbor or address family");
13470 vty_out(vty, "%s\n", json_object_to_json_string(json));
13471 json_object_free(json);
d5f20468 13472 json_object_free(json_loop);
d62a17ae 13473 } else
13474 vty_out(vty, "%% No such neighbor or address family\n");
13475
13476 return CMD_WARNING;
13477 }
2a71e9ce 13478
d62a17ae 13479 memset(&pcounts, 0, sizeof(pcounts));
13480 pcounts.peer = peer;
13481 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13482 pcounts.safi = safi;
d62a17ae 13483
13484 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13485 * stats for the thread-walk (i.e. ensure this can't be blamed on
13486 * on just vty_read()).
13487 */
d62a17ae 13488 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13489
13490 if (use_json) {
13491 json_object_string_add(json, "prefixCountsFor", peer->host);
13492 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13493 get_afi_safi_str(afi, safi, true));
d62a17ae 13494 json_object_int_add(json, "pfxCounter",
13495 peer->pcount[afi][safi]);
13496
13497 for (i = 0; i < PCOUNT_MAX; i++)
13498 json_object_int_add(json_loop, pcount_strs[i],
13499 pcounts.count[i]);
13500
13501 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13502
13503 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13504 json_object_string_add(json, "pfxctDriftFor",
13505 peer->host);
13506 json_object_string_add(
13507 json, "recommended",
13508 "Please report this bug, with the above command output");
13509 }
75eeda93 13510 vty_json(vty, json);
d62a17ae 13511 } else {
13512
13513 if (peer->hostname
892fedb6 13514 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13515 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13516 peer->hostname, peer->host,
5cb5f4d0 13517 get_afi_safi_str(afi, safi, false));
d62a17ae 13518 } else {
13519 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13520 get_afi_safi_str(afi, safi, false));
d62a17ae 13521 }
13522
6cde4b45 13523 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13524 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13525
13526 for (i = 0; i < PCOUNT_MAX; i++)
13527 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13528 pcounts.count[i]);
13529
13530 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13531 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13532 vty_out(vty,
13533 "Please report this bug, with the above command output\n");
13534 }
13535 }
13536
13537 return CMD_SUCCESS;
718e3744 13538}
13539
a636c635
DW
13540DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13541 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13542 "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 13543 SHOW_STR
13544 IP_STR
13545 BGP_STR
8386ac43 13546 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13547 BGP_AFI_HELP_STR
13548 BGP_SAFI_HELP_STR
0b16f239
DS
13549 "Detailed information on TCP and BGP neighbor connections\n"
13550 "Neighbor to display information about\n"
13551 "Neighbor to display information about\n"
91d37724 13552 "Neighbor on BGP configured interface\n"
a636c635 13553 "Display detailed prefix count information\n"
9973d184 13554 JSON_STR)
0b16f239 13555{
d62a17ae 13556 afi_t afi = AFI_IP6;
13557 safi_t safi = SAFI_UNICAST;
13558 struct peer *peer;
13559 int idx = 0;
13560 struct bgp *bgp = NULL;
9f049418
DS
13561 bool uj = use_json(argc, argv);
13562
13563 if (uj)
13564 argc--;
856ca177 13565
d62a17ae 13566 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13567 &bgp, uj);
d62a17ae 13568 if (!idx)
13569 return CMD_WARNING;
0b16f239 13570
d62a17ae 13571 argv_find(argv, argc, "neighbors", &idx);
13572 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13573 if (!peer)
13574 return CMD_WARNING;
bb46e94f 13575
29c8d9da 13576 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13577}
0b16f239 13578
d6902373
PG
13579#ifdef KEEP_OLD_VPN_COMMANDS
13580DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13581 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13582 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13583 SHOW_STR
13584 IP_STR
13585 BGP_STR
d6902373 13586 BGP_VPNVX_HELP_STR
91d37724 13587 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13588 "Detailed information on TCP and BGP neighbor connections\n"
13589 "Neighbor to display information about\n"
13590 "Neighbor to display information about\n"
91d37724 13591 "Neighbor on BGP configured interface\n"
a636c635 13592 "Display detailed prefix count information\n"
9973d184 13593 JSON_STR)
a636c635 13594{
d62a17ae 13595 int idx_peer = 6;
13596 struct peer *peer;
9f049418 13597 bool uj = use_json(argc, argv);
a636c635 13598
d62a17ae 13599 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13600 if (!peer)
13601 return CMD_WARNING;
13602
13603 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13604}
13605
d6902373
PG
13606DEFUN (show_ip_bgp_vpn_all_route_prefix,
13607 show_ip_bgp_vpn_all_route_prefix_cmd,
13608 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13609 SHOW_STR
13610 IP_STR
13611 BGP_STR
d6902373 13612 BGP_VPNVX_HELP_STR
91d37724
QY
13613 "Display information about all VPNv4 NLRIs\n"
13614 "Network in the BGP routing table to display\n"
3a2d747c 13615 "Network in the BGP routing table to display\n"
9973d184 13616 JSON_STR)
91d37724 13617{
d62a17ae 13618 int idx = 0;
13619 char *network = NULL;
13620 struct bgp *bgp = bgp_get_default();
13621 if (!bgp) {
13622 vty_out(vty, "Can't find default instance\n");
13623 return CMD_WARNING;
13624 }
87e34b58 13625
d62a17ae 13626 if (argv_find(argv, argc, "A.B.C.D", &idx))
13627 network = argv[idx]->arg;
13628 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13629 network = argv[idx]->arg;
13630 else {
13631 vty_out(vty, "Unable to figure out Network\n");
13632 return CMD_WARNING;
13633 }
87e34b58 13634
d62a17ae 13635 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13636 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13637 use_json(argc, argv));
91d37724 13638}
d6902373 13639#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13640
44c69747
LK
13641DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13642 show_bgp_l2vpn_evpn_route_prefix_cmd,
13643 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13644 SHOW_STR
4c63a661
PG
13645 BGP_STR
13646 L2VPN_HELP_STR
13647 EVPN_HELP_STR
44c69747
LK
13648 "Network in the BGP routing table to display\n"
13649 "Network in the BGP routing table to display\n"
4c63a661
PG
13650 "Network in the BGP routing table to display\n"
13651 "Network in the BGP routing table to display\n"
13652 JSON_STR)
13653{
d62a17ae 13654 int idx = 0;
13655 char *network = NULL;
44c69747 13656 int prefix_check = 0;
a636c635 13657
44c69747
LK
13658 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13659 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13660 network = argv[idx]->arg;
44c69747 13661 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13662 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13663 network = argv[idx]->arg;
44c69747
LK
13664 prefix_check = 1;
13665 } else {
d62a17ae 13666 vty_out(vty, "Unable to figure out Network\n");
13667 return CMD_WARNING;
13668 }
44c69747
LK
13669 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13670 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13671 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13672}
13673
114fc229 13674static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13675 struct bgp_table *table, int *header1,
13676 int *header2, json_object *json,
13677 json_object *json_scode,
13678 json_object *json_ocode, bool wide)
13679{
13680 uint64_t version = table ? table->version : 0;
13681
13682 if (*header1) {
13683 if (json) {
13684 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13685 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13686 "%pI4", &peer->bgp->router_id);
2f9bc755 13687 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13688 peer->bgp->default_local_pref);
13689 json_object_int_add(json, "localAS",
13690 peer->change_local_as
13691 ? peer->change_local_as
13692 : peer->local_as);
2f9bc755
DS
13693 json_object_object_add(json, "bgpStatusCodes",
13694 json_scode);
13695 json_object_object_add(json, "bgpOriginCodes",
13696 json_ocode);
13697 } else {
13698 vty_out(vty,
23d0a753
DA
13699 "BGP table version is %" PRIu64
13700 ", local router ID is %pI4, vrf id ",
114fc229
DA
13701 version, &peer->bgp->router_id);
13702 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13703 vty_out(vty, "%s", VRFID_NONE_STR);
13704 else
114fc229 13705 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13706 vty_out(vty, "\n");
13707 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13708 peer->bgp->default_local_pref);
13709 vty_out(vty, "local AS %u\n",
13710 peer->change_local_as ? peer->change_local_as
13711 : peer->local_as);
2f9bc755
DS
13712 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13713 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13714 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13715 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13716 }
13717 *header1 = 0;
13718 }
13719 if (*header2) {
13720 if (!json)
13721 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13722 : BGP_SHOW_HEADER));
13723 *header2 = 0;
13724 }
13725}
13726
d9478df0
TA
13727static void
13728show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13729 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13730 const char *rmap_name, json_object *json, json_object *json_ar,
13731 json_object *json_scode, json_object *json_ocode,
96c81f66 13732 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13733 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13734{
d62a17ae 13735 struct bgp_adj_in *ain;
13736 struct bgp_adj_out *adj;
9bcb3eef 13737 struct bgp_dest *dest;
d62a17ae 13738 struct bgp *bgp;
d62a17ae 13739 struct attr attr;
13740 int ret;
13741 struct update_subgroup *subgrp;
d62a17ae 13742 struct peer_af *paf;
f99def61 13743 bool route_filtered;
96f3485c
MK
13744 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13745 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13746 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13747 || (safi == SAFI_EVPN))
13748 ? true
13749 : false;
a636c635 13750
d62a17ae 13751 bgp = peer->bgp;
a636c635 13752
d62a17ae 13753 subgrp = peer_subgroup(peer, afi, safi);
13754
6392aaa6 13755 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13756 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13757 if (use_json) {
13758 json_object_int_add(json, "bgpTableVersion",
13759 table->version);
c949c771
DA
13760 json_object_string_addf(json, "bgpLocalRouterId",
13761 "%pI4", &bgp->router_id);
01eced22
AD
13762 json_object_int_add(json, "defaultLocPrf",
13763 bgp->default_local_pref);
114fc229
DA
13764 json_object_int_add(json, "localAS",
13765 peer->change_local_as
13766 ? peer->change_local_as
13767 : peer->local_as);
d62a17ae 13768 json_object_object_add(json, "bgpStatusCodes",
13769 json_scode);
13770 json_object_object_add(json, "bgpOriginCodes",
13771 json_ocode);
07d0c4ed
DA
13772 json_object_string_add(
13773 json, "bgpOriginatingDefaultNetwork",
13774 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13775 } else {
23d0a753
DA
13776 vty_out(vty,
13777 "BGP table version is %" PRIu64
13778 ", local router ID is %pI4, vrf id ",
13779 table->version, &bgp->router_id);
9df8b37c
PZ
13780 if (bgp->vrf_id == VRF_UNKNOWN)
13781 vty_out(vty, "%s", VRFID_NONE_STR);
13782 else
13783 vty_out(vty, "%u", bgp->vrf_id);
13784 vty_out(vty, "\n");
01eced22
AD
13785 vty_out(vty, "Default local pref %u, ",
13786 bgp->default_local_pref);
114fc229
DA
13787 vty_out(vty, "local AS %u\n",
13788 peer->change_local_as ? peer->change_local_as
13789 : peer->local_as);
d62a17ae 13790 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13791 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13792 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13793 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13794
07d0c4ed
DA
13795 vty_out(vty, "Originating default network %s\n\n",
13796 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13797 }
d9478df0 13798 *header1 = 0;
d62a17ae 13799 }
a636c635 13800
9bcb3eef 13801 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13802 if (type == bgp_show_adj_route_received
13803 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13804 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13805 if (ain->peer != peer)
ea47320b 13806 continue;
6392aaa6 13807
114fc229 13808 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13809 header2, json, json_scode,
13810 json_ocode, wide);
13811
13812 if ((safi == SAFI_MPLS_VPN)
13813 || (safi == SAFI_ENCAP)
13814 || (safi == SAFI_EVPN)) {
13815 if (use_json)
13816 json_object_string_add(
13817 json_ar, "rd", rd_str);
13818 else if (show_rd && rd_str) {
13819 vty_out(vty,
13820 "Route Distinguisher: %s\n",
13821 rd_str);
13822 show_rd = false;
13823 }
13824 }
6392aaa6 13825
6f4f49b2 13826 attr = *ain->attr;
f99def61
AD
13827 route_filtered = false;
13828
13829 /* Filter prefix using distribute list,
13830 * filter list or prefix list
13831 */
b54892e0 13832 const struct prefix *rn_p =
9bcb3eef 13833 bgp_dest_get_prefix(dest);
b54892e0
DS
13834 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13835 safi))
13836 == FILTER_DENY)
f99def61
AD
13837 route_filtered = true;
13838
13839 /* Filter prefix using route-map */
b54892e0
DS
13840 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13841 safi, rmap_name, NULL,
13842 0, NULL);
6392aaa6 13843
13c8e163
AD
13844 if (type == bgp_show_adj_route_filtered &&
13845 !route_filtered && ret != RMAP_DENY) {
d498917e 13846 bgp_attr_flush(&attr);
6392aaa6 13847 continue;
d62a17ae 13848 }
6392aaa6 13849
d9478df0
TA
13850 if (type == bgp_show_adj_route_received
13851 && (route_filtered || ret == RMAP_DENY))
13852 (*filtered_count)++;
6392aaa6 13853
7d3cae70 13854 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13855 use_json, json_ar, wide);
d498917e 13856 bgp_attr_flush(&attr);
d9478df0 13857 (*output_count)++;
d62a17ae 13858 }
6392aaa6 13859 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13860 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13861 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13862 if (paf->peer != peer || !adj->attr)
924c3f6a 13863 continue;
d62a17ae 13864
114fc229 13865 show_adj_route_header(vty, peer, table,
d9478df0
TA
13866 header1, header2,
13867 json, json_scode,
13868 json_ocode, wide);
d62a17ae 13869
b54892e0 13870 const struct prefix *rn_p =
9bcb3eef 13871 bgp_dest_get_prefix(dest);
b54892e0 13872
6f4f49b2 13873 attr = *adj->attr;
b755861b 13874 ret = bgp_output_modifier(
b54892e0 13875 peer, rn_p, &attr, afi, safi,
b755861b 13876 rmap_name);
f46d8e1e 13877
b755861b 13878 if (ret != RMAP_DENY) {
d9478df0
TA
13879 if ((safi == SAFI_MPLS_VPN)
13880 || (safi == SAFI_ENCAP)
13881 || (safi == SAFI_EVPN)) {
13882 if (use_json)
13883 json_object_string_add(
13884 json_ar,
13885 "rd",
13886 rd_str);
13887 else if (show_rd
13888 && rd_str) {
13889 vty_out(vty,
13890 "Route Distinguisher: %s\n",
13891 rd_str);
13892 show_rd = false;
13893 }
13894 }
b54892e0 13895 route_vty_out_tmp(
7d3cae70
DA
13896 vty, dest, rn_p, &attr,
13897 safi, use_json, json_ar,
ae248832 13898 wide);
d9478df0 13899 (*output_count)++;
b755861b 13900 } else {
d9478df0 13901 (*filtered_count)++;
a2addae8 13902 }
b755861b 13903
d498917e 13904 bgp_attr_flush(&attr);
924c3f6a 13905 }
f20ce998
DS
13906 } else if (type == bgp_show_adj_route_bestpath) {
13907 struct bgp_path_info *pi;
13908
114fc229
DA
13909 show_adj_route_header(vty, peer, table, header1,
13910 header2, json, json_scode,
13911 json_ocode, wide);
f20ce998
DS
13912
13913 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13914 pi = pi->next) {
13915 if (pi->peer != peer)
13916 continue;
13917
13918 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13919 continue;
13920
7d3cae70 13921 route_vty_out_tmp(vty, dest,
f20ce998
DS
13922 bgp_dest_get_prefix(dest),
13923 pi->attr, safi, use_json,
13924 json_ar, wide);
d9478df0 13925 (*output_count)++;
f20ce998 13926 }
d62a17ae 13927 }
13928 }
a636c635 13929}
2a71e9ce 13930
d62a17ae 13931static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13932 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13933 const char *rmap_name, uint16_t show_flags)
0b16f239 13934{
d9478df0
TA
13935 struct bgp *bgp;
13936 struct bgp_table *table;
d62a17ae 13937 json_object *json = NULL;
d9478df0
TA
13938 json_object *json_scode = NULL;
13939 json_object *json_ocode = NULL;
13940 json_object *json_ar = NULL;
96f3485c 13941 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13942
d9478df0
TA
13943 /* Init BGP headers here so they're only displayed once
13944 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13945 */
13946 int header1 = 1;
13947 int header2 = 1;
13948
13949 /*
13950 * Initialize variables for each RD
13951 * All prefixes under an RD is aggregated within "json_routes"
13952 */
13953 char rd_str[BUFSIZ] = {0};
13954 json_object *json_routes = NULL;
13955
13956
13957 /* For 2-tier tables, prefix counts need to be
13958 * maintained across multiple runs of show_adj_route()
13959 */
13960 unsigned long output_count_per_rd;
13961 unsigned long filtered_count_per_rd;
13962 unsigned long output_count = 0;
13963 unsigned long filtered_count = 0;
13964
13965 if (use_json) {
d62a17ae 13966 json = json_object_new_object();
d9478df0
TA
13967 json_ar = json_object_new_object();
13968 json_scode = json_object_new_object();
13969 json_ocode = json_object_new_object();
13970
13971 json_object_string_add(json_scode, "suppressed", "s");
13972 json_object_string_add(json_scode, "damped", "d");
13973 json_object_string_add(json_scode, "history", "h");
13974 json_object_string_add(json_scode, "valid", "*");
13975 json_object_string_add(json_scode, "best", ">");
13976 json_object_string_add(json_scode, "multipath", "=");
13977 json_object_string_add(json_scode, "internal", "i");
13978 json_object_string_add(json_scode, "ribFailure", "r");
13979 json_object_string_add(json_scode, "stale", "S");
13980 json_object_string_add(json_scode, "removed", "R");
13981
13982 json_object_string_add(json_ocode, "igp", "i");
13983 json_object_string_add(json_ocode, "egp", "e");
13984 json_object_string_add(json_ocode, "incomplete", "?");
13985 }
0b16f239 13986
d62a17ae 13987 if (!peer || !peer->afc[afi][safi]) {
13988 if (use_json) {
13989 json_object_string_add(
13990 json, "warning",
13991 "No such neighbor or address family");
13992 vty_out(vty, "%s\n", json_object_to_json_string(json));
13993 json_object_free(json);
690c3134
MW
13994 json_object_free(json_ar);
13995 json_object_free(json_scode);
13996 json_object_free(json_ocode);
d62a17ae 13997 } else
13998 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13999
d62a17ae 14000 return CMD_WARNING;
14001 }
14002
6392aaa6
PM
14003 if ((type == bgp_show_adj_route_received
14004 || type == bgp_show_adj_route_filtered)
d62a17ae 14005 && !CHECK_FLAG(peer->af_flags[afi][safi],
14006 PEER_FLAG_SOFT_RECONFIG)) {
14007 if (use_json) {
14008 json_object_string_add(
14009 json, "warning",
14010 "Inbound soft reconfiguration not enabled");
14011 vty_out(vty, "%s\n", json_object_to_json_string(json));
14012 json_object_free(json);
690c3134
MW
14013 json_object_free(json_ar);
14014 json_object_free(json_scode);
14015 json_object_free(json_ocode);
d62a17ae 14016 } else
14017 vty_out(vty,
14018 "%% Inbound soft reconfiguration not enabled\n");
14019
14020 return CMD_WARNING;
14021 }
0b16f239 14022
d9478df0
TA
14023 bgp = peer->bgp;
14024
14025 /* labeled-unicast routes live in the unicast table */
14026 if (safi == SAFI_LABELED_UNICAST)
14027 table = bgp->rib[afi][SAFI_UNICAST];
14028 else
14029 table = bgp->rib[afi][safi];
14030
14031 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14032 || (safi == SAFI_EVPN)) {
14033
14034 struct bgp_dest *dest;
14035
14036 for (dest = bgp_table_top(table); dest;
14037 dest = bgp_route_next(dest)) {
14038 table = bgp_dest_get_bgp_table_info(dest);
14039 if (!table)
14040 continue;
14041
14042 output_count_per_rd = 0;
14043 filtered_count_per_rd = 0;
14044
14045 if (use_json)
14046 json_routes = json_object_new_object();
14047
14048 const struct prefix_rd *prd;
14049 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14050 dest);
14051
14052 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14053
14054 show_adj_route(vty, peer, table, afi, safi, type,
14055 rmap_name, json, json_routes, json_scode,
14056 json_ocode, show_flags, &header1,
14057 &header2, rd_str, &output_count_per_rd,
14058 &filtered_count_per_rd);
14059
14060 /* Don't include an empty RD in the output! */
14061 if (json_routes && (output_count_per_rd > 0))
14062 json_object_object_add(json_ar, rd_str,
14063 json_routes);
14064
14065 output_count += output_count_per_rd;
14066 filtered_count += filtered_count_per_rd;
14067 }
14068 } else
14069 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14070 json, json_ar, json_scode, json_ocode,
14071 show_flags, &header1, &header2, rd_str,
14072 &output_count, &filtered_count);
14073
14074 if (use_json) {
c1984955
TA
14075 if (type == bgp_show_adj_route_advertised)
14076 json_object_object_add(json, "advertisedRoutes",
14077 json_ar);
14078 else
14079 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14080 json_object_int_add(json, "totalPrefixCounter", output_count);
14081 json_object_int_add(json, "filteredPrefixCounter",
14082 filtered_count);
14083
690c3134
MW
14084 /*
14085 * These fields only give up ownership to `json` when `header1`
14086 * is used (set to zero). See code in `show_adj_route` and
14087 * `show_adj_route_header`.
14088 */
14089 if (header1 == 1) {
d9478df0
TA
14090 json_object_free(json_scode);
14091 json_object_free(json_ocode);
14092 }
14093
75eeda93 14094 vty_json(vty, json);
d9478df0
TA
14095 } else if (output_count > 0) {
14096 if (filtered_count > 0)
14097 vty_out(vty,
14098 "\nTotal number of prefixes %ld (%ld filtered)\n",
14099 output_count, filtered_count);
14100 else
14101 vty_out(vty, "\nTotal number of prefixes %ld\n",
14102 output_count);
14103 }
0b16f239 14104
d62a17ae 14105 return CMD_SUCCESS;
a636c635 14106}
50ef26d4 14107
f20ce998
DS
14108DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14109 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14110 "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]",
14111 SHOW_STR
14112 IP_STR
14113 BGP_STR
14114 BGP_INSTANCE_HELP_STR
14115 BGP_AFI_HELP_STR
14116 BGP_SAFI_WITH_LABEL_HELP_STR
14117 "Detailed information on TCP and BGP neighbor connections\n"
14118 "Neighbor to display information about\n"
14119 "Neighbor to display information about\n"
14120 "Neighbor on BGP configured interface\n"
14121 "Display the routes selected by best path\n"
14122 JSON_STR
14123 "Increase table width for longer prefixes\n")
14124{
14125 afi_t afi = AFI_IP6;
14126 safi_t safi = SAFI_UNICAST;
14127 char *rmap_name = NULL;
14128 char *peerstr = NULL;
14129 struct bgp *bgp = NULL;
14130 struct peer *peer;
14131 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14132 int idx = 0;
96c81f66 14133 uint16_t show_flags = 0;
96f3485c
MK
14134
14135 if (uj)
14136 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14137
14138 if (wide)
14139 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14140
14141 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14142 &bgp, uj);
14143
14144 if (!idx)
14145 return CMD_WARNING;
14146
14147 argv_find(argv, argc, "neighbors", &idx);
14148 peerstr = argv[++idx]->arg;
14149
14150 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14151 if (!peer)
14152 return CMD_WARNING;
14153
96f3485c
MK
14154 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14155 show_flags);
f20ce998
DS
14156}
14157
ae248832 14158DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14159 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14160 "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 RMAP_NAME$route_map] [json$uj | wide$wide]",
718e3744 14161 SHOW_STR
14162 IP_STR
14163 BGP_STR
a636c635 14164 BGP_INSTANCE_HELP_STR
7395a2c9 14165 BGP_AFI_HELP_STR
4dd6177e 14166 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14167 "Display the entries for all address families\n"
718e3744 14168 "Detailed information on TCP and BGP neighbor connections\n"
14169 "Neighbor to display information about\n"
14170 "Neighbor to display information about\n"
91d37724 14171 "Neighbor on BGP configured interface\n"
a636c635 14172 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14173 "Display the received routes from neighbor\n"
14174 "Display the filtered routes received from neighbor\n"
a636c635
DW
14175 "Route-map to modify the attributes\n"
14176 "Name of the route map\n"
ae248832
MK
14177 JSON_STR
14178 "Increase table width for longer prefixes\n")
718e3744 14179{
d62a17ae 14180 afi_t afi = AFI_IP6;
14181 safi_t safi = SAFI_UNICAST;
d62a17ae 14182 char *peerstr = NULL;
d62a17ae 14183 struct bgp *bgp = NULL;
14184 struct peer *peer;
6392aaa6 14185 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14186 int idx = 0;
96f3485c 14187 bool first = true;
96c81f66 14188 uint16_t show_flags = 0;
75ce3b14
DA
14189 struct listnode *node;
14190 struct bgp *abgp;
6392aaa6 14191
96f3485c 14192 if (uj) {
d62a17ae 14193 argc--;
96f3485c
MK
14194 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14195 }
14196
14197 if (all) {
14198 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14199 if (argv_find(argv, argc, "ipv4", &idx))
14200 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14201
14202 if (argv_find(argv, argc, "ipv6", &idx))
14203 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14204 }
14205
14206 if (wide)
14207 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14208
9f049418
DS
14209 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14210 &bgp, uj);
14211 if (!idx)
14212 return CMD_WARNING;
14213
d62a17ae 14214 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14215 argv_find(argv, argc, "neighbors", &idx);
14216 peerstr = argv[++idx]->arg;
8c3deaae 14217
d62a17ae 14218 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14219 if (!peer)
14220 return CMD_WARNING;
856ca177 14221
d62a17ae 14222 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14223 type = bgp_show_adj_route_advertised;
14224 else if (argv_find(argv, argc, "received-routes", &idx))
14225 type = bgp_show_adj_route_received;
14226 else if (argv_find(argv, argc, "filtered-routes", &idx))
14227 type = bgp_show_adj_route_filtered;
14228
96f3485c 14229 if (!all)
70dd370f 14230 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14231 show_flags);
14232 if (uj)
14233 vty_out(vty, "{\n");
14234
14235 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14236 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14237 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14238 : AFI_IP6;
75ce3b14
DA
14239 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14240 FOREACH_SAFI (safi) {
14241 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14242 continue;
96f3485c 14243
75ce3b14
DA
14244 if (uj) {
14245 if (first)
14246 first = false;
14247 else
14248 vty_out(vty, ",\n");
14249 vty_out(vty, "\"%s\":",
14250 get_afi_safi_str(afi, safi,
14251 true));
14252 } else
14253 vty_out(vty,
14254 "\nFor address family: %s\n",
14255 get_afi_safi_str(afi, safi,
14256 false));
96f3485c 14257
75ce3b14 14258 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14259 route_map, show_flags);
75ce3b14 14260 }
96f3485c
MK
14261 }
14262 } else {
75ce3b14
DA
14263 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14264 FOREACH_AFI_SAFI (afi, safi) {
14265 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14266 continue;
96f3485c 14267
75ce3b14
DA
14268 if (uj) {
14269 if (first)
14270 first = false;
14271 else
14272 vty_out(vty, ",\n");
14273 vty_out(vty, "\"%s\":",
14274 get_afi_safi_str(afi, safi,
14275 true));
14276 } else
14277 vty_out(vty,
14278 "\nFor address family: %s\n",
14279 get_afi_safi_str(afi, safi,
14280 false));
96f3485c 14281
75ce3b14 14282 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14283 route_map, show_flags);
75ce3b14 14284 }
96f3485c
MK
14285 }
14286 }
14287 if (uj)
14288 vty_out(vty, "}\n");
14289
14290 return CMD_SUCCESS;
95cbbd2a
ML
14291}
14292
718e3744 14293DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14294 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14295 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14296 SHOW_STR
14297 IP_STR
14298 BGP_STR
d3120452 14299 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14300 BGP_AF_STR
14301 BGP_AF_STR
14302 BGP_AF_MODIFIER_STR
718e3744 14303 "Detailed information on TCP and BGP neighbor connections\n"
14304 "Neighbor to display information about\n"
14305 "Neighbor to display information about\n"
91d37724 14306 "Neighbor on BGP configured interface\n"
718e3744 14307 "Display information received from a BGP neighbor\n"
856ca177 14308 "Display the prefixlist filter\n"
9973d184 14309 JSON_STR)
718e3744 14310{
d62a17ae 14311 afi_t afi = AFI_IP6;
14312 safi_t safi = SAFI_UNICAST;
14313 char *peerstr = NULL;
d62a17ae 14314 char name[BUFSIZ];
d62a17ae 14315 struct peer *peer;
d3120452 14316 int count;
d62a17ae 14317 int idx = 0;
d3120452
IR
14318 struct bgp *bgp = NULL;
14319 bool uj = use_json(argc, argv);
14320
14321 if (uj)
14322 argc--;
14323
14324 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14325 &bgp, uj);
14326 if (!idx)
14327 return CMD_WARNING;
d62a17ae 14328
d62a17ae 14329 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14330 argv_find(argv, argc, "neighbors", &idx);
14331 peerstr = argv[++idx]->arg;
14332
d3120452
IR
14333 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14334 if (!peer)
14335 return CMD_WARNING;
718e3744 14336
4ced1a2c 14337 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14338 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14339 if (count) {
14340 if (!uj)
14341 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14342 get_afi_safi_str(afi, safi, false));
d62a17ae 14343 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14344 } else {
14345 if (uj)
14346 vty_out(vty, "{}\n");
14347 else
14348 vty_out(vty, "No functional output\n");
14349 }
718e3744 14350
d62a17ae 14351 return CMD_SUCCESS;
14352}
14353
14354static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14355 afi_t afi, safi_t safi,
9f049418 14356 enum bgp_show_type type, bool use_json)
d62a17ae 14357{
96c81f66 14358 uint16_t show_flags = 0;
96f3485c
MK
14359
14360 if (use_json)
14361 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14362
d62a17ae 14363 if (!peer || !peer->afc[afi][safi]) {
14364 if (use_json) {
14365 json_object *json_no = NULL;
14366 json_no = json_object_new_object();
14367 json_object_string_add(
14368 json_no, "warning",
14369 "No such neighbor or address family");
14370 vty_out(vty, "%s\n",
14371 json_object_to_json_string(json_no));
14372 json_object_free(json_no);
14373 } else
14374 vty_out(vty, "%% No such neighbor or address family\n");
14375 return CMD_WARNING;
14376 }
47fc97cc 14377
7daf25a3
TA
14378 /* labeled-unicast routes live in the unicast table */
14379 if (safi == SAFI_LABELED_UNICAST)
14380 safi = SAFI_UNICAST;
14381
1e2ce4f1
DS
14382 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14383 RPKI_NOT_BEING_USED);
718e3744 14384}
14385
dba3c1d3
PG
14386DEFUN (show_ip_bgp_flowspec_routes_detailed,
14387 show_ip_bgp_flowspec_routes_detailed_cmd,
14388 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14389 SHOW_STR
14390 IP_STR
14391 BGP_STR
14392 BGP_INSTANCE_HELP_STR
14393 BGP_AFI_HELP_STR
14394 "SAFI Flowspec\n"
14395 "Detailed information on flowspec entries\n"
14396 JSON_STR)
14397{
458c1475 14398 afi_t afi = AFI_IP6;
dba3c1d3
PG
14399 safi_t safi = SAFI_UNICAST;
14400 struct bgp *bgp = NULL;
14401 int idx = 0;
9f049418 14402 bool uj = use_json(argc, argv);
5be6fa9b 14403 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14404
96f3485c 14405 if (uj) {
9f049418 14406 argc--;
96f3485c
MK
14407 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14408 }
dba3c1d3
PG
14409
14410 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14411 &bgp, uj);
dba3c1d3
PG
14412 if (!idx)
14413 return CMD_WARNING;
14414
96f3485c 14415 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14416 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14417}
14418
718e3744 14419DEFUN (show_ip_bgp_neighbor_routes,
14420 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14421 "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 14422 SHOW_STR
14423 IP_STR
14424 BGP_STR
8386ac43 14425 BGP_INSTANCE_HELP_STR
4f280b15 14426 BGP_AFI_HELP_STR
4dd6177e 14427 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14428 "Detailed information on TCP and BGP neighbor connections\n"
14429 "Neighbor to display information about\n"
14430 "Neighbor to display information about\n"
91d37724 14431 "Neighbor on BGP configured interface\n"
2525cf39 14432 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14433 "Display the dampened routes received from neighbor\n"
14434 "Display routes learned from neighbor\n"
9973d184 14435 JSON_STR)
718e3744 14436{
d62a17ae 14437 char *peerstr = NULL;
14438 struct bgp *bgp = NULL;
14439 afi_t afi = AFI_IP6;
14440 safi_t safi = SAFI_UNICAST;
14441 struct peer *peer;
14442 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14443 int idx = 0;
9f049418
DS
14444 bool uj = use_json(argc, argv);
14445
14446 if (uj)
14447 argc--;
bb46e94f 14448
d62a17ae 14449 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14450 &bgp, uj);
d62a17ae 14451 if (!idx)
14452 return CMD_WARNING;
c493f2d8 14453
d62a17ae 14454 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14455 argv_find(argv, argc, "neighbors", &idx);
14456 peerstr = argv[++idx]->arg;
8c3deaae 14457
d62a17ae 14458 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14459 if (!peer)
d62a17ae 14460 return CMD_WARNING;
bb46e94f 14461
d62a17ae 14462 if (argv_find(argv, argc, "flap-statistics", &idx))
14463 sh_type = bgp_show_type_flap_neighbor;
14464 else if (argv_find(argv, argc, "dampened-routes", &idx))
14465 sh_type = bgp_show_type_damp_neighbor;
14466 else if (argv_find(argv, argc, "routes", &idx))
14467 sh_type = bgp_show_type_neighbor;
2525cf39 14468
d62a17ae 14469 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14470}
6b0655a2 14471
734b349e 14472struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14473
d62a17ae 14474struct bgp_distance {
14475 /* Distance value for the IP source prefix. */
d7c0a89a 14476 uint8_t distance;
718e3744 14477
d62a17ae 14478 /* Name of the access-list to be matched. */
14479 char *access_list;
718e3744 14480};
14481
4f280b15
LB
14482DEFUN (show_bgp_afi_vpn_rd_route,
14483 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14484 "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
14485 SHOW_STR
14486 BGP_STR
14487 BGP_AFI_HELP_STR
00e6edb9 14488 BGP_AF_MODIFIER_STR
4f280b15
LB
14489 "Display information for a route distinguisher\n"
14490 "Route Distinguisher\n"
a111dd97 14491 "All Route Distinguishers\n"
7395a2c9
DS
14492 "Network in the BGP routing table to display\n"
14493 "Network in the BGP routing table to display\n"
14494 JSON_STR)
4f280b15 14495{
d62a17ae 14496 int ret;
14497 struct prefix_rd prd;
14498 afi_t afi = AFI_MAX;
14499 int idx = 0;
4f280b15 14500
ff6566f3
DS
14501 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14502 vty_out(vty, "%% Malformed Address Family\n");
14503 return CMD_WARNING;
14504 }
14505
a111dd97
TA
14506 if (!strcmp(argv[5]->arg, "all"))
14507 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14508 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14509 RPKI_NOT_BEING_USED,
14510 use_json(argc, argv));
14511
d62a17ae 14512 ret = str2prefix_rd(argv[5]->arg, &prd);
14513 if (!ret) {
14514 vty_out(vty, "%% Malformed Route Distinguisher\n");
14515 return CMD_WARNING;
14516 }
ff6566f3 14517
d62a17ae 14518 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14519 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14520 use_json(argc, argv));
4f280b15
LB
14521}
14522
d62a17ae 14523static struct bgp_distance *bgp_distance_new(void)
718e3744 14524{
d62a17ae 14525 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14526}
14527
d62a17ae 14528static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14529{
d62a17ae 14530 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14531}
14532
585f1adc
IR
14533static int bgp_distance_set(struct vty *vty, const char *distance_str,
14534 const char *ip_str, const char *access_list_str)
718e3744 14535{
d62a17ae 14536 int ret;
585f1adc
IR
14537 afi_t afi;
14538 safi_t safi;
d62a17ae 14539 struct prefix p;
585f1adc 14540 uint8_t distance;
9bcb3eef 14541 struct bgp_dest *dest;
d62a17ae 14542 struct bgp_distance *bdistance;
718e3744 14543
585f1adc
IR
14544 afi = bgp_node_afi(vty);
14545 safi = bgp_node_safi(vty);
14546
d62a17ae 14547 ret = str2prefix(ip_str, &p);
14548 if (ret == 0) {
585f1adc 14549 vty_out(vty, "Malformed prefix\n");
d62a17ae 14550 return CMD_WARNING_CONFIG_FAILED;
14551 }
718e3744 14552
585f1adc
IR
14553 distance = atoi(distance_str);
14554
d62a17ae 14555 /* Get BGP distance node. */
9bcb3eef
DS
14556 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14557 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14558 if (bdistance)
9bcb3eef 14559 bgp_dest_unlock_node(dest);
ca2e160d 14560 else {
d62a17ae 14561 bdistance = bgp_distance_new();
9bcb3eef 14562 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14563 }
718e3744 14564
d62a17ae 14565 /* Set distance value. */
14566 bdistance->distance = distance;
718e3744 14567
d62a17ae 14568 /* Reset access-list configuration. */
e1b36e13 14569 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14570 if (access_list_str)
14571 bdistance->access_list =
14572 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14573
d62a17ae 14574 return CMD_SUCCESS;
718e3744 14575}
14576
585f1adc
IR
14577static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14578 const char *ip_str, const char *access_list_str)
718e3744 14579{
d62a17ae 14580 int ret;
585f1adc
IR
14581 afi_t afi;
14582 safi_t safi;
d62a17ae 14583 struct prefix p;
585f1adc 14584 int distance;
9bcb3eef 14585 struct bgp_dest *dest;
d62a17ae 14586 struct bgp_distance *bdistance;
718e3744 14587
585f1adc
IR
14588 afi = bgp_node_afi(vty);
14589 safi = bgp_node_safi(vty);
14590
d62a17ae 14591 ret = str2prefix(ip_str, &p);
14592 if (ret == 0) {
585f1adc 14593 vty_out(vty, "Malformed prefix\n");
d62a17ae 14594 return CMD_WARNING_CONFIG_FAILED;
14595 }
718e3744 14596
9bcb3eef
DS
14597 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14598 if (!dest) {
585f1adc 14599 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14600 return CMD_WARNING_CONFIG_FAILED;
14601 }
718e3744 14602
9bcb3eef 14603 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14604 distance = atoi(distance_str);
1f9a9fff 14605
d62a17ae 14606 if (bdistance->distance != distance) {
585f1adc 14607 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14608 bgp_dest_unlock_node(dest);
d62a17ae 14609 return CMD_WARNING_CONFIG_FAILED;
14610 }
718e3744 14611
0a22ddfb 14612 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14613 bgp_distance_free(bdistance);
718e3744 14614
9bcb3eef
DS
14615 bgp_dest_set_bgp_path_info(dest, NULL);
14616 bgp_dest_unlock_node(dest);
14617 bgp_dest_unlock_node(dest);
718e3744 14618
d62a17ae 14619 return CMD_SUCCESS;
718e3744 14620}
14621
718e3744 14622/* Apply BGP information to distance method. */
b8685f9b 14623uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14624 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14625{
9bcb3eef 14626 struct bgp_dest *dest;
801bb996 14627 struct prefix q = {0};
d62a17ae 14628 struct peer *peer;
14629 struct bgp_distance *bdistance;
14630 struct access_list *alist;
14631 struct bgp_static *bgp_static;
14632
14633 if (!bgp)
14634 return 0;
14635
40381db7 14636 peer = pinfo->peer;
d62a17ae 14637
7b7d48e5
DS
14638 if (pinfo->attr->distance)
14639 return pinfo->attr->distance;
14640
801bb996
CS
14641 /* Check source address.
14642 * Note: for aggregate route, peer can have unspec af type.
14643 */
14644 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14645 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14646 return 0;
14647
9bcb3eef
DS
14648 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14649 if (dest) {
14650 bdistance = bgp_dest_get_bgp_distance_info(dest);
14651 bgp_dest_unlock_node(dest);
d62a17ae 14652
14653 if (bdistance->access_list) {
14654 alist = access_list_lookup(afi, bdistance->access_list);
14655 if (alist
14656 && access_list_apply(alist, p) == FILTER_PERMIT)
14657 return bdistance->distance;
14658 } else
14659 return bdistance->distance;
718e3744 14660 }
718e3744 14661
d62a17ae 14662 /* Backdoor check. */
9bcb3eef
DS
14663 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14664 if (dest) {
14665 bgp_static = bgp_dest_get_bgp_static_info(dest);
14666 bgp_dest_unlock_node(dest);
718e3744 14667
d62a17ae 14668 if (bgp_static->backdoor) {
14669 if (bgp->distance_local[afi][safi])
14670 return bgp->distance_local[afi][safi];
14671 else
14672 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14673 }
718e3744 14674 }
718e3744 14675
d62a17ae 14676 if (peer->sort == BGP_PEER_EBGP) {
14677 if (bgp->distance_ebgp[afi][safi])
14678 return bgp->distance_ebgp[afi][safi];
14679 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14680 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14681 if (bgp->distance_ibgp[afi][safi])
14682 return bgp->distance_ibgp[afi][safi];
14683 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14684 } else {
14685 if (bgp->distance_local[afi][safi])
14686 return bgp->distance_local[afi][safi];
14687 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14688 }
718e3744 14689}
14690
a612fb77
DA
14691/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14692 * we should tell ZEBRA update the routes for a specific
14693 * AFI/SAFI to reflect changes in RIB.
14694 */
585f1adc
IR
14695static void bgp_announce_routes_distance_update(struct bgp *bgp,
14696 afi_t update_afi,
14697 safi_t update_safi)
a612fb77
DA
14698{
14699 afi_t afi;
14700 safi_t safi;
14701
14702 FOREACH_AFI_SAFI (afi, safi) {
14703 if (!bgp_fibupd_safi(safi))
14704 continue;
14705
8b54bc30
DA
14706 if (afi != update_afi && safi != update_safi)
14707 continue;
14708
14709 if (BGP_DEBUG(zebra, ZEBRA))
14710 zlog_debug(
14711 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14712 __func__, afi, safi);
14713 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14714 }
14715}
14716
585f1adc
IR
14717DEFUN (bgp_distance,
14718 bgp_distance_cmd,
14719 "distance bgp (1-255) (1-255) (1-255)",
14720 "Define an administrative distance\n"
14721 "BGP distance\n"
14722 "Distance for routes external to the AS\n"
14723 "Distance for routes internal to the AS\n"
14724 "Distance for local routes\n")
718e3744 14725{
585f1adc 14726 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14727 int idx_number = 2;
14728 int idx_number_2 = 3;
14729 int idx_number_3 = 4;
585f1adc
IR
14730 int distance_ebgp = atoi(argv[idx_number]->arg);
14731 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14732 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14733 afi_t afi;
14734 safi_t safi;
718e3744 14735
d62a17ae 14736 afi = bgp_node_afi(vty);
14737 safi = bgp_node_safi(vty);
718e3744 14738
585f1adc
IR
14739 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14740 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14741 || bgp->distance_local[afi][safi] != distance_local) {
14742 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14743 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14744 bgp->distance_local[afi][safi] = distance_local;
14745 bgp_announce_routes_distance_update(bgp, afi, safi);
14746 }
14747 return CMD_SUCCESS;
14748}
37a87b8f 14749
585f1adc
IR
14750DEFUN (no_bgp_distance,
14751 no_bgp_distance_cmd,
14752 "no distance bgp [(1-255) (1-255) (1-255)]",
14753 NO_STR
14754 "Define an administrative distance\n"
14755 "BGP distance\n"
14756 "Distance for routes external to the AS\n"
14757 "Distance for routes internal to the AS\n"
14758 "Distance for local routes\n")
718e3744 14759{
585f1adc 14760 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14761 afi_t afi;
14762 safi_t safi;
37a87b8f
CS
14763
14764 afi = bgp_node_afi(vty);
14765 safi = bgp_node_safi(vty);
14766
585f1adc
IR
14767 if (bgp->distance_ebgp[afi][safi] != 0
14768 || bgp->distance_ibgp[afi][safi] != 0
14769 || bgp->distance_local[afi][safi] != 0) {
14770 bgp->distance_ebgp[afi][safi] = 0;
14771 bgp->distance_ibgp[afi][safi] = 0;
14772 bgp->distance_local[afi][safi] = 0;
14773 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14774 }
585f1adc
IR
14775 return CMD_SUCCESS;
14776}
37a87b8f 14777
37a87b8f 14778
585f1adc
IR
14779DEFUN (bgp_distance_source,
14780 bgp_distance_source_cmd,
14781 "distance (1-255) A.B.C.D/M",
14782 "Define an administrative distance\n"
14783 "Administrative distance\n"
14784 "IP source prefix\n")
14785{
14786 int idx_number = 1;
14787 int idx_ipv4_prefixlen = 2;
14788 bgp_distance_set(vty, argv[idx_number]->arg,
14789 argv[idx_ipv4_prefixlen]->arg, NULL);
14790 return CMD_SUCCESS;
734b349e
MZ
14791}
14792
585f1adc
IR
14793DEFUN (no_bgp_distance_source,
14794 no_bgp_distance_source_cmd,
14795 "no distance (1-255) A.B.C.D/M",
14796 NO_STR
14797 "Define an administrative distance\n"
14798 "Administrative distance\n"
14799 "IP source prefix\n")
37a87b8f 14800{
585f1adc
IR
14801 int idx_number = 2;
14802 int idx_ipv4_prefixlen = 3;
14803 bgp_distance_unset(vty, argv[idx_number]->arg,
14804 argv[idx_ipv4_prefixlen]->arg, NULL);
14805 return CMD_SUCCESS;
37a87b8f
CS
14806}
14807
585f1adc
IR
14808DEFUN (bgp_distance_source_access_list,
14809 bgp_distance_source_access_list_cmd,
14810 "distance (1-255) A.B.C.D/M WORD",
14811 "Define an administrative distance\n"
14812 "Administrative distance\n"
14813 "IP source prefix\n"
14814 "Access list name\n")
37a87b8f 14815{
585f1adc
IR
14816 int idx_number = 1;
14817 int idx_ipv4_prefixlen = 2;
14818 int idx_word = 3;
14819 bgp_distance_set(vty, argv[idx_number]->arg,
14820 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14821 return CMD_SUCCESS;
14822}
718e3744 14823
585f1adc
IR
14824DEFUN (no_bgp_distance_source_access_list,
14825 no_bgp_distance_source_access_list_cmd,
14826 "no distance (1-255) A.B.C.D/M WORD",
14827 NO_STR
14828 "Define an administrative distance\n"
14829 "Administrative distance\n"
14830 "IP source prefix\n"
14831 "Access list name\n")
14832{
14833 int idx_number = 2;
14834 int idx_ipv4_prefixlen = 3;
14835 int idx_word = 4;
14836 bgp_distance_unset(vty, argv[idx_number]->arg,
14837 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14838 return CMD_SUCCESS;
14839}
37a87b8f 14840
585f1adc
IR
14841DEFUN (ipv6_bgp_distance_source,
14842 ipv6_bgp_distance_source_cmd,
14843 "distance (1-255) X:X::X:X/M",
14844 "Define an administrative distance\n"
14845 "Administrative distance\n"
14846 "IP source prefix\n")
14847{
14848 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14849 return CMD_SUCCESS;
14850}
7ebe9748 14851
585f1adc
IR
14852DEFUN (no_ipv6_bgp_distance_source,
14853 no_ipv6_bgp_distance_source_cmd,
14854 "no distance (1-255) X:X::X:X/M",
14855 NO_STR
14856 "Define an administrative distance\n"
14857 "Administrative distance\n"
14858 "IP source prefix\n")
14859{
14860 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14861 return CMD_SUCCESS;
14862}
37a87b8f 14863
585f1adc
IR
14864DEFUN (ipv6_bgp_distance_source_access_list,
14865 ipv6_bgp_distance_source_access_list_cmd,
14866 "distance (1-255) X:X::X:X/M WORD",
14867 "Define an administrative distance\n"
14868 "Administrative distance\n"
14869 "IP source prefix\n"
14870 "Access list name\n")
14871{
14872 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14873 return CMD_SUCCESS;
718e3744 14874}
14875
585f1adc
IR
14876DEFUN (no_ipv6_bgp_distance_source_access_list,
14877 no_ipv6_bgp_distance_source_access_list_cmd,
14878 "no distance (1-255) X:X::X:X/M WORD",
14879 NO_STR
14880 "Define an administrative distance\n"
14881 "Administrative distance\n"
14882 "IP source prefix\n"
14883 "Access list name\n")
718e3744 14884{
585f1adc
IR
14885 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14886 return CMD_SUCCESS;
14887}
37a87b8f 14888
585f1adc
IR
14889DEFUN (bgp_damp_set,
14890 bgp_damp_set_cmd,
a30fec23 14891 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14892 "BGP Specific commands\n"
14893 "Enable route-flap dampening\n"
14894 "Half-life time for the penalty\n"
14895 "Value to start reusing a route\n"
14896 "Value to start suppressing a route\n"
14897 "Maximum duration to suppress a stable route\n")
14898{
14899 VTY_DECLVAR_CONTEXT(bgp, bgp);
14900 int idx_half_life = 2;
14901 int idx_reuse = 3;
14902 int idx_suppress = 4;
14903 int idx_max_suppress = 5;
37a87b8f
CS
14904 int half = DEFAULT_HALF_LIFE * 60;
14905 int reuse = DEFAULT_REUSE;
14906 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14907 int max = 4 * half;
14908
14909 if (argc == 6) {
14910 half = atoi(argv[idx_half_life]->arg) * 60;
14911 reuse = atoi(argv[idx_reuse]->arg);
14912 suppress = atoi(argv[idx_suppress]->arg);
14913 max = atoi(argv[idx_max_suppress]->arg) * 60;
14914 } else if (argc == 3) {
14915 half = atoi(argv[idx_half_life]->arg) * 60;
14916 max = 4 * half;
14917 }
14918
14919 /*
14920 * These can't be 0 but our SA doesn't understand the
14921 * way our cli is constructed
14922 */
14923 assert(reuse);
14924 assert(half);
14925 if (suppress < reuse) {
14926 vty_out(vty,
14927 "Suppress value cannot be less than reuse value \n");
14928 return 0;
14929 }
14930
14931 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14932 reuse, suppress, max);
14933}
14934
14935DEFUN (bgp_damp_unset,
14936 bgp_damp_unset_cmd,
a30fec23 14937 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14938 NO_STR
14939 "BGP Specific commands\n"
14940 "Enable route-flap dampening\n"
14941 "Half-life time for the penalty\n"
14942 "Value to start reusing a route\n"
14943 "Value to start suppressing a route\n"
14944 "Maximum duration to suppress a stable route\n")
14945{
14946 VTY_DECLVAR_CONTEXT(bgp, bgp);
14947 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14948}
14949
718e3744 14950/* Display specified route of BGP table. */
d62a17ae 14951static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14952 const char *ip_str, afi_t afi, safi_t safi,
14953 struct prefix_rd *prd, int prefix_check)
14954{
14955 int ret;
14956 struct prefix match;
9bcb3eef
DS
14957 struct bgp_dest *dest;
14958 struct bgp_dest *rm;
40381db7
DS
14959 struct bgp_path_info *pi;
14960 struct bgp_path_info *pi_temp;
d62a17ae 14961 struct bgp *bgp;
14962 struct bgp_table *table;
14963
14964 /* BGP structure lookup. */
14965 if (view_name) {
14966 bgp = bgp_lookup_by_name(view_name);
14967 if (bgp == NULL) {
14968 vty_out(vty, "%% Can't find BGP instance %s\n",
14969 view_name);
14970 return CMD_WARNING;
14971 }
14972 } else {
14973 bgp = bgp_get_default();
14974 if (bgp == NULL) {
14975 vty_out(vty, "%% No BGP process is configured\n");
14976 return CMD_WARNING;
14977 }
718e3744 14978 }
718e3744 14979
d62a17ae 14980 /* Check IP address argument. */
14981 ret = str2prefix(ip_str, &match);
14982 if (!ret) {
14983 vty_out(vty, "%% address is malformed\n");
14984 return CMD_WARNING;
14985 }
718e3744 14986
d62a17ae 14987 match.family = afi2family(afi);
14988
14989 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14990 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14991 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14992 dest = bgp_route_next(dest)) {
14993 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14994
9bcb3eef 14995 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14996 continue;
9bcb3eef 14997 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14998 if (!table)
ea47320b 14999 continue;
4953391b
DA
15000 rm = bgp_node_match(table, &match);
15001 if (rm == NULL)
ea47320b 15002 continue;
d62a17ae 15003
9bcb3eef 15004 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15005
ea47320b 15006 if (!prefix_check
b54892e0 15007 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15008 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15009 while (pi) {
15010 if (pi->extra && pi->extra->damp_info) {
15011 pi_temp = pi->next;
ea47320b 15012 bgp_damp_info_free(
19971c9a 15013 pi->extra->damp_info,
5c8846f6 15014 1, afi, safi);
40381db7 15015 pi = pi_temp;
ea47320b 15016 } else
40381db7 15017 pi = pi->next;
d62a17ae 15018 }
ea47320b
DL
15019 }
15020
9bcb3eef 15021 bgp_dest_unlock_node(rm);
d62a17ae 15022 }
15023 } else {
4953391b
DA
15024 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15025 if (dest != NULL) {
9bcb3eef 15026 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15027
d62a17ae 15028 if (!prefix_check
9bcb3eef
DS
15029 || dest_p->prefixlen == match.prefixlen) {
15030 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15031 while (pi) {
15032 if (pi->extra && pi->extra->damp_info) {
15033 pi_temp = pi->next;
d62a17ae 15034 bgp_damp_info_free(
19971c9a 15035 pi->extra->damp_info,
5c8846f6 15036 1, afi, safi);
40381db7 15037 pi = pi_temp;
d62a17ae 15038 } else
40381db7 15039 pi = pi->next;
d62a17ae 15040 }
15041 }
15042
9bcb3eef 15043 bgp_dest_unlock_node(dest);
d62a17ae 15044 }
15045 }
718e3744 15046
d62a17ae 15047 return CMD_SUCCESS;
718e3744 15048}
15049
15050DEFUN (clear_ip_bgp_dampening,
15051 clear_ip_bgp_dampening_cmd,
15052 "clear ip bgp dampening",
15053 CLEAR_STR
15054 IP_STR
15055 BGP_STR
15056 "Clear route flap dampening information\n")
15057{
b4f7f45b 15058 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15059 return CMD_SUCCESS;
718e3744 15060}
15061
15062DEFUN (clear_ip_bgp_dampening_prefix,
15063 clear_ip_bgp_dampening_prefix_cmd,
15064 "clear ip bgp dampening A.B.C.D/M",
15065 CLEAR_STR
15066 IP_STR
15067 BGP_STR
15068 "Clear route flap dampening information\n"
0c7b1b01 15069 "IPv4 prefix\n")
718e3744 15070{
d62a17ae 15071 int idx_ipv4_prefixlen = 4;
15072 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15073 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15074}
15075
15076DEFUN (clear_ip_bgp_dampening_address,
15077 clear_ip_bgp_dampening_address_cmd,
15078 "clear ip bgp dampening A.B.C.D",
15079 CLEAR_STR
15080 IP_STR
15081 BGP_STR
15082 "Clear route flap dampening information\n"
15083 "Network to clear damping information\n")
15084{
d62a17ae 15085 int idx_ipv4 = 4;
15086 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15087 SAFI_UNICAST, NULL, 0);
718e3744 15088}
15089
15090DEFUN (clear_ip_bgp_dampening_address_mask,
15091 clear_ip_bgp_dampening_address_mask_cmd,
15092 "clear ip bgp dampening A.B.C.D A.B.C.D",
15093 CLEAR_STR
15094 IP_STR
15095 BGP_STR
15096 "Clear route flap dampening information\n"
15097 "Network to clear damping information\n"
15098 "Network mask\n")
15099{
d62a17ae 15100 int idx_ipv4 = 4;
15101 int idx_ipv4_2 = 5;
15102 int ret;
15103 char prefix_str[BUFSIZ];
718e3744 15104
d62a17ae 15105 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15106 prefix_str, sizeof(prefix_str));
d62a17ae 15107 if (!ret) {
15108 vty_out(vty, "%% Inconsistent address and mask\n");
15109 return CMD_WARNING;
15110 }
718e3744 15111
d62a17ae 15112 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15113 NULL, 0);
718e3744 15114}
6b0655a2 15115
e3b78da8 15116static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15117{
15118 struct vty *vty = arg;
e3b78da8 15119 struct peer *peer = bucket->data;
825d9834 15120
47e12884 15121 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15122}
15123
2a0e69ae
DS
15124DEFUN (show_bgp_listeners,
15125 show_bgp_listeners_cmd,
15126 "show bgp listeners",
15127 SHOW_STR
15128 BGP_STR
15129 "Display Listen Sockets and who created them\n")
15130{
15131 bgp_dump_listener_info(vty);
15132
15133 return CMD_SUCCESS;
15134}
15135
825d9834
DS
15136DEFUN (show_bgp_peerhash,
15137 show_bgp_peerhash_cmd,
15138 "show bgp peerhash",
15139 SHOW_STR
15140 BGP_STR
15141 "Display information about the BGP peerhash\n")
15142{
15143 struct list *instances = bm->bgp;
15144 struct listnode *node;
15145 struct bgp *bgp;
15146
15147 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15148 vty_out(vty, "BGP: %s\n", bgp->name);
15149 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15150 vty);
15151 }
15152
15153 return CMD_SUCCESS;
15154}
15155
587ff0fd 15156/* also used for encap safi */
2b791107
DL
15157static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15158 afi_t afi, safi_t safi)
d62a17ae 15159{
9bcb3eef
DS
15160 struct bgp_dest *pdest;
15161 struct bgp_dest *dest;
d62a17ae 15162 struct bgp_table *table;
b54892e0
DS
15163 const struct prefix *p;
15164 const struct prefix_rd *prd;
d62a17ae 15165 struct bgp_static *bgp_static;
15166 mpls_label_t label;
d62a17ae 15167 char rdbuf[RD_ADDRSTRLEN];
15168
15169 /* Network configuration. */
9bcb3eef
DS
15170 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15171 pdest = bgp_route_next(pdest)) {
15172 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15173 if (!table)
ea47320b 15174 continue;
d62a17ae 15175
9bcb3eef
DS
15176 for (dest = bgp_table_top(table); dest;
15177 dest = bgp_route_next(dest)) {
15178 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15179 if (bgp_static == NULL)
ea47320b 15180 continue;
d62a17ae 15181
9bcb3eef
DS
15182 p = bgp_dest_get_prefix(dest);
15183 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15184 pdest);
d62a17ae 15185
ea47320b 15186 /* "network" configuration display. */
06b9f471 15187 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
15188 label = decode_label(&bgp_static->label);
15189
8228a9a7 15190 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
15191 if (safi == SAFI_MPLS_VPN)
15192 vty_out(vty, " label %u", label);
15193
15194 if (bgp_static->rmap.name)
15195 vty_out(vty, " route-map %s",
15196 bgp_static->rmap.name);
e2a86ad9
DS
15197
15198 if (bgp_static->backdoor)
15199 vty_out(vty, " backdoor");
15200
ea47320b
DL
15201 vty_out(vty, "\n");
15202 }
15203 }
d62a17ae 15204}
15205
2b791107
DL
15206static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15207 afi_t afi, safi_t safi)
d62a17ae 15208{
9bcb3eef
DS
15209 struct bgp_dest *pdest;
15210 struct bgp_dest *dest;
d62a17ae 15211 struct bgp_table *table;
b54892e0
DS
15212 const struct prefix *p;
15213 const struct prefix_rd *prd;
d62a17ae 15214 struct bgp_static *bgp_static;
ff44f570 15215 char buf[PREFIX_STRLEN * 2];
d62a17ae 15216 char buf2[SU_ADDRSTRLEN];
15217 char rdbuf[RD_ADDRSTRLEN];
5f933e1e 15218 char esi_buf[ESI_STR_LEN];
d62a17ae 15219
15220 /* Network configuration. */
9bcb3eef
DS
15221 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15222 pdest = bgp_route_next(pdest)) {
15223 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15224 if (!table)
ea47320b 15225 continue;
d62a17ae 15226
9bcb3eef
DS
15227 for (dest = bgp_table_top(table); dest;
15228 dest = bgp_route_next(dest)) {
15229 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15230 if (bgp_static == NULL)
ea47320b 15231 continue;
d62a17ae 15232
ea47320b 15233 char *macrouter = NULL;
d62a17ae 15234
ea47320b
DL
15235 if (bgp_static->router_mac)
15236 macrouter = prefix_mac2str(
15237 bgp_static->router_mac, NULL, 0);
15238 if (bgp_static->eth_s_id)
0a50c248
AK
15239 esi_to_str(bgp_static->eth_s_id,
15240 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15241 p = bgp_dest_get_prefix(dest);
15242 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15243
ea47320b 15244 /* "network" configuration display. */
06b9f471 15245 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15246 if (p->u.prefix_evpn.route_type == 5) {
15247 char local_buf[PREFIX_STRLEN];
3714a385 15248 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15249 struct prefix_evpn *)p)
15250 ? AF_INET
15251 : AF_INET6;
3714a385 15252 inet_ntop(family,
15253 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15254 local_buf, PREFIX_STRLEN);
772270f3
QY
15255 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15256 p->u.prefix_evpn.prefix_addr
15257 .ip_prefix_length);
197cb530
PG
15258 } else {
15259 prefix2str(p, buf, sizeof(buf));
15260 }
ea47320b 15261
a4d82a8a
PZ
15262 if (bgp_static->gatewayIp.family == AF_INET
15263 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15264 inet_ntop(bgp_static->gatewayIp.family,
15265 &bgp_static->gatewayIp.u.prefix, buf2,
15266 sizeof(buf2));
ea47320b 15267 vty_out(vty,
7bcc8dac 15268 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15269 buf, rdbuf,
15270 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15271 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15272 macrouter);
15273
0a22ddfb 15274 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15275 }
15276 }
3da6fcd5
PG
15277}
15278
718e3744 15279/* Configuration of static route announcement and aggregate
15280 information. */
2b791107
DL
15281void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15282 safi_t safi)
d62a17ae 15283{
9bcb3eef 15284 struct bgp_dest *dest;
b54892e0 15285 const struct prefix *p;
d62a17ae 15286 struct bgp_static *bgp_static;
15287 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15288
2b791107
DL
15289 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15290 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15291 return;
15292 }
d62a17ae 15293
2b791107
DL
15294 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15295 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15296 return;
15297 }
d62a17ae 15298
15299 /* Network configuration. */
9bcb3eef
DS
15300 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15301 dest = bgp_route_next(dest)) {
15302 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15303 if (bgp_static == NULL)
ea47320b 15304 continue;
d62a17ae 15305
9bcb3eef 15306 p = bgp_dest_get_prefix(dest);
d62a17ae 15307
8228a9a7 15308 vty_out(vty, " network %pFX", p);
d62a17ae 15309
ea47320b
DL
15310 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15311 vty_out(vty, " label-index %u",
15312 bgp_static->label_index);
d62a17ae 15313
ea47320b
DL
15314 if (bgp_static->rmap.name)
15315 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15316
15317 if (bgp_static->backdoor)
15318 vty_out(vty, " backdoor");
718e3744 15319
ea47320b
DL
15320 vty_out(vty, "\n");
15321 }
15322
d62a17ae 15323 /* Aggregate-address configuration. */
9bcb3eef
DS
15324 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15325 dest = bgp_route_next(dest)) {
15326 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15327 if (bgp_aggregate == NULL)
ea47320b 15328 continue;
d62a17ae 15329
9bcb3eef 15330 p = bgp_dest_get_prefix(dest);
d62a17ae 15331
8228a9a7 15332 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15333
ea47320b
DL
15334 if (bgp_aggregate->as_set)
15335 vty_out(vty, " as-set");
d62a17ae 15336
ea47320b
DL
15337 if (bgp_aggregate->summary_only)
15338 vty_out(vty, " summary-only");
718e3744 15339
20894f50
DA
15340 if (bgp_aggregate->rmap.name)
15341 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15342
229757f1
DA
15343 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15344 vty_out(vty, " origin %s",
15345 bgp_origin2str(bgp_aggregate->origin));
15346
6aabb15d
RZ
15347 if (bgp_aggregate->match_med)
15348 vty_out(vty, " matching-MED-only");
15349
365ab2e7
RZ
15350 if (bgp_aggregate->suppress_map_name)
15351 vty_out(vty, " suppress-map %s",
15352 bgp_aggregate->suppress_map_name);
15353
ea47320b
DL
15354 vty_out(vty, "\n");
15355 }
d62a17ae 15356}
734b349e 15357
2b791107 15358void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15359 safi_t safi)
d62a17ae 15360{
9bcb3eef 15361 struct bgp_dest *dest;
d62a17ae 15362 struct bgp_distance *bdistance;
15363
15364 /* Distance configuration. */
15365 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15366 && bgp->distance_local[afi][safi]
15367 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15368 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15369 || bgp->distance_local[afi][safi]
15370 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15371 vty_out(vty, " distance bgp %d %d %d\n",
15372 bgp->distance_ebgp[afi][safi],
15373 bgp->distance_ibgp[afi][safi],
15374 bgp->distance_local[afi][safi]);
15375 }
734b349e 15376
9bcb3eef
DS
15377 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15378 dest = bgp_route_next(dest)) {
15379 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15380 if (bdistance != NULL)
56ca3b5b 15381 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15382 bdistance->distance, dest,
d62a17ae 15383 bdistance->access_list ? bdistance->access_list
15384 : "");
ca2e160d 15385 }
718e3744 15386}
15387
15388/* Allocate routing table structure and install commands. */
d62a17ae 15389void bgp_route_init(void)
15390{
15391 afi_t afi;
15392 safi_t safi;
15393
15394 /* Init BGP distance table. */
05c7a1cc 15395 FOREACH_AFI_SAFI (afi, safi)
960035b2 15396 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15397
15398 /* IPv4 BGP commands. */
15399 install_element(BGP_NODE, &bgp_table_map_cmd);
15400 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15401 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15402
554b3b10 15403 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15404
15405 /* IPv4 unicast configuration. */
15406 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15407 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15408 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15409
554b3b10 15410 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15411
15412 /* IPv4 multicast configuration. */
15413 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15414 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15415 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15416 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15417
15418 /* IPv4 labeled-unicast configuration. */
fb985e0c 15419 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15420 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15421
d62a17ae 15422 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15423 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15424 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15425 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15426 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15427 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15428 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15429 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15430
15431 install_element(VIEW_NODE,
15432 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15433 install_element(VIEW_NODE,
15434 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15435 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15436 install_element(VIEW_NODE,
15437 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15438#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15439 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15440#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15441 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15442 install_element(VIEW_NODE,
44c69747 15443 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15444
d62a17ae 15445 /* BGP dampening clear commands */
15446 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15447 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15448
d62a17ae 15449 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15450 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15451
15452 /* prefix count */
15453 install_element(ENABLE_NODE,
15454 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15455#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15456 install_element(ENABLE_NODE,
15457 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15458#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15459
d62a17ae 15460 /* New config IPv6 BGP commands. */
15461 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15462 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15463 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15464
554b3b10 15465 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15466
15467 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15468
fb985e0c
DA
15469 /* IPv6 labeled unicast address family. */
15470 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15471 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15472
d62a17ae 15473 install_element(BGP_NODE, &bgp_distance_cmd);
15474 install_element(BGP_NODE, &no_bgp_distance_cmd);
15475 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15476 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15477 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15478 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15479 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15480 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15481 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15482 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15483 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15484 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15485 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15486 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15487 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15488 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15489 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15490 install_element(BGP_IPV4M_NODE,
15491 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15492 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15493 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15494 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15495 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15496 install_element(BGP_IPV6_NODE,
15497 &ipv6_bgp_distance_source_access_list_cmd);
15498 install_element(BGP_IPV6_NODE,
15499 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15500 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15501 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15502 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15503 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15504 install_element(BGP_IPV6M_NODE,
15505 &ipv6_bgp_distance_source_access_list_cmd);
15506 install_element(BGP_IPV6M_NODE,
15507 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15508
ef5f4b23 15509 /* BGP dampening */
585f1adc
IR
15510 install_element(BGP_NODE, &bgp_damp_set_cmd);
15511 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15512 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15513 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15514 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15515 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15516 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15517 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15518 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15519 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15520 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15521 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15522 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15523 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15524
15525 /* Large Communities */
15526 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15527 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15528
15529 /* show bgp ipv4 flowspec detailed */
15530 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15531
2a0e69ae 15532 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15533 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15534}
15535
15536void bgp_route_finish(void)
15537{
15538 afi_t afi;
15539 safi_t safi;
15540
05c7a1cc
QY
15541 FOREACH_AFI_SAFI (afi, safi) {
15542 bgp_table_unlock(bgp_distance_table[afi][safi]);
15543 bgp_distance_table[afi][safi] = NULL;
15544 }
228da428 15545}