]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #11333 from opensourcerouting/fix/memory_leak_with_rmaps
[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
5a1ae2c2 1564static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1565 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1566 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1567 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1568{
d62a17ae 1569 struct bgp_filter *filter;
82b692c0
LK
1570 struct bgp_path_info rmap_path = { 0 };
1571 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1572 route_map_result_t ret;
1573 struct route_map *rmap = NULL;
718e3744 1574
d62a17ae 1575 filter = &peer->filter[afi][safi];
718e3744 1576
d62a17ae 1577 /* Apply default weight value. */
1578 if (peer->weight[afi][safi])
1579 attr->weight = peer->weight[afi][safi];
718e3744 1580
d62a17ae 1581 if (rmap_name) {
1582 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1583
d62a17ae 1584 if (rmap == NULL)
1585 return RMAP_DENY;
1586 } else {
1587 if (ROUTE_MAP_IN_NAME(filter)) {
1588 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1589
d62a17ae 1590 if (rmap == NULL)
1591 return RMAP_DENY;
1592 }
1593 }
0b16f239 1594
d62a17ae 1595 /* Route map apply. */
1596 if (rmap) {
6006b807 1597 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1598 /* Duplicate current value to new structure for modification. */
40381db7
DS
1599 rmap_path.peer = peer;
1600 rmap_path.attr = attr;
82b692c0 1601 rmap_path.extra = &extra;
9bcb3eef 1602 rmap_path.net = dest;
196c6b09 1603
82b692c0
LK
1604 extra.num_labels = num_labels;
1605 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1606 memcpy(extra.label, label,
1607 num_labels * sizeof(mpls_label_t));
718e3744 1608
d62a17ae 1609 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1610
d62a17ae 1611 /* Apply BGP route map to the attribute. */
1782514f 1612 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1613
d62a17ae 1614 peer->rmap_type = 0;
0b16f239 1615
1f2263be 1616 if (ret == RMAP_DENYMATCH)
d62a17ae 1617 return RMAP_DENY;
0b16f239 1618 }
d62a17ae 1619 return RMAP_PERMIT;
0b16f239
DS
1620}
1621
5f040085 1622static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1623 struct attr *attr, afi_t afi, safi_t safi,
1624 const char *rmap_name)
0b16f239 1625{
40381db7 1626 struct bgp_path_info rmap_path;
d62a17ae 1627 route_map_result_t ret;
1628 struct route_map *rmap = NULL;
d7c0a89a 1629 uint8_t rmap_type;
0b16f239 1630
b787157a
DS
1631 /*
1632 * So if we get to this point and have no rmap_name
1633 * we want to just show the output as it currently
1634 * exists.
1635 */
1636 if (!rmap_name)
1637 return RMAP_PERMIT;
0b16f239 1638
d62a17ae 1639 /* Apply default weight value. */
1640 if (peer->weight[afi][safi])
1641 attr->weight = peer->weight[afi][safi];
0b16f239 1642
b787157a 1643 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1644
b787157a
DS
1645 /*
1646 * If we have a route map name and we do not find
1647 * the routemap that means we have an implicit
1648 * deny.
1649 */
1650 if (rmap == NULL)
1651 return RMAP_DENY;
0b16f239 1652
6006b807 1653 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1654 /* Route map apply. */
544be979 1655 /* Duplicate current value to new structure for modification. */
40381db7
DS
1656 rmap_path.peer = peer;
1657 rmap_path.attr = attr;
0b16f239 1658
0f672529 1659 rmap_type = peer->rmap_type;
b787157a 1660 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1661
b787157a 1662 /* Apply BGP route map to the attribute. */
1782514f 1663 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1664
0f672529 1665 peer->rmap_type = rmap_type;
b787157a
DS
1666
1667 if (ret == RMAP_DENYMATCH)
1668 /*
1669 * caller has multiple error paths with bgp_attr_flush()
1670 */
1671 return RMAP_DENY;
ac41b2a2 1672
d62a17ae 1673 return RMAP_PERMIT;
718e3744 1674}
6b0655a2 1675
5000f21c 1676/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1677static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1678 struct peer *peer, struct attr *attr)
1679{
1680 if (peer->sort == BGP_PEER_EBGP
1681 && (peer_af_flag_check(peer, afi, safi,
1682 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1683 || peer_af_flag_check(peer, afi, safi,
1684 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1685 || peer_af_flag_check(peer, afi, safi,
1686 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1687 || peer_af_flag_check(peer, afi, safi,
1688 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1689 // Take action on the entire aspath
1690 if (peer_af_flag_check(peer, afi, safi,
1691 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1692 || peer_af_flag_check(peer, afi, safi,
1693 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1694 if (peer_af_flag_check(
1695 peer, afi, safi,
1696 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1697 attr->aspath = aspath_replace_private_asns(
bf26b80e 1698 attr->aspath, bgp->as, peer->as);
d62a17ae 1699
179d5a0e
TA
1700 /*
1701 * Even if the aspath consists of just private ASNs we
1702 * need to walk the AS-Path to maintain all instances
1703 * of the peer's ASN to break possible loops.
1704 */
d62a17ae 1705 else
1706 attr->aspath = aspath_remove_private_asns(
bf26b80e 1707 attr->aspath, peer->as);
d62a17ae 1708 }
1709
1710 // 'all' was not specified so the entire aspath must be private
1711 // ASNs
1712 // for us to do anything
1713 else if (aspath_private_as_check(attr->aspath)) {
1714 if (peer_af_flag_check(
1715 peer, afi, safi,
1716 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1717 attr->aspath = aspath_replace_private_asns(
bf26b80e 1718 attr->aspath, bgp->as, peer->as);
d62a17ae 1719 else
179d5a0e
TA
1720 /*
1721 * Walk the aspath to retain any instances of
1722 * the peer_asn
1723 */
1724 attr->aspath = aspath_remove_private_asns(
1725 attr->aspath, peer->as);
d62a17ae 1726 }
1727 }
5000f21c
DS
1728}
1729
c7122e14 1730/* If this is an EBGP peer with as-override */
d62a17ae 1731static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1732 struct peer *peer, struct attr *attr)
1733{
1734 if (peer->sort == BGP_PEER_EBGP
1735 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1736 if (aspath_single_asn_check(attr->aspath, peer->as))
1737 attr->aspath = aspath_replace_specific_asn(
1738 attr->aspath, peer->as, bgp->as);
1739 }
1740}
1741
1479ed2f
DA
1742void bgp_attr_add_llgr_community(struct attr *attr)
1743{
1744 struct community *old;
1745 struct community *new;
1746 struct community *merge;
1747 struct community *llgr;
1748
9a706b42 1749 old = bgp_attr_get_community(attr);
1479ed2f
DA
1750 llgr = community_str2com("llgr-stale");
1751
1752 assert(llgr);
1753
1754 if (old) {
1755 merge = community_merge(community_dup(old), llgr);
1756
1757 if (old->refcnt == 0)
1758 community_free(&old);
1759
1760 new = community_uniq_sort(merge);
1761 community_free(&merge);
1762 } else {
1763 new = community_dup(llgr);
1764 }
1765
1766 community_free(&llgr);
1767
9a706b42 1768 bgp_attr_set_community(attr, new);
1479ed2f
DA
1769}
1770
7f323236
DW
1771void bgp_attr_add_gshut_community(struct attr *attr)
1772{
1773 struct community *old;
1774 struct community *new;
1775 struct community *merge;
1776 struct community *gshut;
1777
9a706b42 1778 old = bgp_attr_get_community(attr);
7f323236
DW
1779 gshut = community_str2com("graceful-shutdown");
1780
990f4f91 1781 assert(gshut);
1782
7f323236
DW
1783 if (old) {
1784 merge = community_merge(community_dup(old), gshut);
1785
a4d82a8a 1786 if (old->refcnt == 0)
3c1f53de 1787 community_free(&old);
7f323236
DW
1788
1789 new = community_uniq_sort(merge);
3c1f53de 1790 community_free(&merge);
7f323236
DW
1791 } else {
1792 new = community_dup(gshut);
1793 }
1794
3c1f53de 1795 community_free(&gshut);
9a706b42 1796 bgp_attr_set_community(attr, new);
7f323236
DW
1797
1798 /* When we add the graceful-shutdown community we must also
1799 * lower the local-preference */
1800 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1801 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1802}
1803
1804
e73c112e
MK
1805/* Notify BGP Conditional advertisement scanner process. */
1806void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1807{
e73c112e 1808 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1809 afi_t afi = SUBGRP_AFI(subgrp);
1810 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1811 struct bgp_filter *filter = &peer->filter[afi][safi];
1812
1813 if (!ADVERTISE_MAP_NAME(filter))
1814 return;
1815
52979c3b
DS
1816 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1817 return;
e73c112e 1818
52979c3b 1819 peer->advmap_table_change = true;
e73c112e
MK
1820}
1821
1822
f2ee6d5c 1823void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1824{
960035b2 1825 if (family == AF_INET) {
975a328e
DA
1826 attr->nexthop.s_addr = INADDR_ANY;
1827 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1828 }
d62a17ae 1829 if (family == AF_INET6)
1830 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1831 if (family == AF_EVPN)
1832 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1833}
1834
9bcb3eef 1835bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1836 struct update_subgroup *subgrp,
7f7940e6 1837 const struct prefix *p, struct attr *attr,
51c3a7de 1838 struct attr *post_attr)
d62a17ae 1839{
1840 struct bgp_filter *filter;
1841 struct peer *from;
1842 struct peer *peer;
1843 struct peer *onlypeer;
1844 struct bgp *bgp;
40381db7 1845 struct attr *piattr;
b68885f9 1846 route_map_result_t ret;
d62a17ae 1847 int transparent;
1848 int reflect;
1849 afi_t afi;
1850 safi_t safi;
1851 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1852 bool nh_reset = false;
1853 uint64_t cum_bw;
d62a17ae 1854
1855 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1856 return false;
d62a17ae 1857
1858 afi = SUBGRP_AFI(subgrp);
1859 safi = SUBGRP_SAFI(subgrp);
1860 peer = SUBGRP_PEER(subgrp);
1861 onlypeer = NULL;
1862 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1863 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1864
40381db7 1865 from = pi->peer;
d62a17ae 1866 filter = &peer->filter[afi][safi];
1867 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1868 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1869 : pi->attr;
3f9c7369 1870
d0bf49ec
LS
1871 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1872 peer->pmax_out[afi][safi] != 0 &&
1873 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1874 if (BGP_DEBUG(update, UPDATE_OUT) ||
1875 BGP_DEBUG(update, UPDATE_PREFIX)) {
1876 zlog_debug("%s reached maximum prefix to be send (%u)",
1877 peer->host, peer->pmax_out[afi][safi]);
1878 }
1879 return false;
1880 }
1881
49e5a4a0 1882#ifdef ENABLE_BGP_VNC
d62a17ae 1883 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1884 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1885 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1886
1887 /*
1888 * direct and direct_ext type routes originate internally even
1889 * though they can have peer pointers that reference other
1890 * systems
1891 */
8228a9a7
DS
1892 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1893 __func__, p);
d62a17ae 1894 samepeer_safe = 1;
1895 }
65efcfce
LB
1896#endif
1897
ddb5b488
PZ
1898 if (((afi == AFI_IP) || (afi == AFI_IP6))
1899 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1900 && (pi->type == ZEBRA_ROUTE_BGP)
1901 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1902
1903 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1904
1905 samepeer_safe = 1;
1906 }
1907
d62a17ae 1908 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1909 * pi is valid */
1910 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1911 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1912 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1913 return false;
d62a17ae 1914 }
adbac85e 1915
d62a17ae 1916 /* If this is not the bestpath then check to see if there is an enabled
1917 * addpath
1918 * feature that requires us to advertise it */
40381db7 1919 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1920 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1921 return false;
d62a17ae 1922 }
1923 }
06370dac 1924
d62a17ae 1925 /* Aggregate-address suppress check. */
4056a5f6
RZ
1926 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1927 return false;
3f9c7369 1928
13b7e7f0
DS
1929 /*
1930 * If we are doing VRF 2 VRF leaking via the import
1931 * statement, we want to prevent the route going
1932 * off box as that the RT and RD created are localy
1933 * significant and globaly useless.
1934 */
40381db7
DS
1935 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1936 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1937 return false;
13b7e7f0 1938
d62a17ae 1939 /* If it's labeled safi, make sure the route has a valid label. */
1940 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1941 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1942 if (!bgp_is_valid_label(&label)) {
1943 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1944 zlog_debug("u%" PRIu64 ":s%" PRIu64
1945 " %pFX is filtered - no label (%p)",
d62a17ae 1946 subgrp->update_group->id, subgrp->id,
8228a9a7 1947 p, &label);
3dc339cd 1948 return false;
d62a17ae 1949 }
1950 }
cd1964ff 1951
d62a17ae 1952 /* Do not send back route to sender. */
1953 if (onlypeer && from == onlypeer) {
3dc339cd 1954 return false;
d62a17ae 1955 }
3f9c7369 1956
d62a17ae 1957 /* Do not send the default route in the BGP table if the neighbor is
1958 * configured for default-originate */
1959 if (CHECK_FLAG(peer->af_flags[afi][safi],
1960 PEER_FLAG_DEFAULT_ORIGINATE)) {
1961 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1962 return false;
d62a17ae 1963 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1964 return false;
d62a17ae 1965 }
4125bb67 1966
d62a17ae 1967 /* Transparency check. */
1968 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1969 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1970 transparent = 1;
1971 else
1972 transparent = 0;
1973
1974 /* If community is not disabled check the no-export and local. */
40381db7 1975 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1976 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1977 zlog_debug("%s: community filter check fail for %pFX",
1978 __func__, p);
3dc339cd 1979 return false;
d62a17ae 1980 }
3f9c7369 1981
d62a17ae 1982 /* If the attribute has originator-id and it is same as remote
1983 peer's id. */
40381db7
DS
1984 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1985 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1986 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1987 zlog_debug(
8228a9a7
DS
1988 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1989 onlypeer->host, p);
3dc339cd 1990 return false;
d62a17ae 1991 }
3f9c7369 1992
d62a17ae 1993 /* ORF prefix-list filter check */
1994 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1995 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1996 || CHECK_FLAG(peer->af_cap[afi][safi],
1997 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1998 if (peer->orf_plist[afi][safi]) {
1999 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2000 == PREFIX_DENY) {
2001 if (bgp_debug_update(NULL, p,
2002 subgrp->update_group, 0))
2003 zlog_debug(
8228a9a7
DS
2004 "%s [Update:SEND] %pFX is filtered via ORF",
2005 peer->host, p);
3dc339cd 2006 return false;
d62a17ae 2007 }
2008 }
2009
2010 /* Output filter check. */
40381db7 2011 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2012 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2013 zlog_debug("%s [Update:SEND] %pFX is filtered",
2014 peer->host, p);
3dc339cd 2015 return false;
d62a17ae 2016 }
3f9c7369 2017
d62a17ae 2018 /* AS path loop check. */
2b31007c
RZ
2019 if (onlypeer && onlypeer->as_path_loop_detection
2020 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2021 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2022 zlog_debug(
3efd0893 2023 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 2024 onlypeer->host, onlypeer->as);
3dc339cd 2025 return false;
d62a17ae 2026 }
3f9c7369 2027
d62a17ae 2028 /* If we're a CONFED we need to loop check the CONFED ID too */
2029 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2030 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2031 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2032 zlog_debug(
3efd0893 2033 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 2034 peer->host, bgp->confed_id);
3dc339cd 2035 return false;
d62a17ae 2036 }
3f9c7369 2037 }
3f9c7369 2038
d62a17ae 2039 /* Route-Reflect check. */
2040 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2041 reflect = 1;
2042 else
2043 reflect = 0;
2044
2045 /* IBGP reflection check. */
2046 if (reflect && !samepeer_safe) {
2047 /* A route from a Client peer. */
2048 if (CHECK_FLAG(from->af_flags[afi][safi],
2049 PEER_FLAG_REFLECTOR_CLIENT)) {
2050 /* Reflect to all the Non-Client peers and also to the
2051 Client peers other than the originator. Originator
2052 check
2053 is already done. So there is noting to do. */
2054 /* no bgp client-to-client reflection check. */
892fedb6
DA
2055 if (CHECK_FLAG(bgp->flags,
2056 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2057 if (CHECK_FLAG(peer->af_flags[afi][safi],
2058 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2059 return false;
d62a17ae 2060 } else {
2061 /* A route from a Non-client peer. Reflect to all other
2062 clients. */
2063 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2064 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2065 return false;
d62a17ae 2066 }
2067 }
3f9c7369 2068
51c3a7de
DA
2069 /* For modify attribute, copy it to temporary structure.
2070 * post_attr comes from BGP conditional advertisements, where
2071 * attributes are already processed by advertise-map route-map,
2072 * and this needs to be saved instead of overwriting from the
2073 * path attributes.
2074 */
2075 if (post_attr)
2076 *attr = *post_attr;
2077 else
2078 *attr = *piattr;
d62a17ae 2079
2080 /* If local-preference is not set. */
2081 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2082 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2083 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2084 attr->local_pref = bgp->default_local_pref;
3f9c7369 2085 }
3f9c7369 2086
d62a17ae 2087 /* If originator-id is not set and the route is to be reflected,
2088 set the originator id */
2089 if (reflect
2090 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2091 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2092 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2093 }
3f9c7369 2094
d62a17ae 2095 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2096 */
2097 if (peer->sort == BGP_PEER_EBGP
2098 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2099 if (from != bgp->peer_self && !transparent
2100 && !CHECK_FLAG(peer->af_flags[afi][safi],
2101 PEER_FLAG_MED_UNCHANGED))
2102 attr->flag &=
2103 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2104 }
3f9c7369 2105
d62a17ae 2106 /* Since the nexthop attribute can vary per peer, it is not explicitly
2107 * set
2108 * in announce check, only certain flags and length (or number of
2109 * nexthops
2110 * -- for IPv6/MP_REACH) are set here in order to guide the update
2111 * formation
2112 * code in setting the nexthop(s) on a per peer basis in
2113 * reformat_peer().
2114 * Typically, the source nexthop in the attribute is preserved but in
2115 * the
2116 * scenarios where we know it will always be overwritten, we reset the
2117 * nexthop to "0" in an attempt to achieve better Update packing. An
2118 * example of this is when a prefix from each of 2 IBGP peers needs to
2119 * be
2120 * announced to an EBGP peer (and they have the same attributes barring
2121 * their nexthop).
2122 */
2123 if (reflect)
2124 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2125
2126#define NEXTHOP_IS_V6 \
2127 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2128 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2129 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2130 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2131
2132 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2133 * if
2134 * the peer (group) is configured to receive link-local nexthop
2135 * unchanged
c728d027
DA
2136 * and it is available in the prefix OR we're not reflecting the route,
2137 * link-local nexthop address is valid and
d62a17ae 2138 * the peer (group) to whom we're going to announce is on a shared
2139 * network
2140 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2141 * By checking if nexthop LL address is valid we are sure that
2142 * we do not announce LL address as `::`.
d62a17ae 2143 */
2144 if (NEXTHOP_IS_V6) {
2145 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2146 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2147 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2148 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2149 || (!reflect && !transparent
c728d027
DA
2150 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2151 && peer->shared_network
d62a17ae 2152 && (from == bgp->peer_self
2153 || peer->sort == BGP_PEER_EBGP))) {
2154 attr->mp_nexthop_len =
2155 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2156 }
3f9c7369 2157
d62a17ae 2158 /* Clear off link-local nexthop in source, whenever it is not
2159 * needed to
2160 * ensure more prefixes share the same attribute for
2161 * announcement.
2162 */
2163 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2164 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2165 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2166 }
3f9c7369 2167
d62a17ae 2168 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2169 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2170
2171 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2172 if (!post_attr &&
2173 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2174 struct bgp_path_info rmap_path = {0};
2175 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2176 struct attr dummy_attr = {0};
d62a17ae 2177
e34291b8 2178 /* Fill temp path_info */
9bcb3eef
DS
2179 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2180 pi, peer, attr);
16f7ce2b 2181
d62a17ae 2182 /* don't confuse inbound and outbound setting */
2183 RESET_FLAG(attr->rmap_change_flags);
2184
2185 /*
2186 * The route reflector is not allowed to modify the attributes
2187 * of the reflected IBGP routes unless explicitly allowed.
2188 */
2189 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2190 && !CHECK_FLAG(bgp->flags,
2191 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2192 dummy_attr = *attr;
40381db7 2193 rmap_path.attr = &dummy_attr;
d62a17ae 2194 }
3f9c7369 2195
d62a17ae 2196 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2197
4056a5f6 2198 if (bgp_path_suppressed(pi))
d62a17ae 2199 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2200 &rmap_path);
d62a17ae 2201 else
2202 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2203 &rmap_path);
d62a17ae 2204
7e7639f5 2205 bgp_attr_flush(&dummy_attr);
d62a17ae 2206 peer->rmap_type = 0;
2207
2208 if (ret == RMAP_DENYMATCH) {
778048bf 2209 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2210 zlog_debug(
02494580
DA
2211 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2212 peer->host, p,
2213 ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2214 bgp_attr_flush(rmap_path.attr);
3dc339cd 2215 return false;
d62a17ae 2216 }
3f9c7369 2217 }
3f9c7369 2218
9dac9fc8
DA
2219 /* RFC 8212 to prevent route leaks.
2220 * This specification intends to improve this situation by requiring the
2221 * explicit configuration of both BGP Import and Export Policies for any
2222 * External BGP (EBGP) session such as customers, peers, or
2223 * confederation boundaries for all enabled address families. Through
2224 * codification of the aforementioned requirement, operators will
2225 * benefit from consistent behavior across different BGP
2226 * implementations.
2227 */
1d3fdccf 2228 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2229 if (!bgp_outbound_policy_exists(peer, filter)) {
2230 if (monotime_since(&bgp->ebgprequirespolicywarning,
2231 NULL) > FIFTEENMINUTE2USEC ||
2232 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2233 zlog_warn(
2234 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2235 monotime(&bgp->ebgprequirespolicywarning);
2236 }
3dc339cd 2237 return false;
b17826b7 2238 }
9dac9fc8 2239
fb29348a
DA
2240 /* draft-ietf-idr-deprecate-as-set-confed-set
2241 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2242 * Eventually, This document (if approved) updates RFC 4271
2243 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2244 * and obsoletes RFC 6472.
2245 */
7f972cd8 2246 if (peer->bgp->reject_as_sets)
fb29348a 2247 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2248 return false;
fb29348a 2249
33d022bc
DA
2250 /* Codification of AS 0 Processing */
2251 if (aspath_check_as_zero(attr->aspath))
e2369003 2252 return false;
33d022bc 2253
637e5ba4 2254 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2255 if (peer->sort == BGP_PEER_IBGP
2256 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2257 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2258 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2259 } else {
2260 bgp_attr_add_gshut_community(attr);
2261 }
2262 }
2263
1479ed2f
DA
2264 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2265 * Capability" to a neighbor MUST perform the following upon receiving
2266 * a route from that neighbor with the "LLGR_STALE" community, or upon
2267 * attaching the "LLGR_STALE" community itself per Section 4.2:
2268 *
2269 * The route SHOULD NOT be advertised to any neighbor from which the
2270 * Long-lived Graceful Restart Capability has not been received.
2271 */
9a706b42
DA
2272 if (bgp_attr_get_community(attr) &&
2273 community_include(bgp_attr_get_community(attr),
2274 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2275 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2276 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2277 return false;
2278
d62a17ae 2279 /* After route-map has been applied, we check to see if the nexthop to
2280 * be carried in the attribute (that is used for the announcement) can
2281 * be cleared off or not. We do this in all cases where we would be
2282 * setting the nexthop to "ourselves". For IPv6, we only need to
2283 * consider
2284 * the global nexthop here; the link-local nexthop would have been
2285 * cleared
2286 * already, and if not, it is required by the update formation code.
2287 * Also see earlier comments in this function.
2288 */
2289 /*
2290 * If route-map has performed some operation on the nexthop or the peer
2291 * configuration says to pass it unchanged, we cannot reset the nexthop
2292 * here, so only attempt to do it if these aren't true. Note that the
2293 * route-map handler itself might have cleared the nexthop, if for
2294 * example,
2295 * it is configured as 'peer-address'.
2296 */
2297 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2298 piattr->rmap_change_flags)
d62a17ae 2299 && !transparent
2300 && !CHECK_FLAG(peer->af_flags[afi][safi],
2301 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2302 /* We can reset the nexthop, if setting (or forcing) it to
2303 * 'self' */
2304 if (CHECK_FLAG(peer->af_flags[afi][safi],
2305 PEER_FLAG_NEXTHOP_SELF)
2306 || CHECK_FLAG(peer->af_flags[afi][safi],
2307 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2308 if (!reflect
2309 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2310 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2311 subgroup_announce_reset_nhop(
2312 (peer_cap_enhe(peer, afi, safi)
2313 ? AF_INET6
2314 : p->family),
2315 attr);
7b651a32 2316 nh_reset = true;
2317 }
d62a17ae 2318 } else if (peer->sort == BGP_PEER_EBGP) {
2319 /* Can also reset the nexthop if announcing to EBGP, but
2320 * only if
2321 * no peer in the subgroup is on a shared subnet.
2322 * Note: 3rd party nexthop currently implemented for
2323 * IPv4 only.
2324 */
737af885
BS
2325 if ((p->family == AF_INET) &&
2326 (!bgp_subgrp_multiaccess_check_v4(
2327 piattr->nexthop,
7b651a32 2328 subgrp, from))) {
d62a17ae 2329 subgroup_announce_reset_nhop(
2330 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2331 ? AF_INET6
2332 : p->family),
737af885 2333 attr);
7b651a32 2334 nh_reset = true;
2335 }
737af885
BS
2336
2337 if ((p->family == AF_INET6) &&
2338 (!bgp_subgrp_multiaccess_check_v6(
2339 piattr->mp_nexthop_global,
7b651a32 2340 subgrp, from))) {
737af885
BS
2341 subgroup_announce_reset_nhop(
2342 (peer_cap_enhe(peer, afi, safi)
2343 ? AF_INET6
2344 : p->family),
2345 attr);
7b651a32 2346 nh_reset = true;
2347 }
737af885
BS
2348
2349
2350
40381db7 2351 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2352 /*
2353 * This flag is used for leaked vpn-vrf routes
2354 */
2355 int family = p->family;
2356
2357 if (peer_cap_enhe(peer, afi, safi))
2358 family = AF_INET6;
2359
2360 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2361 zlog_debug(
1defdda8 2362 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2363 __func__, family2str(family));
2364 subgroup_announce_reset_nhop(family, attr);
7b651a32 2365 nh_reset = true;
d62a17ae 2366 }
63696f1d 2367 }
960035b2 2368
63696f1d 2369 /* If IPv6/MP and nexthop does not have any override and happens
2370 * to
2371 * be a link-local address, reset it so that we don't pass along
2372 * the
2373 * source's link-local IPv6 address to recipients who may not be
2374 * on
2375 * the same interface.
2376 */
2377 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2378 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2379 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2380 nh_reset = true;
2381 }
d62a17ae 2382 }
3f9c7369 2383
7b651a32 2384 /*
2385 * When the next hop is set to ourselves, if all multipaths have
2386 * link-bandwidth announce the cumulative bandwidth as that makes
2387 * the most sense. However, don't modify if the link-bandwidth has
2388 * been explicitly set by user policy.
2389 */
2390 if (nh_reset &&
f7e1c681 2391 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2392 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2393 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2394 bgp_attr_set_ecommunity(
2395 attr,
2396 ecommunity_replace_linkbw(
2397 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2398 CHECK_FLAG(
2399 peer->flags,
2400 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2401
3dc339cd 2402 return true;
3f9c7369
DS
2403}
2404
cc9f21da 2405static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2406{
2407 struct afi_safi_info *info;
2408 afi_t afi;
2409 safi_t safi;
2410 struct bgp *bgp;
2411
2412 info = THREAD_ARG(thread);
2413 afi = info->afi;
2414 safi = info->safi;
2415 bgp = info->bgp;
2416
2417 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2418 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2419 safi);
f009ff26 2420
2421 bgp->gr_info[afi][safi].t_route_select = NULL;
2422
2423 XFREE(MTYPE_TMP, info);
2424
2425 /* Best path selection */
cc9f21da 2426 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2427}
2428
9bcb3eef 2429void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2430 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2431 struct bgp_path_info_pair *result, afi_t afi,
2432 safi_t safi)
2433{
2434 struct bgp_path_info *new_select;
2435 struct bgp_path_info *old_select;
40381db7
DS
2436 struct bgp_path_info *pi;
2437 struct bgp_path_info *pi1;
2438 struct bgp_path_info *pi2;
2439 struct bgp_path_info *nextpi = NULL;
d62a17ae 2440 int paths_eq, do_mpath, debug;
2441 struct list mp_list;
2442 char pfx_buf[PREFIX2STR_BUFFER];
2443 char path_buf[PATH_ADDPATH_STR_BUFFER];
2444
2445 bgp_mp_list_init(&mp_list);
2446 do_mpath =
2447 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2448
9bcb3eef 2449 debug = bgp_debug_bestpath(dest);
d62a17ae 2450
2451 if (debug)
9bcb3eef 2452 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2453
9bcb3eef 2454 dest->reason = bgp_path_selection_none;
d62a17ae 2455 /* bgp deterministic-med */
2456 new_select = NULL;
892fedb6 2457 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2458
1defdda8 2459 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2460 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2461 pi1 = pi1->next)
9bcb3eef 2462 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2463 BGP_PATH_DMED_SELECTED);
d62a17ae 2464
9bcb3eef 2465 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2466 pi1 = pi1->next) {
40381db7 2467 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2468 continue;
40381db7 2469 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2470 continue;
ea8b2282 2471 if (pi1->peer != bgp->peer_self)
feb17238 2472 if (!peer_established(pi1->peer))
d62a17ae 2473 continue;
2474
40381db7
DS
2475 new_select = pi1;
2476 if (pi1->next) {
2477 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2478 if (CHECK_FLAG(pi2->flags,
1defdda8 2479 BGP_PATH_DMED_CHECK))
d62a17ae 2480 continue;
40381db7 2481 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2482 continue;
ea8b2282 2483 if (pi2->peer != bgp->peer_self
d62a17ae 2484 && !CHECK_FLAG(
ea8b2282
DS
2485 pi2->peer->sflags,
2486 PEER_STATUS_NSF_WAIT))
40381db7 2487 if (pi2->peer->status
d62a17ae 2488 != Established)
2489 continue;
2490
121e245d
DS
2491 if (!aspath_cmp_left(pi1->attr->aspath,
2492 pi2->attr->aspath)
2493 && !aspath_cmp_left_confed(
40381db7 2494 pi1->attr->aspath,
121e245d
DS
2495 pi2->attr->aspath))
2496 continue;
d62a17ae 2497
121e245d
DS
2498 if (bgp_path_info_cmp(
2499 bgp, pi2, new_select,
2500 &paths_eq, mpath_cfg, debug,
fdf81fa0 2501 pfx_buf, afi, safi,
9bcb3eef 2502 &dest->reason)) {
121e245d 2503 bgp_path_info_unset_flag(
9bcb3eef 2504 dest, new_select,
121e245d
DS
2505 BGP_PATH_DMED_SELECTED);
2506 new_select = pi2;
d62a17ae 2507 }
121e245d
DS
2508
2509 bgp_path_info_set_flag(
9bcb3eef 2510 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2511 }
2512 }
9bcb3eef 2513 bgp_path_info_set_flag(dest, new_select,
18ee8310 2514 BGP_PATH_DMED_CHECK);
9bcb3eef 2515 bgp_path_info_set_flag(dest, new_select,
18ee8310 2516 BGP_PATH_DMED_SELECTED);
d62a17ae 2517
2518 if (debug) {
18ee8310 2519 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2520 new_select, path_buf, sizeof(path_buf));
8228a9a7 2521 zlog_debug(
4378495a
DS
2522 "%pBD(%s): %s is the bestpath from AS %u",
2523 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2524 aspath_get_first_as(
2525 new_select->attr->aspath));
d62a17ae 2526 }
2527 }
2528 }
96450faf 2529
d62a17ae 2530 /* Check old selected route and new selected route. */
2531 old_select = NULL;
2532 new_select = NULL;
9bcb3eef 2533 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2534 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2535 enum bgp_path_selection_reason reason;
2536
40381db7
DS
2537 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2538 old_select = pi;
d62a17ae 2539
40381db7 2540 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2541 /* reap REMOVED routes, if needs be
2542 * selected route must stay for a while longer though
2543 */
40381db7
DS
2544 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2545 && (pi != old_select))
9bcb3eef 2546 bgp_path_info_reap(dest, pi);
d62a17ae 2547
ddb5b488 2548 if (debug)
40381db7
DS
2549 zlog_debug("%s: pi %p in holddown", __func__,
2550 pi);
ddb5b488 2551
d62a17ae 2552 continue;
2553 }
96450faf 2554
40381db7
DS
2555 if (pi->peer && pi->peer != bgp->peer_self
2556 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2557 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2558
2559 if (debug)
2560 zlog_debug(
40381db7
DS
2561 "%s: pi %p non self peer %s not estab state",
2562 __func__, pi, pi->peer->host);
ddb5b488 2563
d62a17ae 2564 continue;
ddb5b488 2565 }
9fbdd100 2566
892fedb6 2567 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2568 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2569 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2570 if (debug)
40381db7 2571 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2572 continue;
2573 }
9fbdd100 2574
9bcb3eef 2575 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2576
9bcb3eef 2577 reason = dest->reason;
40381db7 2578 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2579 debug, pfx_buf, afi, safi,
2580 &dest->reason)) {
19ea4cec
DS
2581 if (new_select == NULL &&
2582 reason != bgp_path_selection_none)
9bcb3eef 2583 dest->reason = reason;
40381db7 2584 new_select = pi;
d62a17ae 2585 }
2586 }
718e3744 2587
d62a17ae 2588 /* Now that we know which path is the bestpath see if any of the other
2589 * paths
2590 * qualify as multipaths
2591 */
2592 if (debug) {
2593 if (new_select)
7533cad7
QY
2594 bgp_path_info_path_with_addpath_rx_str(
2595 new_select, path_buf, sizeof(path_buf));
d62a17ae 2596 else
772270f3 2597 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2598 zlog_debug(
4378495a
DS
2599 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2600 dest, bgp->name_pretty, path_buf,
d62a17ae 2601 old_select ? old_select->peer->host : "NONE");
96450faf 2602 }
9fbdd100 2603
d62a17ae 2604 if (do_mpath && new_select) {
9bcb3eef 2605 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2606 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2607
2608 if (debug)
18ee8310 2609 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2610 pi, path_buf, sizeof(path_buf));
d62a17ae 2611
40381db7 2612 if (pi == new_select) {
d62a17ae 2613 if (debug)
2614 zlog_debug(
4378495a
DS
2615 "%pBD(%s): %s is the bestpath, add to the multipath list",
2616 dest, bgp->name_pretty,
2617 path_buf);
40381db7 2618 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2619 continue;
2620 }
2621
40381db7 2622 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2623 continue;
2624
40381db7
DS
2625 if (pi->peer && pi->peer != bgp->peer_self
2626 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2627 PEER_STATUS_NSF_WAIT))
feb17238 2628 if (!peer_established(pi->peer))
d62a17ae 2629 continue;
2630
40381db7 2631 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2632 if (debug)
2633 zlog_debug(
8228a9a7
DS
2634 "%pBD: %s has the same nexthop as the bestpath, skip it",
2635 dest, path_buf);
d62a17ae 2636 continue;
2637 }
2638
40381db7 2639 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2640 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2641 &dest->reason);
d62a17ae 2642
2643 if (paths_eq) {
2644 if (debug)
2645 zlog_debug(
8228a9a7
DS
2646 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2647 dest, path_buf);
40381db7 2648 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2649 }
2650 }
2651 }
fee0f4c6 2652
4378495a 2653 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2654 mpath_cfg);
2655 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2656 bgp_mp_list_clear(&mp_list);
96450faf 2657
9bcb3eef 2658 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2659
d62a17ae 2660 result->old = old_select;
2661 result->new = new_select;
96450faf 2662
d62a17ae 2663 return;
fee0f4c6 2664}
2665
3f9c7369
DS
2666/*
2667 * A new route/change in bestpath of an existing route. Evaluate the path
2668 * for advertisement to the subgroup.
2669 */
3dc339cd
DA
2670void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2671 struct bgp_path_info *selected,
9bcb3eef 2672 struct bgp_dest *dest,
3dc339cd 2673 uint32_t addpath_tx_id)
d62a17ae 2674{
b54892e0 2675 const struct prefix *p;
d62a17ae 2676 struct peer *onlypeer;
2677 struct attr attr;
2678 afi_t afi;
2679 safi_t safi;
a77e2f4b
S
2680 struct bgp *bgp;
2681 bool advertise;
adbac85e 2682
9bcb3eef 2683 p = bgp_dest_get_prefix(dest);
d62a17ae 2684 afi = SUBGRP_AFI(subgrp);
2685 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2686 bgp = SUBGRP_INST(subgrp);
d62a17ae 2687 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2688 : NULL);
2689
2dbe669b
DA
2690 if (BGP_DEBUG(update, UPDATE_OUT))
2691 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2692
d62a17ae 2693 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2694 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2695 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2696 return;
d62a17ae 2697
6006b807 2698 memset(&attr, 0, sizeof(attr));
d62a17ae 2699 /* It's initialized in bgp_announce_check() */
2700
a77e2f4b
S
2701 /* Announcement to the subgroup. If the route is filtered withdraw it.
2702 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2703 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2704 * route
d62a17ae 2705 */
a77e2f4b
S
2706 advertise = bgp_check_advertise(bgp, dest);
2707
d62a17ae 2708 if (selected) {
7f7940e6 2709 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2710 NULL)) {
a77e2f4b
S
2711 /* Route is selected, if the route is already installed
2712 * in FIB, then it is advertised
2713 */
be785e35
DS
2714 if (advertise) {
2715 if (!bgp_check_withdrawal(bgp, dest))
2716 bgp_adj_out_set_subgroup(
2717 dest, subgrp, &attr, selected);
2718 else
2719 bgp_adj_out_unset_subgroup(
2720 dest, subgrp, 1, addpath_tx_id);
2721 }
a77e2f4b 2722 } else
9bcb3eef 2723 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2724 addpath_tx_id);
d62a17ae 2725 }
2726
2727 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2728 else {
9bcb3eef 2729 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2730 }
200df115 2731}
fee0f4c6 2732
3064bf43 2733/*
e1072051 2734 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2735 * This is called at the end of route processing.
3064bf43 2736 */
9bcb3eef 2737void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2738{
40381db7 2739 struct bgp_path_info *pi;
3064bf43 2740
9bcb3eef 2741 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2742 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2743 continue;
40381db7
DS
2744 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2745 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2746 }
3064bf43 2747}
2748
2749/*
2750 * Has the route changed from the RIB's perspective? This is invoked only
2751 * if the route selection returns the same best route as earlier - to
2752 * determine if we need to update zebra or not.
2753 */
9bcb3eef 2754bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2755{
4b7e6066 2756 struct bgp_path_info *mpinfo;
d62a17ae 2757
2bb9eff4
DS
2758 /* If this is multipath, check all selected paths for any nexthop
2759 * change or attribute change. Some attribute changes (e.g., community)
2760 * aren't of relevance to the RIB, but we'll update zebra to ensure
2761 * we handle the case of BGP nexthop change. This is the behavior
2762 * when the best path has an attribute change anyway.
d62a17ae 2763 */
1defdda8 2764 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2765 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2766 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2767 return true;
d62a17ae 2768
2bb9eff4
DS
2769 /*
2770 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2771 */
18ee8310
DS
2772 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2773 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2774 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2775 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2776 return true;
d62a17ae 2777 }
3064bf43 2778
d62a17ae 2779 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2780 return false;
3064bf43 2781}
2782
d62a17ae 2783struct bgp_process_queue {
2784 struct bgp *bgp;
9bcb3eef 2785 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2786#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2787 unsigned int flags;
2788 unsigned int queued;
200df115 2789};
2790
3b0c17e1 2791static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2792 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2793 struct bgp_path_info *new_select,
2794 struct bgp_path_info *old_select)
2795{
9bcb3eef 2796 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2797
2798 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2799 return;
2800
2801 if (advertise_type5_routes(bgp, afi) && new_select
2802 && is_route_injectable_into_evpn(new_select)) {
2803
2804 /* apply the route-map */
2805 if (bgp->adv_cmd_rmap[afi][safi].map) {
2806 route_map_result_t ret;
2807 struct bgp_path_info rmap_path;
2808 struct bgp_path_info_extra rmap_path_extra;
2809 struct attr dummy_attr;
2810
2811 dummy_attr = *new_select->attr;
2812
2813 /* Fill temp path_info */
9bcb3eef 2814 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2815 new_select, new_select->peer,
2816 &dummy_attr);
2817
2818 RESET_FLAG(dummy_attr.rmap_change_flags);
2819
2820 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2821 p, &rmap_path);
3b0c17e1 2822
2823 if (ret == RMAP_DENYMATCH) {
2824 bgp_attr_flush(&dummy_attr);
2825 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2826 safi);
2827 } else
2828 bgp_evpn_advertise_type5_route(
2829 bgp, p, &dummy_attr, afi, safi);
2830 } else {
2831 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2832 afi, safi);
2833 }
2834 } else if (advertise_type5_routes(bgp, afi) && old_select
2835 && is_route_injectable_into_evpn(old_select))
2836 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2837}
2838
bb2ca692
MS
2839/*
2840 * Utility to determine whether a particular path_info should use
2841 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2842 * in a path where we basically _know_ this is a BGP-LU route.
2843 */
2844static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2845{
2846 /* Certain types get imp null; so do paths where the nexthop is
2847 * not labeled.
2848 */
2849 if (new_select->sub_type == BGP_ROUTE_STATIC
2850 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2851 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2852 return true;
2853 else if (new_select->extra == NULL ||
2854 !bgp_is_valid_label(&new_select->extra->label[0]))
2855 /* TODO -- should be configurable? */
2856 return true;
2857 else
2858 return false;
2859}
2860
3103e8d2
DS
2861/*
2862 * old_select = The old best path
2863 * new_select = the new best path
2864 *
2865 * if (!old_select && new_select)
2866 * We are sending new information on.
2867 *
2868 * if (old_select && new_select) {
2869 * if (new_select != old_select)
2870 * We have a new best path send a change
2871 * else
2872 * We've received a update with new attributes that needs
2873 * to be passed on.
2874 * }
2875 *
2876 * if (old_select && !new_select)
2877 * We have no eligible route that we can announce or the rn
2878 * is being removed.
2879 */
9bcb3eef 2880static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2881 afi_t afi, safi_t safi)
d62a17ae 2882{
4b7e6066
DS
2883 struct bgp_path_info *new_select;
2884 struct bgp_path_info *old_select;
2885 struct bgp_path_info_pair old_and_new;
ddb5b488 2886 int debug = 0;
d62a17ae 2887
892fedb6 2888 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2889 if (dest)
2890 debug = bgp_debug_bestpath(dest);
b54892e0 2891 if (debug)
f4c713ae 2892 zlog_debug(
56ca3b5b 2893 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2894 __func__, dest);
f4c713ae
LB
2895 return;
2896 }
d62a17ae 2897 /* Is it end of initial update? (after startup) */
9bcb3eef 2898 if (!dest) {
e36f61b5
DS
2899 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2900 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2901
2902 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2903 FOREACH_AFI_SAFI (afi, safi) {
2904 if (bgp_fibupd_safi(safi))
2905 bgp_zebra_announce_table(bgp, afi, safi);
2906 }
d62a17ae 2907 bgp->main_peers_update_hold = 0;
2908
2909 bgp_start_routeadv(bgp);
aac24838 2910 return;
d62a17ae 2911 }
cb1faec9 2912
9bcb3eef 2913 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2914
9bcb3eef 2915 debug = bgp_debug_bestpath(dest);
b54892e0 2916 if (debug)
4378495a
DS
2917 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2918 dest, bgp->name_pretty, afi2str(afi),
2919 safi2str(safi));
ddb5b488 2920
f009ff26 2921 /* The best path calculation for the route is deferred if
2922 * BGP_NODE_SELECT_DEFER is set
2923 */
9bcb3eef 2924 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2925 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2926 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2927 return;
2928 }
2929
d62a17ae 2930 /* Best path selection. */
9bcb3eef 2931 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2932 afi, safi);
2933 old_select = old_and_new.old;
2934 new_select = old_and_new.new;
2935
2936 /* Do we need to allocate or free labels?
2937 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2938 * necessary to do this upon changes to best path. Exceptions:
2939 * - label index has changed -> recalculate resulting label
2940 * - path_info sub_type changed -> switch to/from implicit-null
2941 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2942 */
318cac96 2943 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2944 if (new_select) {
2945 if (!old_select
2946 || bgp_label_index_differs(new_select, old_select)
57592a53 2947 || new_select->sub_type != old_select->sub_type
9bcb3eef 2948 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2949 /* Enforced penultimate hop popping:
2950 * implicit-null for local routes, aggregate
2951 * and redistributed routes
2952 */
bb2ca692 2953 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 2954 if (CHECK_FLAG(
9bcb3eef 2955 dest->flags,
992dd67e
PR
2956 BGP_NODE_REGISTERED_FOR_LABEL)
2957 || CHECK_FLAG(
2958 dest->flags,
2959 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2960 bgp_unregister_for_label(dest);
67f67ba4
DA
2961 dest->local_label = mpls_lse_encode(
2962 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
2963 1);
9bcb3eef 2964 bgp_set_valid_label(&dest->local_label);
d62a17ae 2965 } else
9bcb3eef
DS
2966 bgp_register_for_label(dest,
2967 new_select);
d62a17ae 2968 }
9bcb3eef 2969 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2970 BGP_NODE_REGISTERED_FOR_LABEL)
2971 || CHECK_FLAG(dest->flags,
2972 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2973 bgp_unregister_for_label(dest);
318cac96 2974 }
992dd67e
PR
2975 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2976 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2977 bgp_unregister_for_label(dest);
d62a17ae 2978 }
cd1964ff 2979
b54892e0 2980 if (debug)
ddb5b488 2981 zlog_debug(
4378495a
DS
2982 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2983 __func__, dest, bgp->name_pretty, afi2str(afi),
2984 safi2str(safi), old_select, new_select);
ddb5b488 2985
d62a17ae 2986 /* If best route remains the same and this is not due to user-initiated
2987 * clear, see exactly what needs to be done.
2988 */
d62a17ae 2989 if (old_select && old_select == new_select
9bcb3eef 2990 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2991 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2992 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2993 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2994#ifdef ENABLE_BGP_VNC
d62a17ae 2995 vnc_import_bgp_add_route(bgp, p, old_select);
2996 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2997#endif
bb744275 2998 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2999 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3000
be785e35
DS
3001 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3002 && new_select->sub_type == BGP_ROUTE_NORMAL)
3003 SET_FLAG(dest->flags,
3004 BGP_NODE_FIB_INSTALL_PENDING);
3005
ddb5b488
PZ
3006 if (new_select->type == ZEBRA_ROUTE_BGP
3007 && (new_select->sub_type == BGP_ROUTE_NORMAL
3008 || new_select->sub_type
3009 == BGP_ROUTE_IMPORTED))
3010
9bcb3eef 3011 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3012 bgp, afi, safi);
3013 }
d62a17ae 3014 }
d62a17ae 3015
3016 /* If there is a change of interest to peers, reannounce the
3017 * route. */
1defdda8 3018 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3019 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3020 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3021 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3022
3023 /* unicast routes must also be annouced to
3024 * labeled-unicast update-groups */
3025 if (safi == SAFI_UNICAST)
3026 group_announce_route(bgp, afi,
9bcb3eef 3027 SAFI_LABELED_UNICAST, dest,
d62a17ae 3028 new_select);
3029
1defdda8 3030 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3031 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3032 }
fee0f4c6 3033
3b0c17e1 3034 /* advertise/withdraw type-5 routes */
3035 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3036 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3037 bgp_process_evpn_route_injection(
9bcb3eef 3038 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3039
b1875e65 3040 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3041 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3042 bgp_zebra_clear_route_change_flags(dest);
3043 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3044 return;
d62a17ae 3045 }
8ad7271d 3046
d62a17ae 3047 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3048 */
9bcb3eef 3049 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3050
3051 /* bestpath has changed; bump version */
3052 if (old_select || new_select) {
9bcb3eef 3053 bgp_bump_version(dest);
d62a17ae 3054
3055 if (!bgp->t_rmap_def_originate_eval) {
3056 bgp_lock(bgp);
3057 thread_add_timer(
3058 bm->master,
3059 update_group_refresh_default_originate_route_map,
3060 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3061 &bgp->t_rmap_def_originate_eval);
3062 }
3063 }
3f9c7369 3064
d62a17ae 3065 if (old_select)
9bcb3eef 3066 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3067 if (new_select) {
ddb5b488
PZ
3068 if (debug)
3069 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3070 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3071 bgp_path_info_unset_flag(dest, new_select,
3072 BGP_PATH_ATTR_CHANGED);
1defdda8 3073 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3074 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3075 }
338b3424 3076
49e5a4a0 3077#ifdef ENABLE_BGP_VNC
d62a17ae 3078 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3079 if (old_select != new_select) {
3080 if (old_select) {
3081 vnc_import_bgp_exterior_del_route(bgp, p,
3082 old_select);
3083 vnc_import_bgp_del_route(bgp, p, old_select);
3084 }
3085 if (new_select) {
3086 vnc_import_bgp_exterior_add_route(bgp, p,
3087 new_select);
3088 vnc_import_bgp_add_route(bgp, p, new_select);
3089 }
3090 }
3091 }
65efcfce
LB
3092#endif
3093
9bcb3eef 3094 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3095
3096 /* unicast routes must also be annouced to labeled-unicast update-groups
3097 */
3098 if (safi == SAFI_UNICAST)
9bcb3eef 3099 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3100 new_select);
3101
3102 /* FIB update. */
3103 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3104 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3105
d62a17ae 3106 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3107 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3108 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3109 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3110
be785e35
DS
3111 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3112 SET_FLAG(dest->flags,
3113 BGP_NODE_FIB_INSTALL_PENDING);
3114
2b659f33
MK
3115 /* if this is an evpn imported type-5 prefix,
3116 * we need to withdraw the route first to clear
3117 * the nh neigh and the RMAC entry.
3118 */
3119 if (old_select &&
3120 is_route_parent_evpn(old_select))
3121 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3122
9bcb3eef 3123 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3124 } else {
d62a17ae 3125 /* Withdraw the route from the kernel. */
3126 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3127 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3128 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3129 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3130
568e10ca 3131 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3132 }
718e3744 3133 }
3064bf43 3134
9bcb3eef 3135 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3136 old_select);
5424b7ba 3137
d62a17ae 3138 /* Clear any route change flags. */
9bcb3eef 3139 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3140
18ee8310 3141 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3142 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3143 bgp_path_info_reap(dest, old_select);
d62a17ae 3144
9bcb3eef 3145 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3146 return;
718e3744 3147}
3148
f009ff26 3149/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3150int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3151{
9bcb3eef 3152 struct bgp_dest *dest;
f009ff26 3153 int cnt = 0;
3154 struct afi_safi_info *thread_info;
f009ff26 3155
56c226e7
DS
3156 if (bgp->gr_info[afi][safi].t_route_select) {
3157 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3158
3159 thread_info = THREAD_ARG(t);
3160 XFREE(MTYPE_TMP, thread_info);
f009ff26 3161 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3162 }
f009ff26 3163
3164 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3165 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3166 get_afi_safi_str(afi, safi, false),
26742171 3167 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3168 }
3169
3170 /* Process the route list */
6338d242 3171 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3172 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3173 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3174 dest = bgp_route_next(dest)) {
3175 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3176 continue;
3177
3178 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3179 bgp->gr_info[afi][safi].gr_deferred--;
3180 bgp_process_main_one(bgp, dest, afi, safi);
3181 cnt++;
067ea165
CB
3182 }
3183 /* If iteration stopped before the entire table was traversed then the
3184 * node needs to be unlocked.
3185 */
3186 if (dest) {
3187 bgp_dest_unlock_node(dest);
3188 dest = NULL;
f009ff26 3189 }
3190
9e3b51a7 3191 /* Send EOR message when all routes are processed */
6338d242 3192 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3193 bgp_send_delayed_eor(bgp);
8c48b3b6 3194 /* Send route processing complete message to RIB */
3195 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3196 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3197 return 0;
9e3b51a7 3198 }
f009ff26 3199
3200 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3201
3202 thread_info->afi = afi;
3203 thread_info->safi = safi;
3204 thread_info->bgp = bgp;
3205
3206 /* If there are more routes to be processed, start the
3207 * selection timer
3208 */
3209 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3210 BGP_ROUTE_SELECT_DELAY,
3211 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3212 return 0;
3213}
3214
aac24838 3215static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3216{
aac24838
JB
3217 struct bgp_process_queue *pqnode = data;
3218 struct bgp *bgp = pqnode->bgp;
d62a17ae 3219 struct bgp_table *table;
9bcb3eef 3220 struct bgp_dest *dest;
aac24838
JB
3221
3222 /* eoiu marker */
3223 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3224 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3225 /* should always have dedicated wq call */
3226 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3227 return WQ_SUCCESS;
3228 }
3229
ac021f40 3230 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3231 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3232 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3233 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3234 table = bgp_dest_table(dest);
3235 /* note, new DESTs may be added as part of processing */
3236 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3237
9bcb3eef 3238 bgp_dest_unlock_node(dest);
d62a17ae 3239 bgp_table_unlock(table);
3240 }
aac24838
JB
3241
3242 return WQ_SUCCESS;
3243}
3244
3245static void bgp_processq_del(struct work_queue *wq, void *data)
3246{
3247 struct bgp_process_queue *pqnode = data;
3248
3249 bgp_unlock(pqnode->bgp);
3250
3251 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3252}
3253
b6c386bb 3254void bgp_process_queue_init(struct bgp *bgp)
200df115 3255{
b6c386bb
DS
3256 if (!bgp->process_queue) {
3257 char name[BUFSIZ];
3258
3259 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3260 bgp->process_queue = work_queue_new(bm->master, name);
3261 }
3262
3263 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3264 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3265 bgp->process_queue->spec.max_retries = 0;
3266 bgp->process_queue->spec.hold = 50;
d62a17ae 3267 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3268 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3269}
3270
cfe8d15a 3271static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3272{
3273 struct bgp_process_queue *pqnode;
3274
a4d82a8a
PZ
3275 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3276 sizeof(struct bgp_process_queue));
aac24838
JB
3277
3278 /* unlocked in bgp_processq_del */
3279 pqnode->bgp = bgp_lock(bgp);
3280 STAILQ_INIT(&pqnode->pqueue);
3281
aac24838
JB
3282 return pqnode;
3283}
3284
9bcb3eef 3285void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3286{
aac24838 3287#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3288 struct work_queue *wq = bgp->process_queue;
d62a17ae 3289 struct bgp_process_queue *pqnode;
cfe8d15a 3290 int pqnode_reuse = 0;
495f0b13 3291
d62a17ae 3292 /* already scheduled for processing? */
9bcb3eef 3293 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3294 return;
2e02b9b2 3295
f009ff26 3296 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3297 * the workqueue
3298 */
9bcb3eef 3299 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3300 if (BGP_DEBUG(update, UPDATE_OUT))
3301 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3302 dest);
f009ff26 3303 return;
3304 }
3305
46aeabed
LS
3306 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3307 if (BGP_DEBUG(update, UPDATE_OUT))
3308 zlog_debug(
3309 "Soft reconfigure table in progress for route %p",
3310 dest);
3311 return;
3312 }
3313
aac24838 3314 if (wq == NULL)
d62a17ae 3315 return;
3316
aac24838 3317 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3318 limit only if is from the same BGP view and it's not an EOIU marker
3319 */
aac24838
JB
3320 if (work_queue_item_count(wq)) {
3321 struct work_queue_item *item = work_queue_last_item(wq);
3322 pqnode = item->data;
228da428 3323
a4d82a8a
PZ
3324 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3325 || pqnode->bgp != bgp
3326 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3327 pqnode = bgp_processq_alloc(bgp);
3328 else
3329 pqnode_reuse = 1;
aac24838 3330 } else
cfe8d15a 3331 pqnode = bgp_processq_alloc(bgp);
aac24838 3332 /* all unlocked in bgp_process_wq */
9bcb3eef 3333 bgp_table_lock(bgp_dest_table(dest));
aac24838 3334
9bcb3eef
DS
3335 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3336 bgp_dest_lock_node(dest);
aac24838 3337
60466a63 3338 /* can't be enqueued twice */
9bcb3eef
DS
3339 assert(STAILQ_NEXT(dest, pq) == NULL);
3340 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3341 pqnode->queued++;
3342
cfe8d15a
LB
3343 if (!pqnode_reuse)
3344 work_queue_add(wq, pqnode);
3345
d62a17ae 3346 return;
fee0f4c6 3347}
0a486e5f 3348
d62a17ae 3349void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3350{
d62a17ae 3351 struct bgp_process_queue *pqnode;
cb1faec9 3352
b6c386bb 3353 if (bgp->process_queue == NULL)
d62a17ae 3354 return;
2e02b9b2 3355
cfe8d15a 3356 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3357
aac24838 3358 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3359 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3360}
3361
cc9f21da 3362static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3363{
d62a17ae 3364 struct peer *peer;
0a486e5f 3365
d62a17ae 3366 peer = THREAD_ARG(thread);
3367 peer->t_pmax_restart = NULL;
0a486e5f 3368
d62a17ae 3369 if (bgp_debug_neighbor_events(peer))
3370 zlog_debug(
3371 "%s Maximum-prefix restart timer expired, restore peering",
3372 peer->host);
0a486e5f 3373
a9bafa95 3374 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3375 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3376}
3377
9cbd06e0
DA
3378static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3379 safi_t safi)
3380{
3381 uint32_t count = 0;
f41b0459 3382 bool filtered = false;
9cbd06e0
DA
3383 struct bgp_dest *dest;
3384 struct bgp_adj_in *ain;
40bb2ccf 3385 struct attr attr = {};
9cbd06e0
DA
3386 struct bgp_table *table = peer->bgp->rib[afi][safi];
3387
3388 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3389 for (ain = dest->adj_in; ain; ain = ain->next) {
3390 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3391
3392 attr = *ain->attr;
9cbd06e0
DA
3393
3394 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3395 == FILTER_DENY)
f41b0459
DA
3396 filtered = true;
3397
3398 if (bgp_input_modifier(
3399 peer, rn_p, &attr, afi, safi,
3400 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3401 NULL, 0, NULL)
3402 == RMAP_DENY)
3403 filtered = true;
3404
3405 if (filtered)
9cbd06e0 3406 count++;
f41b0459 3407
d498917e 3408 bgp_attr_flush(&attr);
9cbd06e0
DA
3409 }
3410 }
3411
3412 return count;
3413}
3414
3dc339cd
DA
3415bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3416 int always)
718e3744 3417{
d62a17ae 3418 iana_afi_t pkt_afi;
5c525538 3419 iana_safi_t pkt_safi;
9cbd06e0
DA
3420 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3421 PEER_FLAG_MAX_PREFIX_FORCE))
3422 ? bgp_filtered_routes_count(peer, afi, safi)
3423 + peer->pcount[afi][safi]
3424 : peer->pcount[afi][safi];
9cabb64b 3425
d62a17ae 3426 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3427 return false;
e0701b79 3428
9cbd06e0 3429 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3430 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3431 PEER_STATUS_PREFIX_LIMIT)
3432 && !always)
3dc339cd 3433 return false;
e0701b79 3434
d62a17ae 3435 zlog_info(
f70c91dc
DA
3436 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3437 get_afi_safi_str(afi, safi, false), peer, pcount,
3438 peer->pmax[afi][safi]);
d62a17ae 3439 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3440
3441 if (CHECK_FLAG(peer->af_flags[afi][safi],
3442 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3443 return false;
d62a17ae 3444
3445 /* Convert AFI, SAFI to values for packet. */
3446 pkt_afi = afi_int2iana(afi);
3447 pkt_safi = safi_int2iana(safi);
3448 {
d7c0a89a 3449 uint8_t ndata[7];
d62a17ae 3450
3451 ndata[0] = (pkt_afi >> 8);
3452 ndata[1] = pkt_afi;
3453 ndata[2] = pkt_safi;
3454 ndata[3] = (peer->pmax[afi][safi] >> 24);
3455 ndata[4] = (peer->pmax[afi][safi] >> 16);
3456 ndata[5] = (peer->pmax[afi][safi] >> 8);
3457 ndata[6] = (peer->pmax[afi][safi]);
3458
3459 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3460 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3461 BGP_NOTIFY_CEASE_MAX_PREFIX,
3462 ndata, 7);
3463 }
3464
3465 /* Dynamic peers will just close their connection. */
3466 if (peer_dynamic_neighbor(peer))
3dc339cd 3467 return true;
d62a17ae 3468
3469 /* restart timer start */
3470 if (peer->pmax_restart[afi][safi]) {
3471 peer->v_pmax_restart =
3472 peer->pmax_restart[afi][safi] * 60;
3473
3474 if (bgp_debug_neighbor_events(peer))
3475 zlog_debug(
f70c91dc
DA
3476 "%pBP Maximum-prefix restart timer started for %d secs",
3477 peer, peer->v_pmax_restart);
d62a17ae 3478
3479 BGP_TIMER_ON(peer->t_pmax_restart,
3480 bgp_maximum_prefix_restart_timer,
3481 peer->v_pmax_restart);
3482 }
3483
3dc339cd 3484 return true;
d62a17ae 3485 } else
3486 UNSET_FLAG(peer->af_sflags[afi][safi],
3487 PEER_STATUS_PREFIX_LIMIT);
3488
b1823b69
DS
3489 if (pcount
3490 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3491 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3492 PEER_STATUS_PREFIX_THRESHOLD)
3493 && !always)
3dc339cd 3494 return false;
d62a17ae 3495
3496 zlog_info(
f70c91dc
DA
3497 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3498 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3499 peer->pmax[afi][safi]);
d62a17ae 3500 SET_FLAG(peer->af_sflags[afi][safi],
3501 PEER_STATUS_PREFIX_THRESHOLD);
3502 } else
3503 UNSET_FLAG(peer->af_sflags[afi][safi],
3504 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3505 return false;
718e3744 3506}
3507
b40d939b 3508/* Unconditionally remove the route from the RIB, without taking
3509 * damping into consideration (eg, because the session went down)
3510 */
9bcb3eef 3511void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3512 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3513{
f009ff26 3514
3515 struct bgp *bgp = NULL;
3516 bool delete_route = false;
3517
9bcb3eef
DS
3518 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3519 safi);
d62a17ae 3520
f009ff26 3521 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3522 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3523
f009ff26 3524 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3525 * flag
3526 */
3527 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3528 delete_route = true;
9bcb3eef 3529 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3530 delete_route = true;
f009ff26 3531 if (delete_route) {
9bcb3eef
DS
3532 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3533 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3534 bgp = pi->peer->bgp;
26742171 3535 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3536 }
3537 }
3538 }
4a11bf2c 3539
9bcb3eef
DS
3540 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3541 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3542}
3543
9bcb3eef 3544static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3545 struct peer *peer, afi_t afi, safi_t safi,
3546 struct prefix_rd *prd)
3547{
9bcb3eef 3548 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3549
d62a17ae 3550 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3551 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3552 */
b4f7f45b
IR
3553 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3554 && peer->sort == BGP_PEER_EBGP)
3555 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3556 == BGP_DAMP_SUPPRESSED) {
3557 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3558 safi);
3559 return;
d62a17ae 3560 }
3561
49e5a4a0 3562#ifdef ENABLE_BGP_VNC
d62a17ae 3563 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3564 struct bgp_dest *pdest = NULL;
d62a17ae 3565 struct bgp_table *table = NULL;
3566
9bcb3eef
DS
3567 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3568 (struct prefix *)prd);
3569 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3570 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3571
3572 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3573 peer->bgp, prd, table, p, pi);
d62a17ae 3574 }
9bcb3eef 3575 bgp_dest_unlock_node(pdest);
d62a17ae 3576 }
3577 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3578 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3579
b54892e0
DS
3580 vnc_import_bgp_del_route(peer->bgp, p, pi);
3581 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3582 }
65efcfce 3583 }
d62a17ae 3584#endif
128ea8ab 3585
d62a17ae 3586 /* If this is an EVPN route, process for un-import. */
3587 if (safi == SAFI_EVPN)
b54892e0 3588 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3589
9bcb3eef 3590 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3591}
3592
4b7e6066
DS
3593struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3594 struct peer *peer, struct attr *attr,
9bcb3eef 3595 struct bgp_dest *dest)
fb018d25 3596{
4b7e6066 3597 struct bgp_path_info *new;
fb018d25 3598
d62a17ae 3599 /* Make new BGP info. */
4b7e6066 3600 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3601 new->type = type;
3602 new->instance = instance;
3603 new->sub_type = sub_type;
3604 new->peer = peer;
3605 new->attr = attr;
3606 new->uptime = bgp_clock();
9bcb3eef 3607 new->net = dest;
d62a17ae 3608 return new;
fb018d25
DS
3609}
3610
c265ee22 3611/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3612bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3613 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3614 struct bgp_dest *dest)
d62a17ae 3615{
2dbe3fa9 3616 bool ret = false;
b099a5c8
DA
3617 bool is_bgp_static_route =
3618 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3619 : false;
d62a17ae 3620
e8442016
DS
3621 /*
3622 * Only validated for unicast and multicast currently.
3623 * Also valid for EVPN where the nexthop is an IP address.
3624 * If we are a bgp static route being checked then there is
3625 * no need to check to see if the nexthop is martian as
3626 * that it should be ok.
3627 */
3628 if (is_bgp_static_route ||
3629 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3630 return false;
d62a17ae 3631
3632 /* If NEXT_HOP is present, validate it. */
3633 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3634 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3635 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3636 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3637 return true;
d62a17ae 3638 }
c265ee22 3639
d62a17ae 3640 /* If MP_NEXTHOP is present, validate it. */
3641 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3642 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3643 * it is not an IPv6 link-local address.
0355b41d
DA
3644 *
3645 * If we receive an UPDATE with nexthop length set to 32 bytes
3646 * we shouldn't discard an UPDATE if it's set to (::).
3647 * The link-local (2st) is validated along the code path later.
d62a17ae 3648 */
3649 if (attr->mp_nexthop_len) {
3650 switch (attr->mp_nexthop_len) {
3651 case BGP_ATTR_NHLEN_IPV4:
3652 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3653 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3654 || IPV4_CLASS_DE(
3655 ntohl(attr->mp_nexthop_global_in.s_addr))
3656 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3657 dest));
d62a17ae 3658 break;
3659
3660 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3661 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3662 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3663 &attr->mp_nexthop_global)
d62a17ae 3664 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3665 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3666 &attr->mp_nexthop_global)
3667 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3668 dest));
d62a17ae 3669 break;
0355b41d
DA
3670 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3671 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3672 || IN6_IS_ADDR_MULTICAST(
3673 &attr->mp_nexthop_global)
3674 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3675 dest));
0355b41d 3676 break;
d62a17ae 3677
3678 default:
3dc339cd 3679 ret = true;
d62a17ae 3680 break;
3681 }
3682 }
c265ee22 3683
d62a17ae 3684 return ret;
3685}
3686
aade37d7 3687static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3688{
3689 struct community *old;
3690 struct community *new;
3691 struct community *merge;
aade37d7 3692 struct community *no_export;
2721dd61 3693
9a706b42 3694 old = bgp_attr_get_community(attr);
aade37d7 3695 no_export = community_str2com("no-export");
2721dd61 3696
b4efa101
DA
3697 assert(no_export);
3698
2721dd61 3699 if (old) {
aade37d7 3700 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3701
3702 if (!old->refcnt)
3703 community_free(&old);
3704
3705 new = community_uniq_sort(merge);
3706 community_free(&merge);
3707 } else {
aade37d7 3708 new = community_dup(no_export);
2721dd61
DA
3709 }
3710
aade37d7 3711 community_free(&no_export);
2721dd61 3712
9a706b42 3713 bgp_attr_set_community(attr, new);
2721dd61
DA
3714}
3715
5a1ae2c2 3716int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3717 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3718 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3719 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3720 struct bgp_route_evpn *evpn)
d62a17ae 3721{
3722 int ret;
3723 int aspath_loop_count = 0;
9bcb3eef 3724 struct bgp_dest *dest;
d62a17ae 3725 struct bgp *bgp;
3726 struct attr new_attr;
3727 struct attr *attr_new;
40381db7 3728 struct bgp_path_info *pi;
4b7e6066
DS
3729 struct bgp_path_info *new;
3730 struct bgp_path_info_extra *extra;
d62a17ae 3731 const char *reason;
3732 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3733 int connected = 0;
3734 int do_loop_check = 1;
3735 int has_valid_label = 0;
7c312383 3736 afi_t nh_afi;
949b0f24 3737 uint8_t pi_type = 0;
3738 uint8_t pi_sub_type = 0;
9146341f 3739 bool force_evpn_import = false;
907707db 3740 safi_t orig_safi = safi;
949b0f24 3741
c7bb4f00 3742 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3743 char pfxprint[PREFIX2STR_BUFFER];
3744
3745 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3746 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3747 afi, safi, attr);
6401252f
QY
3748 }
3749
49e5a4a0 3750#ifdef ENABLE_BGP_VNC
d62a17ae 3751 int vnc_implicit_withdraw = 0;
65efcfce 3752#endif
d62a17ae 3753 int same_attr = 0;
718e3744 3754
907707db
MS
3755 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3756 if (orig_safi == SAFI_LABELED_UNICAST)
3757 safi = SAFI_UNICAST;
3758
6006b807 3759 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3760 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3761 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3762
d62a17ae 3763 bgp = peer->bgp;
9bcb3eef 3764 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3765 /* TODO: Check to see if we can get rid of "is_valid_label" */
3766 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3767 has_valid_label = (num_labels > 0) ? 1 : 0;
3768 else
3769 has_valid_label = bgp_is_valid_label(label);
718e3744 3770
28f66de2
MS
3771 if (has_valid_label)
3772 assert(label != NULL);
3773
66ff6089
AD
3774 /* Update overlay index of the attribute */
3775 if (afi == AFI_L2VPN && evpn)
3776 memcpy(&attr->evpn_overlay, evpn,
3777 sizeof(struct bgp_route_evpn));
3778
d62a17ae 3779 /* When peer's soft reconfiguration enabled. Record input packet in
3780 Adj-RIBs-In. */
3781 if (!soft_reconfig
3782 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3783 && peer != bgp->peer_self)
9bcb3eef 3784 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3785
3786 /* Check previously received route. */
9bcb3eef 3787 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3788 if (pi->peer == peer && pi->type == type
3789 && pi->sub_type == sub_type
3790 && pi->addpath_rx_id == addpath_id)
d62a17ae 3791 break;
3792
3793 /* AS path local-as loop check. */
3794 if (peer->change_local_as) {
c4368918
DW
3795 if (peer->allowas_in[afi][safi])
3796 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3797 else if (!CHECK_FLAG(peer->flags,
3798 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3799 aspath_loop_count = 1;
3800
3801 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3802 > aspath_loop_count) {
b4d46cc9 3803 peer->stat_pfx_aspath_loop++;
692174a1 3804 reason = "as-path contains our own AS;";
d62a17ae 3805 goto filtered;
3806 }
718e3744 3807 }
718e3744 3808
d62a17ae 3809 /* If the peer is configured for "allowas-in origin" and the last ASN in
3810 * the
3811 * as-path is our ASN then we do not need to call aspath_loop_check
3812 */
3813 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3814 if (aspath_get_last_as(attr->aspath) == bgp->as)
3815 do_loop_check = 0;
3816
3817 /* AS path loop check. */
3818 if (do_loop_check) {
3819 if (aspath_loop_check(attr->aspath, bgp->as)
3820 > peer->allowas_in[afi][safi]
3821 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3822 && aspath_loop_check(attr->aspath, bgp->confed_id)
3823 > peer->allowas_in[afi][safi])) {
b4d46cc9 3824 peer->stat_pfx_aspath_loop++;
d62a17ae 3825 reason = "as-path contains our own AS;";
3826 goto filtered;
3827 }
3828 }
aac9ef6c 3829
d62a17ae 3830 /* Route reflector originator ID check. */
3831 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3832 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3833 peer->stat_pfx_originator_loop++;
d62a17ae 3834 reason = "originator is us;";
3835 goto filtered;
3836 }
718e3744 3837
d62a17ae 3838 /* Route reflector cluster ID check. */
3839 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3840 peer->stat_pfx_cluster_loop++;
d62a17ae 3841 reason = "reflected from the same cluster;";
3842 goto filtered;
3843 }
718e3744 3844
d62a17ae 3845 /* Apply incoming filter. */
907707db 3846 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3847 peer->stat_pfx_filter++;
d62a17ae 3848 reason = "filter;";
3849 goto filtered;
3850 }
718e3744 3851
a8b72dc6
DA
3852 /* RFC 8212 to prevent route leaks.
3853 * This specification intends to improve this situation by requiring the
3854 * explicit configuration of both BGP Import and Export Policies for any
3855 * External BGP (EBGP) session such as customers, peers, or
3856 * confederation boundaries for all enabled address families. Through
3857 * codification of the aforementioned requirement, operators will
3858 * benefit from consistent behavior across different BGP
3859 * implementations.
3860 */
1d3fdccf 3861 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3862 if (!bgp_inbound_policy_exists(peer,
3863 &peer->filter[afi][safi])) {
3864 reason = "inbound policy missing";
b17826b7
DS
3865 if (monotime_since(&bgp->ebgprequirespolicywarning,
3866 NULL) > FIFTEENMINUTE2USEC ||
3867 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3868 zlog_warn(
3869 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3870 monotime(&bgp->ebgprequirespolicywarning);
3871 }
a8b72dc6
DA
3872 goto filtered;
3873 }
3874
fb29348a
DA
3875 /* draft-ietf-idr-deprecate-as-set-confed-set
3876 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3877 * Eventually, This document (if approved) updates RFC 4271
3878 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3879 * and obsoletes RFC 6472.
3880 */
7f972cd8 3881 if (peer->bgp->reject_as_sets)
fb29348a
DA
3882 if (aspath_check_as_sets(attr->aspath)) {
3883 reason =
3884 "as-path contains AS_SET or AS_CONFED_SET type;";
3885 goto filtered;
3886 }
3887
6f4f49b2 3888 new_attr = *attr;
d62a17ae 3889
3890 /* Apply incoming route-map.
3891 * NB: new_attr may now contain newly allocated values from route-map
3892 * "set"
3893 * commands, so we need bgp_attr_flush in the error paths, until we
3894 * intern
3895 * the attr (which takes over the memory references) */
907707db 3896 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3897 num_labels, dest)
3898 == RMAP_DENY) {
b4d46cc9 3899 peer->stat_pfx_filter++;
d62a17ae 3900 reason = "route-map;";
3901 bgp_attr_flush(&new_attr);
3902 goto filtered;
3903 }
718e3744 3904
05864da7 3905 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3906 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3907 /* remove from RIB previous entry */
3908 bgp_zebra_withdraw(p, pi, bgp, safi);
3909 }
3910
7f323236
DW
3911 if (peer->sort == BGP_PEER_EBGP) {
3912
2721dd61
DA
3913 /* rfc7999:
3914 * A BGP speaker receiving an announcement tagged with the
3915 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3916 * NO_EXPORT community as defined in RFC1997, or a
3917 * similar community, to prevent propagation of the
3918 * prefix outside the local AS. The community to prevent
3919 * propagation SHOULD be chosen according to the operator's
3920 * routing policy.
3921 */
9a706b42
DA
3922 if (bgp_attr_get_community(&new_attr) &&
3923 community_include(bgp_attr_get_community(&new_attr),
3924 COMMUNITY_BLACKHOLE))
aade37d7 3925 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3926
a4d82a8a
PZ
3927 /* If we receive the graceful-shutdown community from an eBGP
3928 * peer we must lower local-preference */
9a706b42
DA
3929 if (bgp_attr_get_community(&new_attr) &&
3930 community_include(bgp_attr_get_community(&new_attr),
3931 COMMUNITY_GSHUT)) {
7f323236
DW
3932 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3933 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3934
a4d82a8a
PZ
3935 /* If graceful-shutdown is configured then add the GSHUT
3936 * community to all paths received from eBGP peers */
637e5ba4 3937 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3938 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3939 }
3940
949b0f24 3941 if (pi) {
3942 pi_type = pi->type;
3943 pi_sub_type = pi->sub_type;
3944 }
3945
d62a17ae 3946 /* next hop check. */
a4d82a8a 3947 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3948 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3949 &new_attr, dest)) {
b4d46cc9 3950 peer->stat_pfx_nh_invalid++;
d62a17ae 3951 reason = "martian or self next-hop;";
3952 bgp_attr_flush(&new_attr);
3953 goto filtered;
3954 }
718e3744 3955
5c14a191 3956 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3957 peer->stat_pfx_nh_invalid++;
4e802e66 3958 reason = "self mac;";
4dbf2038 3959 bgp_attr_flush(&new_attr);
4e802e66
DS
3960 goto filtered;
3961 }
3962
a1b773e2
DS
3963 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3964 * condition :
3965 * Suppress fib is enabled
3966 * BGP_OPT_NO_FIB is not enabled
3967 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3968 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3969 */
3970 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3971 && (sub_type == BGP_ROUTE_NORMAL)
3972 && (!bgp_option_check(BGP_OPT_NO_FIB))
3973 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3974 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3975
9cbd06e0
DA
3976 /* If maximum prefix count is configured and current prefix
3977 * count exeed it.
3978 */
4dbf2038
IR
3979 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
3980 bgp_attr_flush(&new_attr);
9cbd06e0 3981 return -1;
4dbf2038
IR
3982 }
3983
3984 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 3985
d62a17ae 3986 /* If the update is implicit withdraw. */
40381db7
DS
3987 if (pi) {
3988 pi->uptime = bgp_clock();
3989 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3990
9bcb3eef 3991 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3992
d62a17ae 3993 /* Same attribute comes in. */
40381db7 3994 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3995 && same_attr
d62a17ae 3996 && (!has_valid_label
40381db7 3997 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3998 num_labels * sizeof(mpls_label_t))
66ff6089 3999 == 0)) {
b4f7f45b
IR
4000 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4001 BGP_CONFIG_DAMPENING)
d62a17ae 4002 && peer->sort == BGP_PEER_EBGP
40381db7 4003 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4004 if (bgp_debug_update(peer, p, NULL, 1)) {
4005 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4006 afi, safi, prd, p, label,
4007 num_labels, addpath_id ? 1 : 0,
66ff6089 4008 addpath_id, evpn, pfx_buf,
a4d82a8a 4009 sizeof(pfx_buf));
f70c91dc 4010 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4011 pfx_buf);
4012 }
4013
9bcb3eef 4014 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4015 != BGP_DAMP_SUPPRESSED) {
40381db7 4016 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4017 safi);
9bcb3eef 4018 bgp_process(bgp, dest, afi, safi);
d62a17ae 4019 }
4020 } else /* Duplicate - odd */
4021 {
4022 if (bgp_debug_update(peer, p, NULL, 1)) {
4023 if (!peer->rcvd_attr_printed) {
4024 zlog_debug(
f70c91dc
DA
4025 "%pBP rcvd UPDATE w/ attr: %s",
4026 peer,
d62a17ae 4027 peer->rcvd_attr_str);
4028 peer->rcvd_attr_printed = 1;
4029 }
4030
4031 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4032 afi, safi, prd, p, label,
4033 num_labels, addpath_id ? 1 : 0,
66ff6089 4034 addpath_id, evpn, pfx_buf,
a4d82a8a 4035 sizeof(pfx_buf));
d62a17ae 4036 zlog_debug(
f70c91dc
DA
4037 "%pBP rcvd %s...duplicate ignored",
4038 peer, pfx_buf);
d62a17ae 4039 }
4040
4041 /* graceful restart STALE flag unset. */
40381db7 4042 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4043 bgp_path_info_unset_flag(
9bcb3eef
DS
4044 dest, pi, BGP_PATH_STALE);
4045 bgp_dest_set_defer_flag(dest, false);
4046 bgp_process(bgp, dest, afi, safi);
d62a17ae 4047 }
4048 }
4049
9bcb3eef 4050 bgp_dest_unlock_node(dest);
d62a17ae 4051 bgp_attr_unintern(&attr_new);
4052
4053 return 0;
4054 }
718e3744 4055
d62a17ae 4056 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4057 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4058 if (bgp_debug_update(peer, p, NULL, 1)) {
4059 bgp_debug_rdpfxpath2str(
a4d82a8a 4060 afi, safi, prd, p, label, num_labels,
66ff6089 4061 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4062 pfx_buf, sizeof(pfx_buf));
d62a17ae 4063 zlog_debug(
f70c91dc
DA
4064 "%pBP rcvd %s, flapped quicker than processing",
4065 peer, pfx_buf);
d62a17ae 4066 }
4067
9bcb3eef 4068 bgp_path_info_restore(dest, pi);
9146341f 4069
4070 /*
4071 * If the BGP_PATH_REMOVED flag is set, then EVPN
4072 * routes would have been unimported already when a
4073 * prior BGP withdraw processing happened. Such routes
4074 * need to be imported again, so flag accordingly.
4075 */
4076 force_evpn_import = true;
d62a17ae 4077 }
718e3744 4078
d62a17ae 4079 /* Received Logging. */
4080 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4081 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4082 num_labels, addpath_id ? 1 : 0,
66ff6089 4083 addpath_id, evpn, pfx_buf,
a4d82a8a 4084 sizeof(pfx_buf));
f70c91dc 4085 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4086 }
718e3744 4087
d62a17ae 4088 /* graceful restart STALE flag unset. */
f009ff26 4089 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4090 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4091 bgp_dest_set_defer_flag(dest, false);
f009ff26 4092 }
d62a17ae 4093
4094 /* The attribute is changed. */
9bcb3eef 4095 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4096
4097 /* implicit withdraw, decrement aggregate and pcount here.
4098 * only if update is accepted, they'll increment below.
4099 */
40381db7 4100 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4101
4102 /* Update bgp route dampening information. */
b4f7f45b 4103 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4104 && peer->sort == BGP_PEER_EBGP) {
4105 /* This is implicit withdraw so we should update
b4f7f45b
IR
4106 dampening
4107 information. */
40381db7 4108 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4109 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4110 }
49e5a4a0 4111#ifdef ENABLE_BGP_VNC
d62a17ae 4112 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4113 struct bgp_dest *pdest = NULL;
d62a17ae 4114 struct bgp_table *table = NULL;
4115
9bcb3eef
DS
4116 pdest = bgp_node_get(bgp->rib[afi][safi],
4117 (struct prefix *)prd);
4118 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4119 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4120
4121 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4122 bgp, prd, table, p, pi);
d62a17ae 4123 }
9bcb3eef 4124 bgp_dest_unlock_node(pdest);
d62a17ae 4125 }
4126 if ((afi == AFI_IP || afi == AFI_IP6)
4127 && (safi == SAFI_UNICAST)) {
40381db7 4128 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4129 /*
4130 * Implicit withdraw case.
4131 */
4132 ++vnc_implicit_withdraw;
40381db7
DS
4133 vnc_import_bgp_del_route(bgp, p, pi);
4134 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4135 }
4136 }
65efcfce 4137#endif
128ea8ab 4138
d62a17ae 4139 /* Special handling for EVPN update of an existing route. If the
4140 * extended community attribute has changed, we need to
4141 * un-import
4142 * the route using its existing extended community. It will be
4143 * subsequently processed for import with the new extended
4144 * community.
4145 */
6f8c9c11
PR
4146 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4147 && !same_attr) {
40381db7 4148 if ((pi->attr->flag
d62a17ae 4149 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4150 && (attr_new->flag
4151 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4152 int cmp;
4153
b53e67a3
DA
4154 cmp = ecommunity_cmp(
4155 bgp_attr_get_ecommunity(pi->attr),
4156 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4157 if (!cmp) {
4158 if (bgp_debug_update(peer, p, NULL, 1))
4159 zlog_debug(
4160 "Change in EXT-COMM, existing %s new %s",
4161 ecommunity_str(
b53e67a3
DA
4162 bgp_attr_get_ecommunity(
4163 pi->attr)),
d62a17ae 4164 ecommunity_str(
b53e67a3
DA
4165 bgp_attr_get_ecommunity(
4166 attr_new)));
6f8c9c11
PR
4167 if (safi == SAFI_EVPN)
4168 bgp_evpn_unimport_route(
4169 bgp, afi, safi, p, pi);
4170 else /* SAFI_MPLS_VPN */
4171 vpn_leak_to_vrf_withdraw(bgp,
4172 pi);
d62a17ae 4173 }
4174 }
4175 }
718e3744 4176
d62a17ae 4177 /* Update to new attribute. */
40381db7
DS
4178 bgp_attr_unintern(&pi->attr);
4179 pi->attr = attr_new;
d62a17ae 4180
4181 /* Update MPLS label */
4182 if (has_valid_label) {
40381db7 4183 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4184 if (extra->label != label) {
4185 memcpy(&extra->label, label,
dbd587da 4186 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4187 extra->num_labels = num_labels;
4188 }
b57ba6d2
MK
4189 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4190 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4191 }
718e3744 4192
e496b420
HS
4193 /* Update SRv6 SID */
4194 if (attr->srv6_l3vpn) {
4195 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4196 if (sid_diff(&extra->sid[0].sid,
4197 &attr->srv6_l3vpn->sid)) {
4198 sid_copy(&extra->sid[0].sid,
e496b420
HS
4199 &attr->srv6_l3vpn->sid);
4200 extra->num_sids = 1;
cc8f05df 4201
16f3db2d
RS
4202 extra->sid[0].loc_block_len = 0;
4203 extra->sid[0].loc_node_len = 0;
4204 extra->sid[0].func_len = 0;
4205 extra->sid[0].arg_len = 0;
ea7cd161
RS
4206 extra->sid[0].transposition_len = 0;
4207 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4208
4209 if (attr->srv6_l3vpn->loc_block_len != 0) {
4210 extra->sid[0].loc_block_len =
4211 attr->srv6_l3vpn->loc_block_len;
4212 extra->sid[0].loc_node_len =
4213 attr->srv6_l3vpn->loc_node_len;
4214 extra->sid[0].func_len =
4215 attr->srv6_l3vpn->func_len;
4216 extra->sid[0].arg_len =
4217 attr->srv6_l3vpn->arg_len;
ea7cd161 4218 extra->sid[0].transposition_len =
cc8f05df 4219 attr->srv6_l3vpn
ea7cd161
RS
4220 ->transposition_len;
4221 extra->sid[0].transposition_offset =
cc8f05df 4222 attr->srv6_l3vpn
ea7cd161
RS
4223 ->transposition_offset;
4224 }
e496b420
HS
4225 }
4226 } else if (attr->srv6_vpn) {
4227 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4228 if (sid_diff(&extra->sid[0].sid,
4229 &attr->srv6_vpn->sid)) {
4230 sid_copy(&extra->sid[0].sid,
4231 &attr->srv6_vpn->sid);
e496b420
HS
4232 extra->num_sids = 1;
4233 }
4234 }
4235
49e5a4a0 4236#ifdef ENABLE_BGP_VNC
d62a17ae 4237 if ((afi == AFI_IP || afi == AFI_IP6)
4238 && (safi == SAFI_UNICAST)) {
4239 if (vnc_implicit_withdraw) {
4240 /*
4241 * Add back the route with its new attributes
4242 * (e.g., nexthop).
4243 * The route is still selected, until the route
4244 * selection
4245 * queued by bgp_process actually runs. We have
4246 * to make this
4247 * update to the VNC side immediately to avoid
4248 * racing against
4249 * configuration changes (e.g., route-map
4250 * changes) which
4251 * trigger re-importation of the entire RIB.
4252 */
40381db7
DS
4253 vnc_import_bgp_add_route(bgp, p, pi);
4254 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4255 }
4256 }
65efcfce
LB
4257#endif
4258
d62a17ae 4259 /* Update bgp route dampening information. */
b4f7f45b 4260 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4261 && peer->sort == BGP_PEER_EBGP) {
4262 /* Now we do normal update dampening. */
9bcb3eef 4263 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4264 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4265 bgp_dest_unlock_node(dest);
d62a17ae 4266 return 0;
4267 }
4268 }
128ea8ab 4269
d62a17ae 4270 /* Nexthop reachability check - for unicast and
4271 * labeled-unicast.. */
7c312383
AD
4272 if (((afi == AFI_IP || afi == AFI_IP6)
4273 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4274 || (safi == SAFI_EVPN &&
4275 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4276 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4277 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4278 && !CHECK_FLAG(peer->flags,
4279 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4280 && !CHECK_FLAG(bgp->flags,
4281 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4282 connected = 1;
4283 else
4284 connected = 0;
4285
960035b2
PZ
4286 struct bgp *bgp_nexthop = bgp;
4287
40381db7
DS
4288 if (pi->extra && pi->extra->bgp_orig)
4289 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4290
7c312383
AD
4291 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4292
4293 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4294 safi, pi, NULL, connected,
4295 p)
a4d82a8a 4296 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4297 bgp_path_info_set_flag(dest, pi,
4298 BGP_PATH_VALID);
d62a17ae 4299 else {
4300 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4301 zlog_debug("%s(%pI4): NH unresolved",
4302 __func__,
4303 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4304 }
9bcb3eef 4305 bgp_path_info_unset_flag(dest, pi,
18ee8310 4306 BGP_PATH_VALID);
d62a17ae 4307 }
4308 } else
9bcb3eef 4309 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4310
49e5a4a0 4311#ifdef ENABLE_BGP_VNC
d62a17ae 4312 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4313 struct bgp_dest *pdest = NULL;
d62a17ae 4314 struct bgp_table *table = NULL;
4315
9bcb3eef
DS
4316 pdest = bgp_node_get(bgp->rib[afi][safi],
4317 (struct prefix *)prd);
4318 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4319 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4320
4321 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4322 bgp, prd, table, p, pi);
d62a17ae 4323 }
9bcb3eef 4324 bgp_dest_unlock_node(pdest);
d62a17ae 4325 }
4326#endif
718e3744 4327
d62a17ae 4328 /* If this is an EVPN route and some attribute has changed,
9146341f 4329 * or we are explicitly told to perform a route import, process
d62a17ae 4330 * route for import. If the extended community has changed, we
4331 * would
4332 * have done the un-import earlier and the import would result
4333 * in the
4334 * route getting injected into appropriate L2 VNIs. If it is
4335 * just
4336 * some other attribute change, the import will result in
4337 * updating
4338 * the attributes for the route in the VNI(s).
4339 */
9146341f 4340 if (safi == SAFI_EVPN &&
4341 (!same_attr || force_evpn_import) &&
7c312383 4342 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4343 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4344
4345 /* Process change. */
40381db7 4346 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4347
9bcb3eef
DS
4348 bgp_process(bgp, dest, afi, safi);
4349 bgp_dest_unlock_node(dest);
558d1fec 4350
ddb5b488
PZ
4351 if (SAFI_UNICAST == safi
4352 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4353 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4354
40381db7 4355 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4356 }
4357 if ((SAFI_MPLS_VPN == safi)
4358 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4359
40381db7 4360 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4361 }
4362
49e5a4a0 4363#ifdef ENABLE_BGP_VNC
d62a17ae 4364 if (SAFI_MPLS_VPN == safi) {
4365 mpls_label_t label_decoded = decode_label(label);
28070ee3 4366
d62a17ae 4367 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4368 type, sub_type, &label_decoded);
4369 }
4370 if (SAFI_ENCAP == safi) {
4371 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4372 type, sub_type, NULL);
4373 }
28070ee3
PZ
4374#endif
4375
d62a17ae 4376 return 0;
4377 } // End of implicit withdraw
718e3744 4378
d62a17ae 4379 /* Received Logging. */
4380 if (bgp_debug_update(peer, p, NULL, 1)) {
4381 if (!peer->rcvd_attr_printed) {
f70c91dc 4382 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4383 peer->rcvd_attr_str);
4384 peer->rcvd_attr_printed = 1;
4385 }
718e3744 4386
a4d82a8a 4387 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4388 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4389 pfx_buf, sizeof(pfx_buf));
f70c91dc 4390 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4391 }
718e3744 4392
d62a17ae 4393 /* Make new BGP info. */
9bcb3eef 4394 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4395
d62a17ae 4396 /* Update MPLS label */
4397 if (has_valid_label) {
18ee8310 4398 extra = bgp_path_info_extra_get(new);
8ba71050 4399 if (extra->label != label) {
dbd587da
QY
4400 memcpy(&extra->label, label,
4401 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4402 extra->num_labels = num_labels;
4403 }
b57ba6d2
MK
4404 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4405 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4406 }
718e3744 4407
e496b420
HS
4408 /* Update SRv6 SID */
4409 if (safi == SAFI_MPLS_VPN) {
4410 extra = bgp_path_info_extra_get(new);
4411 if (attr->srv6_l3vpn) {
16f3db2d 4412 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4413 extra->num_sids = 1;
cc8f05df 4414
16f3db2d
RS
4415 extra->sid[0].loc_block_len =
4416 attr->srv6_l3vpn->loc_block_len;
4417 extra->sid[0].loc_node_len =
4418 attr->srv6_l3vpn->loc_node_len;
4419 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4420 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4421 extra->sid[0].transposition_len =
4422 attr->srv6_l3vpn->transposition_len;
4423 extra->sid[0].transposition_offset =
4424 attr->srv6_l3vpn->transposition_offset;
e496b420 4425 } else if (attr->srv6_vpn) {
16f3db2d 4426 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4427 extra->num_sids = 1;
4428 }
4429 }
4430
d62a17ae 4431 /* Nexthop reachability check. */
7c312383
AD
4432 if (((afi == AFI_IP || afi == AFI_IP6)
4433 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4434 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4435 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4436 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4437 && !CHECK_FLAG(peer->flags,
4438 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4439 && !CHECK_FLAG(bgp->flags,
4440 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4441 connected = 1;
4442 else
4443 connected = 0;
4444
7c312383
AD
4445 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4446
4053e952 4447 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4448 connected, p)
a4d82a8a 4449 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4450 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4451 else {
4452 if (BGP_DEBUG(nht, NHT)) {
4453 char buf1[INET6_ADDRSTRLEN];
4454 inet_ntop(AF_INET,
4455 (const void *)&attr_new->nexthop,
4456 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4457 zlog_debug("%s(%s): NH unresolved", __func__,
4458 buf1);
d62a17ae 4459 }
9bcb3eef 4460 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4461 }
4462 } else
9bcb3eef 4463 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4464
d62a17ae 4465 /* Addpath ID */
4466 new->addpath_rx_id = addpath_id;
4467
4468 /* Increment prefix */
4469 bgp_aggregate_increment(bgp, p, new, afi, safi);
4470
4471 /* Register new BGP information. */
9bcb3eef 4472 bgp_path_info_add(dest, new);
d62a17ae 4473
4474 /* route_node_get lock */
9bcb3eef 4475 bgp_dest_unlock_node(dest);
558d1fec 4476
49e5a4a0 4477#ifdef ENABLE_BGP_VNC
d62a17ae 4478 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4479 struct bgp_dest *pdest = NULL;
d62a17ae 4480 struct bgp_table *table = NULL;
4481
9bcb3eef
DS
4482 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4483 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4484 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4485
4486 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4487 bgp, prd, table, p, new);
4488 }
9bcb3eef 4489 bgp_dest_unlock_node(pdest);
d62a17ae 4490 }
65efcfce
LB
4491#endif
4492
d62a17ae 4493 /* If this is an EVPN route, process for import. */
7c312383 4494 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4495 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4496
9bcb3eef 4497 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4498
d62a17ae 4499 /* Process change. */
9bcb3eef 4500 bgp_process(bgp, dest, afi, safi);
718e3744 4501
ddb5b488
PZ
4502 if (SAFI_UNICAST == safi
4503 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4504 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4505 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4506 }
4507 if ((SAFI_MPLS_VPN == safi)
4508 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4509
4510 vpn_leak_to_vrf_update(bgp, new);
4511 }
49e5a4a0 4512#ifdef ENABLE_BGP_VNC
d62a17ae 4513 if (SAFI_MPLS_VPN == safi) {
4514 mpls_label_t label_decoded = decode_label(label);
28070ee3 4515
d62a17ae 4516 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4517 sub_type, &label_decoded);
4518 }
4519 if (SAFI_ENCAP == safi) {
4520 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4521 sub_type, NULL);
4522 }
28070ee3
PZ
4523#endif
4524
d62a17ae 4525 return 0;
718e3744 4526
d62a17ae 4527/* This BGP update is filtered. Log the reason then update BGP
4528 entry. */
4529filtered:
9bcb3eef 4530 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4531
d62a17ae 4532 if (bgp_debug_update(peer, p, NULL, 1)) {
4533 if (!peer->rcvd_attr_printed) {
f70c91dc 4534 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4535 peer->rcvd_attr_str);
4536 peer->rcvd_attr_printed = 1;
4537 }
718e3744 4538
a4d82a8a 4539 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4540 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4541 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4542 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4543 peer, pfx_buf, reason);
d62a17ae 4544 }
128ea8ab 4545
40381db7 4546 if (pi) {
d62a17ae 4547 /* If this is an EVPN route, un-import it as it is now filtered.
4548 */
4549 if (safi == SAFI_EVPN)
40381db7 4550 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4551
ddb5b488
PZ
4552 if (SAFI_UNICAST == safi
4553 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4554 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4555
40381db7 4556 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4557 }
4558 if ((SAFI_MPLS_VPN == safi)
4559 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4560
40381db7 4561 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4562 }
4563
9bcb3eef 4564 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4565 }
4566
9bcb3eef 4567 bgp_dest_unlock_node(dest);
558d1fec 4568
49e5a4a0 4569#ifdef ENABLE_BGP_VNC
d62a17ae 4570 /*
4571 * Filtered update is treated as an implicit withdrawal (see
4572 * bgp_rib_remove()
4573 * a few lines above)
4574 */
4575 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4576 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4577 0);
4578 }
97736e32
PZ
4579#endif
4580
d62a17ae 4581 return 0;
718e3744 4582}
4583
26a3ffd6 4584int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4585 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4586 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4587 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4588{
d62a17ae 4589 struct bgp *bgp;
4590 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4591 struct bgp_dest *dest;
40381db7 4592 struct bgp_path_info *pi;
718e3744 4593
49e5a4a0 4594#ifdef ENABLE_BGP_VNC
d62a17ae 4595 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4596 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4597 0);
4598 }
28070ee3
PZ
4599#endif
4600
d62a17ae 4601 bgp = peer->bgp;
4602
4603 /* Lookup node. */
9bcb3eef 4604 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4605
4606 /* If peer is soft reconfiguration enabled. Record input packet for
4607 * further calculation.
4608 *
4609 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4610 * routes that are filtered. This tanks out Quagga RS pretty badly due
4611 * to
4612 * the iteration over all RS clients.
4613 * Since we need to remove the entry from adj_in anyway, do that first
4614 * and
4615 * if there was no entry, we don't need to do anything more.
4616 */
4617 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4618 && peer != bgp->peer_self)
9bcb3eef 4619 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4620 peer->stat_pfx_dup_withdraw++;
4621
d62a17ae 4622 if (bgp_debug_update(peer, p, NULL, 1)) {
4623 bgp_debug_rdpfxpath2str(
a4d82a8a 4624 afi, safi, prd, p, label, num_labels,
6c995628
AD
4625 addpath_id ? 1 : 0, addpath_id, NULL,
4626 pfx_buf, sizeof(pfx_buf));
d62a17ae 4627 zlog_debug(
4628 "%s withdrawing route %s not in adj-in",
4629 peer->host, pfx_buf);
4630 }
9bcb3eef 4631 bgp_dest_unlock_node(dest);
d62a17ae 4632 return 0;
4633 }
cd808e74 4634
d62a17ae 4635 /* Lookup withdrawn route. */
9bcb3eef 4636 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4637 if (pi->peer == peer && pi->type == type
4638 && pi->sub_type == sub_type
4639 && pi->addpath_rx_id == addpath_id)
d62a17ae 4640 break;
4641
4642 /* Logging. */
4643 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4644 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4645 addpath_id ? 1 : 0, addpath_id, NULL,
4646 pfx_buf, sizeof(pfx_buf));
f70c91dc 4647 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4648 pfx_buf);
4649 }
718e3744 4650
d62a17ae 4651 /* Withdraw specified route from routing table. */
40381db7 4652 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4653 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4654 if (SAFI_UNICAST == safi
4655 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4656 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4657 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4658 }
4659 if ((SAFI_MPLS_VPN == safi)
4660 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4661
40381db7 4662 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4663 }
4664 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4665 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4666 addpath_id ? 1 : 0, addpath_id, NULL,
4667 pfx_buf, sizeof(pfx_buf));
d62a17ae 4668 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4669 }
718e3744 4670
d62a17ae 4671 /* Unlock bgp_node_get() lock. */
9bcb3eef 4672 bgp_dest_unlock_node(dest);
d62a17ae 4673
4674 return 0;
718e3744 4675}
6b0655a2 4676
d62a17ae 4677void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4678 int withdraw)
718e3744 4679{
d62a17ae 4680 struct update_subgroup *subgrp;
4681 subgrp = peer_subgroup(peer, afi, safi);
4682 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4683}
6182d65b 4684
718e3744 4685
3f9c7369
DS
4686/*
4687 * bgp_stop_announce_route_timer
4688 */
d62a17ae 4689void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4690{
d62a17ae 4691 if (!paf->t_announce_route)
4692 return;
4693
50478845 4694 thread_cancel(&paf->t_announce_route);
718e3744 4695}
6b0655a2 4696
3f9c7369
DS
4697/*
4698 * bgp_announce_route_timer_expired
4699 *
4700 * Callback that is invoked when the route announcement timer for a
4701 * peer_af expires.
4702 */
cc9f21da 4703static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4704{
d62a17ae 4705 struct peer_af *paf;
4706 struct peer *peer;
558d1fec 4707
d62a17ae 4708 paf = THREAD_ARG(t);
4709 peer = paf->peer;
718e3744 4710
feb17238 4711 if (!peer_established(peer))
cc9f21da 4712 return;
3f9c7369 4713
d62a17ae 4714 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4715 return;
3f9c7369 4716
d62a17ae 4717 peer_af_announce_route(paf, 1);
c5aec50b
MK
4718
4719 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4720 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4721}
4722
3f9c7369
DS
4723/*
4724 * bgp_announce_route
4725 *
4726 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4727 *
4728 * if force is true we will force an update even if the update
4729 * limiting code is attempted to kick in.
3f9c7369 4730 */
e1a32ec1 4731void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4732{
4733 struct peer_af *paf;
4734 struct update_subgroup *subgrp;
4735
4736 paf = peer_af_find(peer, afi, safi);
4737 if (!paf)
4738 return;
4739 subgrp = PAF_SUBGRP(paf);
4740
4741 /*
4742 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4743 * or a refresh has already been triggered.
4744 */
4745 if (!subgrp || paf->t_announce_route)
4746 return;
4747
e1a32ec1
DS
4748 if (force)
4749 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4750
d62a17ae 4751 /*
4752 * Start a timer to stagger/delay the announce. This serves
4753 * two purposes - announcement can potentially be combined for
4754 * multiple peers and the announcement doesn't happen in the
4755 * vty context.
4756 */
4757 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4758 (subgrp->peer_count == 1)
4759 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4760 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4761 &paf->t_announce_route);
3f9c7369
DS
4762}
4763
4764/*
4765 * Announce routes from all AF tables to a peer.
4766 *
4767 * This should ONLY be called when there is a need to refresh the
4768 * routes to the peer based on a policy change for this peer alone
4769 * or a route refresh request received from the peer.
4770 * The operation will result in splitting the peer from its existing
4771 * subgroups and putting it in new subgroups.
4772 */
d62a17ae 4773void bgp_announce_route_all(struct peer *peer)
718e3744 4774{
d62a17ae 4775 afi_t afi;
4776 safi_t safi;
4777
05c7a1cc 4778 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4779 bgp_announce_route(peer, afi, safi, false);
718e3744 4780}
6b0655a2 4781
46aeabed
LS
4782/* Flag or unflag bgp_dest to determine whether it should be treated by
4783 * bgp_soft_reconfig_table_task.
4784 * Flag if flag is true. Unflag if flag is false.
4785 */
4786static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4787{
4788 struct bgp_dest *dest;
4789 struct bgp_adj_in *ain;
4790
4791 if (!table)
4792 return;
4793
4794 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4795 for (ain = dest->adj_in; ain; ain = ain->next) {
4796 if (ain->peer != NULL)
4797 break;
4798 }
4799 if (flag && ain != NULL && ain->peer != NULL)
4800 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4801 else
4802 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4803 }
4804}
4805
4806static int bgp_soft_reconfig_table_update(struct peer *peer,
4807 struct bgp_dest *dest,
4808 struct bgp_adj_in *ain, afi_t afi,
4809 safi_t safi, struct prefix_rd *prd)
4810{
4811 struct bgp_path_info *pi;
4812 uint32_t num_labels = 0;
4813 mpls_label_t *label_pnt = NULL;
4814 struct bgp_route_evpn evpn;
4815
4816 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4817 if (pi->peer == peer)
4818 break;
4819
4820 if (pi && pi->extra)
4821 num_labels = pi->extra->num_labels;
4822 if (num_labels)
4823 label_pnt = &pi->extra->label[0];
4824 if (pi)
4825 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4826 sizeof(evpn));
4827 else
4828 memset(&evpn, 0, sizeof(evpn));
4829
4830 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4831 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4832 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4833 &evpn);
4834}
4835
d62a17ae 4836static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4837 struct bgp_table *table,
4838 struct prefix_rd *prd)
718e3744 4839{
d62a17ae 4840 int ret;
9bcb3eef 4841 struct bgp_dest *dest;
d62a17ae 4842 struct bgp_adj_in *ain;
718e3744 4843
d62a17ae 4844 if (!table)
4845 table = peer->bgp->rib[afi][safi];
718e3744 4846
9bcb3eef
DS
4847 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4848 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4849 if (ain->peer != peer)
4850 continue;
8692c506 4851
46aeabed
LS
4852 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4853 afi, safi, prd);
ea47320b
DL
4854
4855 if (ret < 0) {
9bcb3eef 4856 bgp_dest_unlock_node(dest);
ea47320b 4857 return;
d62a17ae 4858 }
4859 }
718e3744 4860}
4861
46aeabed
LS
4862/* Do soft reconfig table per bgp table.
4863 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4864 * when BGP_NODE_SOFT_RECONFIG is set,
4865 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4866 * Schedule a new thread to continue the job.
4867 * Without splitting the full job into several part,
4868 * vtysh waits for the job to finish before responding to a BGP command
4869 */
cc9f21da 4870static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
4871{
4872 uint32_t iter, max_iter;
4873 int ret;
4874 struct bgp_dest *dest;
4875 struct bgp_adj_in *ain;
4876 struct peer *peer;
4877 struct bgp_table *table;
4878 struct prefix_rd *prd;
4879 struct listnode *node, *nnode;
4880
4881 table = THREAD_ARG(thread);
4882 prd = NULL;
4883
4884 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4885 if (table->soft_reconfig_init) {
4886 /* first call of the function with a new srta structure.
4887 * Don't do any treatment this time on nodes
4888 * in order vtysh to respond quickly
4889 */
4890 max_iter = 0;
4891 }
4892
4893 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4894 dest = bgp_route_next(dest)) {
4895 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4896 continue;
4897
4898 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4899
4900 for (ain = dest->adj_in; ain; ain = ain->next) {
4901 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4902 nnode, peer)) {
4903 if (ain->peer != peer)
4904 continue;
4905
4906 ret = bgp_soft_reconfig_table_update(
4907 peer, dest, ain, table->afi,
4908 table->safi, prd);
4909 iter++;
4910
4911 if (ret < 0) {
4912 bgp_dest_unlock_node(dest);
4913 listnode_delete(
4914 table->soft_reconfig_peers,
4915 peer);
4916 bgp_announce_route(peer, table->afi,
e1a32ec1 4917 table->safi, false);
46aeabed
LS
4918 if (list_isempty(
4919 table->soft_reconfig_peers)) {
4920 list_delete(
4921 &table->soft_reconfig_peers);
4922 bgp_soft_reconfig_table_flag(
4923 table, false);
cc9f21da 4924 return;
46aeabed
LS
4925 }
4926 }
4927 }
4928 }
4929 }
4930
4931 /* we're either starting the initial iteration,
4932 * or we're going to continue an ongoing iteration
4933 */
4934 if (dest || table->soft_reconfig_init) {
4935 table->soft_reconfig_init = false;
4936 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4937 table, 0, &table->soft_reconfig_thread);
cc9f21da 4938 return;
46aeabed
LS
4939 }
4940 /* we're done, clean up the background iteration context info and
4941 schedule route annoucement
4942 */
4943 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4944 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 4945 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
4946 }
4947
4948 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
4949}
4950
4951
4952/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4953 * and peer.
4954 * - bgp cannot be NULL
4955 * - if table and peer are NULL, cancel all threads within the bgp instance
4956 * - if table is NULL and peer is not,
4957 * remove peer in all threads within the bgp instance
4958 * - if peer is NULL, cancel all threads matching table within the bgp instance
4959 */
4960void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4961 const struct bgp_table *table,
4962 const struct peer *peer)
4963{
4964 struct peer *npeer;
4965 struct listnode *node, *nnode;
4966 int afi, safi;
4967 struct bgp_table *ntable;
4968
4969 if (!bgp)
4970 return;
4971
4972 FOREACH_AFI_SAFI (afi, safi) {
4973 ntable = bgp->rib[afi][safi];
4974 if (!ntable)
4975 continue;
4976 if (table && table != ntable)
4977 continue;
4978
4979 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4980 npeer)) {
4981 if (peer && peer != npeer)
4982 continue;
4983 listnode_delete(ntable->soft_reconfig_peers, npeer);
4984 }
4985
4986 if (!ntable->soft_reconfig_peers
4987 || !list_isempty(ntable->soft_reconfig_peers))
4988 continue;
4989
4990 list_delete(&ntable->soft_reconfig_peers);
4991 bgp_soft_reconfig_table_flag(ntable, false);
4992 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4993 }
4994}
4995
d62a17ae 4996void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4997{
9bcb3eef 4998 struct bgp_dest *dest;
d62a17ae 4999 struct bgp_table *table;
46aeabed
LS
5000 struct listnode *node, *nnode;
5001 struct peer *npeer;
5002 struct peer_af *paf;
718e3744 5003
feb17238 5004 if (!peer_established(peer))
d62a17ae 5005 return;
718e3744 5006
d62a17ae 5007 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5008 && (safi != SAFI_EVPN)) {
5009 table = peer->bgp->rib[afi][safi];
5010 if (!table)
5011 return;
5012
5013 table->soft_reconfig_init = true;
5014
5015 if (!table->soft_reconfig_peers)
5016 table->soft_reconfig_peers = list_new();
5017 npeer = NULL;
5018 /* add peer to the table soft_reconfig_peers if not already
5019 * there
5020 */
5021 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5022 npeer)) {
5023 if (peer == npeer)
5024 break;
5025 }
5026 if (peer != npeer)
5027 listnode_add(table->soft_reconfig_peers, peer);
5028
5029 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5030 * on table would start back at the beginning.
5031 */
5032 bgp_soft_reconfig_table_flag(table, true);
5033
5034 if (!table->soft_reconfig_thread)
5035 thread_add_event(bm->master,
5036 bgp_soft_reconfig_table_task, table, 0,
5037 &table->soft_reconfig_thread);
5038 /* Cancel bgp_announce_route_timer_expired threads.
5039 * bgp_announce_route_timer_expired threads have been scheduled
5040 * to announce routes as soon as the soft_reconfigure process
5041 * finishes.
5042 * In this case, soft_reconfigure is also scheduled by using
5043 * a thread but is planned after the
5044 * bgp_announce_route_timer_expired threads. It means that,
5045 * without cancelling the threads, the route announcement task
5046 * would run before the soft reconfiguration one. That would
5047 * useless and would block vtysh during several seconds. Route
5048 * announcements are rescheduled as soon as the soft_reconfigure
5049 * process finishes.
5050 */
5051 paf = peer_af_find(peer, afi, safi);
5052 if (paf)
5053 bgp_stop_announce_route_timer(paf);
5054 } else
9bcb3eef
DS
5055 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5056 dest = bgp_route_next(dest)) {
5057 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5058
b54892e0
DS
5059 if (table == NULL)
5060 continue;
8692c506 5061
9bcb3eef 5062 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5063 struct prefix_rd prd;
5064
5065 prd.family = AF_UNSPEC;
5066 prd.prefixlen = 64;
5067 memcpy(&prd.val, p->u.val, 8);
5068
5069 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5070 }
718e3744 5071}
6b0655a2 5072
228da428 5073
d62a17ae 5074struct bgp_clear_node_queue {
9bcb3eef 5075 struct bgp_dest *dest;
228da428
CC
5076};
5077
d62a17ae 5078static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5079{
d62a17ae 5080 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5081 struct bgp_dest *dest = cnq->dest;
d62a17ae 5082 struct peer *peer = wq->spec.data;
40381db7 5083 struct bgp_path_info *pi;
3103e8d2 5084 struct bgp *bgp;
9bcb3eef
DS
5085 afi_t afi = bgp_dest_table(dest)->afi;
5086 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5087
9bcb3eef 5088 assert(dest && peer);
3103e8d2 5089 bgp = peer->bgp;
d62a17ae 5090
5091 /* It is possible that we have multiple paths for a prefix from a peer
5092 * if that peer is using AddPath.
5093 */
9bcb3eef 5094 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5095 if (pi->peer != peer)
ea47320b
DL
5096 continue;
5097
5098 /* graceful restart STALE flag set. */
9af52ccf
DA
5099 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5100 && peer->nsf[afi][safi])
5101 || CHECK_FLAG(peer->af_sflags[afi][safi],
5102 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5103 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5104 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5105 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5106 else {
5107 /* If this is an EVPN route, process for
5108 * un-import. */
5109 if (safi == SAFI_EVPN)
9bcb3eef
DS
5110 bgp_evpn_unimport_route(
5111 bgp, afi, safi,
5112 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5113 /* Handle withdraw for VRF route-leaking and L3VPN */
5114 if (SAFI_UNICAST == safi
5115 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5116 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5117 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5118 bgp, pi);
960035b2 5119 }
3103e8d2 5120 if (SAFI_MPLS_VPN == safi &&
960035b2 5121 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5122 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5123 }
3103e8d2 5124
9bcb3eef 5125 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5126 }
ea47320b 5127 }
d62a17ae 5128 return WQ_SUCCESS;
200df115 5129}
5130
d62a17ae 5131static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5132{
d62a17ae 5133 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5134 struct bgp_dest *dest = cnq->dest;
5135 struct bgp_table *table = bgp_dest_table(dest);
228da428 5136
9bcb3eef 5137 bgp_dest_unlock_node(dest);
d62a17ae 5138 bgp_table_unlock(table);
5139 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5140}
5141
d62a17ae 5142static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5143{
d62a17ae 5144 struct peer *peer = wq->spec.data;
64e580a7 5145
d62a17ae 5146 /* Tickle FSM to start moving again */
5147 BGP_EVENT_ADD(peer, Clearing_Completed);
5148
5149 peer_unlock(peer); /* bgp_clear_route */
200df115 5150}
718e3744 5151
d62a17ae 5152static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5153{
d62a17ae 5154 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5155
5156 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5157#undef CLEAR_QUEUE_NAME_LEN
5158
0ce1ca80 5159 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5160 peer->clear_node_queue->spec.hold = 10;
5161 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5162 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5163 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5164 peer->clear_node_queue->spec.max_retries = 0;
5165
5166 /* we only 'lock' this peer reference when the queue is actually active
5167 */
5168 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5169}
5170
d62a17ae 5171static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5172 struct bgp_table *table)
65ca75e0 5173{
9bcb3eef 5174 struct bgp_dest *dest;
b6c386bb 5175 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5176
d62a17ae 5177 if (!table)
5178 table = peer->bgp->rib[afi][safi];
dc83d712 5179
d62a17ae 5180 /* If still no table => afi/safi isn't configured at all or smth. */
5181 if (!table)
5182 return;
dc83d712 5183
9bcb3eef 5184 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5185 struct bgp_path_info *pi, *next;
d62a17ae 5186 struct bgp_adj_in *ain;
5187 struct bgp_adj_in *ain_next;
5188
5189 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5190 * queued for every clearing peer, regardless of whether it is
5191 * relevant to the peer at hand.
5192 *
5193 * Overview: There are 3 different indices which need to be
5194 * scrubbed, potentially, when a peer is removed:
5195 *
5196 * 1 peer's routes visible via the RIB (ie accepted routes)
5197 * 2 peer's routes visible by the (optional) peer's adj-in index
5198 * 3 other routes visible by the peer's adj-out index
5199 *
5200 * 3 there is no hurry in scrubbing, once the struct peer is
5201 * removed from bgp->peer, we could just GC such deleted peer's
5202 * adj-outs at our leisure.
5203 *
5204 * 1 and 2 must be 'scrubbed' in some way, at least made
5205 * invisible via RIB index before peer session is allowed to be
5206 * brought back up. So one needs to know when such a 'search' is
5207 * complete.
5208 *
5209 * Ideally:
5210 *
5211 * - there'd be a single global queue or a single RIB walker
5212 * - rather than tracking which route_nodes still need to be
5213 * examined on a peer basis, we'd track which peers still
5214 * aren't cleared
5215 *
5216 * Given that our per-peer prefix-counts now should be reliable,
5217 * this may actually be achievable. It doesn't seem to be a huge
5218 * problem at this time,
5219 *
5220 * It is possible that we have multiple paths for a prefix from
5221 * a peer
5222 * if that peer is using AddPath.
5223 */
9bcb3eef 5224 ain = dest->adj_in;
d62a17ae 5225 while (ain) {
5226 ain_next = ain->next;
5227
6a840fd9 5228 if (ain->peer == peer)
9bcb3eef 5229 bgp_adj_in_remove(dest, ain);
d62a17ae 5230
5231 ain = ain_next;
5232 }
5233
9bcb3eef 5234 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5235 next = pi->next;
5236 if (pi->peer != peer)
d62a17ae 5237 continue;
5238
5239 if (force)
9bcb3eef 5240 bgp_path_info_reap(dest, pi);
d62a17ae 5241 else {
5242 struct bgp_clear_node_queue *cnq;
5243
5244 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5245 bgp_table_lock(bgp_dest_table(dest));
5246 bgp_dest_lock_node(dest);
d62a17ae 5247 cnq = XCALLOC(
5248 MTYPE_BGP_CLEAR_NODE_QUEUE,
5249 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5250 cnq->dest = dest;
d62a17ae 5251 work_queue_add(peer->clear_node_queue, cnq);
5252 break;
5253 }
5254 }
5255 }
5256 return;
5257}
5258
5259void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5260{
9bcb3eef 5261 struct bgp_dest *dest;
d62a17ae 5262 struct bgp_table *table;
5263
5264 if (peer->clear_node_queue == NULL)
5265 bgp_clear_node_queue_init(peer);
5266
5267 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5268 * Idle until it receives a Clearing_Completed event. This protects
5269 * against peers which flap faster than we can we clear, which could
5270 * lead to:
5271 *
5272 * a) race with routes from the new session being installed before
5273 * clear_route_node visits the node (to delete the route of that
5274 * peer)
5275 * b) resource exhaustion, clear_route_node likely leads to an entry
5276 * on the process_main queue. Fast-flapping could cause that queue
5277 * to grow and grow.
5278 */
5279
5280 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5281 * the unlock will happen upon work-queue completion; other wise, the
5282 * unlock happens at the end of this function.
5283 */
5284 if (!peer->clear_node_queue->thread)
5285 peer_lock(peer);
5286
5287 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5288 bgp_clear_route_table(peer, afi, safi, NULL);
5289 else
9bcb3eef
DS
5290 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5291 dest = bgp_route_next(dest)) {
5292 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5293 if (!table)
5294 continue;
5295
5296 bgp_clear_route_table(peer, afi, safi, table);
5297 }
d62a17ae 5298
5299 /* unlock if no nodes got added to the clear-node-queue. */
5300 if (!peer->clear_node_queue->thread)
5301 peer_unlock(peer);
718e3744 5302}
d62a17ae 5303
5304void bgp_clear_route_all(struct peer *peer)
718e3744 5305{
d62a17ae 5306 afi_t afi;
5307 safi_t safi;
718e3744 5308
05c7a1cc
QY
5309 FOREACH_AFI_SAFI (afi, safi)
5310 bgp_clear_route(peer, afi, safi);
65efcfce 5311
49e5a4a0 5312#ifdef ENABLE_BGP_VNC
d62a17ae 5313 rfapiProcessPeerDown(peer);
65efcfce 5314#endif
718e3744 5315}
5316
d62a17ae 5317void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5318{
d62a17ae 5319 struct bgp_table *table;
9bcb3eef 5320 struct bgp_dest *dest;
d62a17ae 5321 struct bgp_adj_in *ain;
5322 struct bgp_adj_in *ain_next;
718e3744 5323
d62a17ae 5324 table = peer->bgp->rib[afi][safi];
718e3744 5325
d62a17ae 5326 /* It is possible that we have multiple paths for a prefix from a peer
5327 * if that peer is using AddPath.
5328 */
9bcb3eef
DS
5329 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5330 ain = dest->adj_in;
43143c8f 5331
d62a17ae 5332 while (ain) {
5333 ain_next = ain->next;
43143c8f 5334
6a840fd9 5335 if (ain->peer == peer)
9bcb3eef 5336 bgp_adj_in_remove(dest, ain);
43143c8f 5337
d62a17ae 5338 ain = ain_next;
5339 }
5340 }
718e3744 5341}
93406d87 5342
1479ed2f
DA
5343/* If any of the routes from the peer have been marked with the NO_LLGR
5344 * community, either as sent by the peer, or as the result of a configured
5345 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5346 * operation of [RFC4271].
5347 */
d62a17ae 5348void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5349{
9bcb3eef 5350 struct bgp_dest *dest;
40381db7 5351 struct bgp_path_info *pi;
d62a17ae 5352 struct bgp_table *table;
5353
9af52ccf 5354 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5355 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5356 dest = bgp_route_next(dest)) {
5357 struct bgp_dest *rm;
d62a17ae 5358
5359 /* look for neighbor in tables */
9bcb3eef 5360 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5361 if (!table)
ea47320b
DL
5362 continue;
5363
5364 for (rm = bgp_table_top(table); rm;
5365 rm = bgp_route_next(rm))
9bcb3eef 5366 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5367 pi = pi->next) {
40381db7 5368 if (pi->peer != peer)
ea47320b 5369 continue;
1479ed2f
DA
5370 if (CHECK_FLAG(
5371 peer->af_sflags[afi][safi],
5372 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5373 bgp_attr_get_community(pi->attr) &&
1479ed2f 5374 !community_include(
9a706b42
DA
5375 bgp_attr_get_community(
5376 pi->attr),
1479ed2f 5377 COMMUNITY_NO_LLGR))
e3015d91 5378 continue;
40381db7 5379 if (!CHECK_FLAG(pi->flags,
1defdda8 5380 BGP_PATH_STALE))
e3015d91 5381 continue;
ea47320b 5382
641065d4
KM
5383 /*
5384 * If this is VRF leaked route
5385 * process for withdraw.
5386 */
5387 if (pi->sub_type ==
5388 BGP_ROUTE_IMPORTED &&
5389 peer->bgp->inst_type ==
5390 BGP_INSTANCE_TYPE_DEFAULT)
5391 vpn_leak_to_vrf_withdraw(
5392 peer->bgp, pi);
5393
40381db7 5394 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5395 break;
5396 }
d62a17ae 5397 }
5398 } else {
9bcb3eef
DS
5399 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5400 dest = bgp_route_next(dest))
5401 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5402 pi = pi->next) {
40381db7 5403 if (pi->peer != peer)
ea47320b 5404 continue;
1479ed2f
DA
5405 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5406 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5407 bgp_attr_get_community(pi->attr) &&
5408 !community_include(
5409 bgp_attr_get_community(pi->attr),
5410 COMMUNITY_NO_LLGR))
e3015d91 5411 continue;
40381db7 5412 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5413 continue;
641065d4
KM
5414 if (safi == SAFI_UNICAST &&
5415 (peer->bgp->inst_type ==
5416 BGP_INSTANCE_TYPE_VRF ||
5417 peer->bgp->inst_type ==
5418 BGP_INSTANCE_TYPE_DEFAULT))
5419 vpn_leak_from_vrf_withdraw(
5420 bgp_get_default(), peer->bgp,
5421 pi);
5422
9bcb3eef 5423 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5424 break;
5425 }
d62a17ae 5426 }
93406d87 5427}
6b0655a2 5428
9af52ccf
DA
5429void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5430{
5431 struct bgp_dest *dest, *ndest;
5432 struct bgp_path_info *pi;
5433 struct bgp_table *table;
5434
5435 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5436 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5437 dest = bgp_route_next(dest)) {
5438 table = bgp_dest_get_bgp_table_info(dest);
5439 if (!table)
5440 continue;
5441
5442 for (ndest = bgp_table_top(table); ndest;
5443 ndest = bgp_route_next(ndest)) {
5444 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5445 pi = pi->next) {
5446 if (pi->peer != peer)
5447 continue;
5448
5449 if ((CHECK_FLAG(
5450 peer->af_sflags[afi][safi],
5451 PEER_STATUS_ENHANCED_REFRESH))
5452 && !CHECK_FLAG(pi->flags,
5453 BGP_PATH_STALE)
5454 && !CHECK_FLAG(
5455 pi->flags,
5456 BGP_PATH_UNUSEABLE)) {
5457 if (bgp_debug_neighbor_events(
5458 peer))
5459 zlog_debug(
5460 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5461 peer->host,
5462 afi2str(afi),
5463 safi2str(safi),
5464 bgp_dest_get_prefix(
5465 ndest));
5466
5467 bgp_path_info_set_flag(
5468 ndest, pi,
5469 BGP_PATH_STALE);
5470 }
5471 }
5472 }
5473 }
5474 } else {
5475 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5476 dest = bgp_route_next(dest)) {
5477 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5478 pi = pi->next) {
5479 if (pi->peer != peer)
5480 continue;
5481
5482 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5483 PEER_STATUS_ENHANCED_REFRESH))
5484 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5485 && !CHECK_FLAG(pi->flags,
5486 BGP_PATH_UNUSEABLE)) {
5487 if (bgp_debug_neighbor_events(peer))
5488 zlog_debug(
5489 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5490 peer->host,
5491 afi2str(afi),
5492 safi2str(safi),
5493 bgp_dest_get_prefix(
5494 dest));
5495
5496 bgp_path_info_set_flag(dest, pi,
5497 BGP_PATH_STALE);
5498 }
5499 }
5500 }
5501 }
5502}
5503
3dc339cd 5504bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5505{
e0df4c04 5506 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5507 return true;
e0df4c04 5508
9dac9fc8
DA
5509 if (peer->sort == BGP_PEER_EBGP
5510 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5511 || FILTER_LIST_OUT_NAME(filter)
5512 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5513 return true;
5514 return false;
9dac9fc8
DA
5515}
5516
3dc339cd 5517bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5518{
e0df4c04 5519 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5520 return true;
e0df4c04 5521
9dac9fc8
DA
5522 if (peer->sort == BGP_PEER_EBGP
5523 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5524 || FILTER_LIST_IN_NAME(filter)
5525 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5526 return true;
5527 return false;
9dac9fc8
DA
5528}
5529
568e10ca 5530static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5531 safi_t safi)
bb86c601 5532{
9bcb3eef 5533 struct bgp_dest *dest;
40381db7 5534 struct bgp_path_info *pi;
4b7e6066 5535 struct bgp_path_info *next;
bb86c601 5536
9bcb3eef
DS
5537 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5538 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5539 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5540
40381db7 5541 next = pi->next;
1b7bb747
CS
5542
5543 /* Unimport EVPN routes from VRFs */
5544 if (safi == SAFI_EVPN)
5545 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5546 SAFI_EVPN, p, pi);
1b7bb747 5547
40381db7
DS
5548 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5549 && pi->type == ZEBRA_ROUTE_BGP
5550 && (pi->sub_type == BGP_ROUTE_NORMAL
5551 || pi->sub_type == BGP_ROUTE_AGGREGATE
5552 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5553
d62a17ae 5554 if (bgp_fibupd_safi(safi))
b54892e0 5555 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5556 }
9514b37d 5557
9bcb3eef 5558 bgp_path_info_reap(dest, pi);
d62a17ae 5559 }
bb86c601
LB
5560}
5561
718e3744 5562/* Delete all kernel routes. */
d62a17ae 5563void bgp_cleanup_routes(struct bgp *bgp)
5564{
5565 afi_t afi;
9bcb3eef 5566 struct bgp_dest *dest;
67009e22 5567 struct bgp_table *table;
d62a17ae 5568
5569 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5570 if (afi == AFI_L2VPN)
5571 continue;
568e10ca 5572 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5573 SAFI_UNICAST);
d62a17ae 5574 /*
5575 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5576 */
5577 if (afi != AFI_L2VPN) {
5578 safi_t safi;
5579 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5580 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5581 dest = bgp_route_next(dest)) {
5582 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5583 if (table != NULL) {
5584 bgp_cleanup_table(bgp, table, safi);
5585 bgp_table_finish(&table);
9bcb3eef
DS
5586 bgp_dest_set_bgp_table_info(dest, NULL);
5587 bgp_dest_unlock_node(dest);
d62a17ae 5588 }
5589 }
5590 safi = SAFI_ENCAP;
9bcb3eef
DS
5591 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5592 dest = bgp_route_next(dest)) {
5593 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5594 if (table != NULL) {
5595 bgp_cleanup_table(bgp, table, safi);
5596 bgp_table_finish(&table);
9bcb3eef
DS
5597 bgp_dest_set_bgp_table_info(dest, NULL);
5598 bgp_dest_unlock_node(dest);
d62a17ae 5599 }
5600 }
5601 }
5602 }
9bcb3eef
DS
5603 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5604 dest = bgp_route_next(dest)) {
5605 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5606 if (table != NULL) {
5607 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5608 bgp_table_finish(&table);
9bcb3eef
DS
5609 bgp_dest_set_bgp_table_info(dest, NULL);
5610 bgp_dest_unlock_node(dest);
d62a17ae 5611 }
bb86c601 5612 }
718e3744 5613}
5614
d62a17ae 5615void bgp_reset(void)
718e3744 5616{
d62a17ae 5617 vty_reset();
5618 bgp_zclient_reset();
5619 access_list_reset();
5620 prefix_list_reset();
718e3744 5621}
6b0655a2 5622
be92fc9f 5623bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5624{
d62a17ae 5625 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5626 && CHECK_FLAG(peer->af_cap[afi][safi],
5627 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5628}
5629
718e3744 5630/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5631 value. */
d62a17ae 5632int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5633 struct bgp_nlri *packet)
5634{
d7c0a89a
QY
5635 uint8_t *pnt;
5636 uint8_t *lim;
d62a17ae 5637 struct prefix p;
5638 int psize;
5639 int ret;
5640 afi_t afi;
5641 safi_t safi;
be92fc9f 5642 bool addpath_capable;
d7c0a89a 5643 uint32_t addpath_id;
d62a17ae 5644
d62a17ae 5645 pnt = packet->nlri;
5646 lim = pnt + packet->length;
5647 afi = packet->afi;
5648 safi = packet->safi;
5649 addpath_id = 0;
be92fc9f 5650 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5651
5652 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5653 syntactic validity. If the field is syntactically incorrect,
5654 then the Error Subcode is set to Invalid Network Field. */
5655 for (; pnt < lim; pnt += psize) {
5656 /* Clear prefix structure. */
6006b807 5657 memset(&p, 0, sizeof(p));
d62a17ae 5658
be92fc9f 5659 if (addpath_capable) {
d62a17ae 5660
5661 /* When packet overflow occurs return immediately. */
761ed665 5662 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5663 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5664
a3a850a1 5665 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5666 addpath_id = ntohl(addpath_id);
d62a17ae 5667 pnt += BGP_ADDPATH_ID_LEN;
5668 }
718e3744 5669
d62a17ae 5670 /* Fetch prefix length. */
5671 p.prefixlen = *pnt++;
5672 /* afi/safi validity already verified by caller,
5673 * bgp_update_receive */
5674 p.family = afi2family(afi);
5675
5676 /* Prefix length check. */
5677 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5678 flog_err(
e50f7cfd 5679 EC_BGP_UPDATE_RCV,
14454c9f 5680 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5681 peer->host, p.prefixlen, packet->afi);
513386b5 5682 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5683 }
6b0655a2 5684
d62a17ae 5685 /* Packet size overflow check. */
5686 psize = PSIZE(p.prefixlen);
5687
5688 /* When packet overflow occur return immediately. */
5689 if (pnt + psize > lim) {
af4c2728 5690 flog_err(
e50f7cfd 5691 EC_BGP_UPDATE_RCV,
d62a17ae 5692 "%s [Error] Update packet error (prefix length %d overflows packet)",
5693 peer->host, p.prefixlen);
513386b5 5694 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5695 }
5696
5697 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5698 * prefix for the v4 and v6 afi's and unicast/multicast */
5699 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5700 flog_err(
e50f7cfd 5701 EC_BGP_UPDATE_RCV,
d62a17ae 5702 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5703 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5704 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5705 }
5706
5707 /* Fetch prefix from NLRI packet. */
a85297a7 5708 memcpy(p.u.val, pnt, psize);
d62a17ae 5709
5710 /* Check address. */
5711 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5712 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5713 /* From RFC4271 Section 6.3:
5714 *
5715 * If a prefix in the NLRI field is semantically
5716 * incorrect
5717 * (e.g., an unexpected multicast IP address),
5718 * an error SHOULD
5719 * be logged locally, and the prefix SHOULD be
5720 * ignored.
a4d82a8a 5721 */
af4c2728 5722 flog_err(
e50f7cfd 5723 EC_BGP_UPDATE_RCV,
23d0a753
DA
5724 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5725 peer->host, &p.u.prefix4);
d62a17ae 5726 continue;
5727 }
5728 }
5729
5730 /* Check address. */
5731 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5732 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5733 flog_err(
e50f7cfd 5734 EC_BGP_UPDATE_RCV,
c0d72166
DS
5735 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5736 peer->host, &p.u.prefix6);
d62a17ae 5737
5738 continue;
5739 }
5740 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5741 flog_err(
e50f7cfd 5742 EC_BGP_UPDATE_RCV,
c0d72166
DS
5743 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5744 peer->host, &p.u.prefix6);
d62a17ae 5745
5746 continue;
5747 }
5748 }
5749
5750 /* Normal process. */
5751 if (attr)
5752 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5753 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5754 NULL, NULL, 0, 0, NULL);
d62a17ae 5755 else
5756 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5757 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5758 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5759 NULL);
d62a17ae 5760
513386b5
DA
5761 /* Do not send BGP notification twice when maximum-prefix count
5762 * overflow. */
5763 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5764 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5765
5766 /* Address family configuration mismatch. */
d62a17ae 5767 if (ret < 0)
513386b5 5768 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5769 }
5770
5771 /* Packet length consistency check. */
5772 if (pnt != lim) {
af4c2728 5773 flog_err(
e50f7cfd 5774 EC_BGP_UPDATE_RCV,
d62a17ae 5775 "%s [Error] Update packet error (prefix length mismatch with total length)",
5776 peer->host);
513386b5 5777 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5778 }
6b0655a2 5779
513386b5 5780 return BGP_NLRI_PARSE_OK;
718e3744 5781}
5782
d62a17ae 5783static struct bgp_static *bgp_static_new(void)
718e3744 5784{
d62a17ae 5785 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5786}
5787
d62a17ae 5788static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5789{
0a22ddfb 5790 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5791 route_map_counter_decrement(bgp_static->rmap.map);
5792
0a22ddfb 5793 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5794 XFREE(MTYPE_BGP_STATIC, bgp_static);
5795}
5796
5f040085 5797void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5798 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5799{
9bcb3eef 5800 struct bgp_dest *dest;
40381db7 5801 struct bgp_path_info *pi;
4b7e6066 5802 struct bgp_path_info *new;
40381db7 5803 struct bgp_path_info rmap_path;
d62a17ae 5804 struct attr attr;
5805 struct attr *attr_new;
b68885f9 5806 route_map_result_t ret;
49e5a4a0 5807#ifdef ENABLE_BGP_VNC
d62a17ae 5808 int vnc_implicit_withdraw = 0;
65efcfce 5809#endif
fee0f4c6 5810
d62a17ae 5811 assert(bgp_static);
dd8103a9 5812
9bcb3eef 5813 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5814
d62a17ae 5815 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5816
d62a17ae 5817 attr.nexthop = bgp_static->igpnexthop;
5818 attr.med = bgp_static->igpmetric;
5819 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5820
d62a17ae 5821 if (bgp_static->atomic)
5822 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5823
d62a17ae 5824 /* Store label index, if required. */
5825 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5826 attr.label_index = bgp_static->label_index;
5827 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5828 }
718e3744 5829
d62a17ae 5830 /* Apply route-map. */
5831 if (bgp_static->rmap.name) {
5832 struct attr attr_tmp = attr;
80ced710 5833
6006b807 5834 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
5835 rmap_path.peer = bgp->peer_self;
5836 rmap_path.attr = &attr_tmp;
fee0f4c6 5837
d62a17ae 5838 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5839
1782514f 5840 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5841
d62a17ae 5842 bgp->peer_self->rmap_type = 0;
718e3744 5843
d62a17ae 5844 if (ret == RMAP_DENYMATCH) {
5845 /* Free uninterned attribute. */
5846 bgp_attr_flush(&attr_tmp);
718e3744 5847
d62a17ae 5848 /* Unintern original. */
5849 aspath_unintern(&attr.aspath);
5850 bgp_static_withdraw(bgp, p, afi, safi);
5851 return;
5852 }
7f323236 5853
637e5ba4 5854 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5855 bgp_attr_add_gshut_community(&attr_tmp);
5856
d62a17ae 5857 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5858 } else {
5859
637e5ba4 5860 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5861 bgp_attr_add_gshut_community(&attr);
5862
d62a17ae 5863 attr_new = bgp_attr_intern(&attr);
7f323236 5864 }
718e3744 5865
9bcb3eef 5866 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5867 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5868 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5869 break;
5870
40381db7
DS
5871 if (pi) {
5872 if (attrhash_cmp(pi->attr, attr_new)
5873 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5874 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5875 bgp_dest_unlock_node(dest);
d62a17ae 5876 bgp_attr_unintern(&attr_new);
5877 aspath_unintern(&attr.aspath);
5878 return;
5879 } else {
5880 /* The attribute is changed. */
9bcb3eef 5881 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5882
5883 /* Rewrite BGP route information. */
40381db7 5884 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5885 bgp_path_info_restore(dest, pi);
d62a17ae 5886 else
40381db7 5887 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5888#ifdef ENABLE_BGP_VNC
d62a17ae 5889 if ((afi == AFI_IP || afi == AFI_IP6)
5890 && (safi == SAFI_UNICAST)) {
40381db7 5891 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5892 /*
5893 * Implicit withdraw case.
40381db7 5894 * We have to do this before pi is
d62a17ae 5895 * changed
5896 */
5897 ++vnc_implicit_withdraw;
40381db7 5898 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5899 vnc_import_bgp_exterior_del_route(
40381db7 5900 bgp, p, pi);
d62a17ae 5901 }
5902 }
65efcfce 5903#endif
40381db7
DS
5904 bgp_attr_unintern(&pi->attr);
5905 pi->attr = attr_new;
5906 pi->uptime = bgp_clock();
49e5a4a0 5907#ifdef ENABLE_BGP_VNC
d62a17ae 5908 if ((afi == AFI_IP || afi == AFI_IP6)
5909 && (safi == SAFI_UNICAST)) {
5910 if (vnc_implicit_withdraw) {
40381db7 5911 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5912 vnc_import_bgp_exterior_add_route(
40381db7 5913 bgp, p, pi);
d62a17ae 5914 }
5915 }
65efcfce 5916#endif
718e3744 5917
d62a17ae 5918 /* Nexthop reachability check. */
892fedb6 5919 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5920 && (safi == SAFI_UNICAST
5921 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5922
5923 struct bgp *bgp_nexthop = bgp;
5924
40381db7
DS
5925 if (pi->extra && pi->extra->bgp_orig)
5926 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5927
5928 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5929 afi, safi, pi, NULL,
654a5978 5930 0, p))
9bcb3eef 5931 bgp_path_info_set_flag(dest, pi,
18ee8310 5932 BGP_PATH_VALID);
d62a17ae 5933 else {
5934 if (BGP_DEBUG(nht, NHT)) {
5935 char buf1[INET6_ADDRSTRLEN];
5936 inet_ntop(p->family,
5937 &p->u.prefix, buf1,
5938 INET6_ADDRSTRLEN);
5939 zlog_debug(
5940 "%s(%s): Route not in table, not advertising",
15569c58 5941 __func__, buf1);
d62a17ae 5942 }
18ee8310 5943 bgp_path_info_unset_flag(
9bcb3eef 5944 dest, pi, BGP_PATH_VALID);
d62a17ae 5945 }
5946 } else {
5947 /* Delete the NHT structure if any, if we're
5948 * toggling between
5949 * enabling/disabling import check. We
5950 * deregister the route
5951 * from NHT to avoid overloading NHT and the
5952 * process interaction
5953 */
40381db7 5954 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5955 bgp_path_info_set_flag(dest, pi,
5956 BGP_PATH_VALID);
d62a17ae 5957 }
5958 /* Process change. */
40381db7 5959 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5960 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5961
5962 if (SAFI_UNICAST == safi
5963 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5964 || bgp->inst_type
5965 == BGP_INSTANCE_TYPE_DEFAULT)) {
5966 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5967 pi);
ddb5b488
PZ
5968 }
5969
9bcb3eef 5970 bgp_dest_unlock_node(dest);
d62a17ae 5971 aspath_unintern(&attr.aspath);
5972 return;
5973 }
718e3744 5974 }
718e3744 5975
d62a17ae 5976 /* Make new BGP info. */
5977 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5978 attr_new, dest);
d62a17ae 5979 /* Nexthop reachability check. */
892fedb6 5980 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5981 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5982 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5983 p))
9bcb3eef 5984 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5985 else {
5986 if (BGP_DEBUG(nht, NHT)) {
5987 char buf1[INET6_ADDRSTRLEN];
5988 inet_ntop(p->family, &p->u.prefix, buf1,
5989 INET6_ADDRSTRLEN);
5990 zlog_debug(
5991 "%s(%s): Route not in table, not advertising",
15569c58 5992 __func__, buf1);
d62a17ae 5993 }
9bcb3eef 5994 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5995 }
5996 } else {
5997 /* Delete the NHT structure if any, if we're toggling between
5998 * enabling/disabling import check. We deregister the route
5999 * from NHT to avoid overloading NHT and the process interaction
6000 */
6001 bgp_unlink_nexthop(new);
6002
9bcb3eef 6003 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6004 }
078430f6 6005
d62a17ae 6006 /* Aggregate address increment. */
6007 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6008
d62a17ae 6009 /* Register new BGP information. */
9bcb3eef 6010 bgp_path_info_add(dest, new);
718e3744 6011
d62a17ae 6012 /* route_node_get lock */
9bcb3eef 6013 bgp_dest_unlock_node(dest);
d62a17ae 6014
6015 /* Process change. */
9bcb3eef 6016 bgp_process(bgp, dest, afi, safi);
d62a17ae 6017
ddb5b488
PZ
6018 if (SAFI_UNICAST == safi
6019 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6020 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6021 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6022 }
6023
d62a17ae 6024 /* Unintern original. */
6025 aspath_unintern(&attr.aspath);
718e3744 6026}
6027
5f040085 6028void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6029 safi_t safi)
718e3744 6030{
9bcb3eef 6031 struct bgp_dest *dest;
40381db7 6032 struct bgp_path_info *pi;
718e3744 6033
9bcb3eef 6034 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6035
d62a17ae 6036 /* Check selected route and self inserted route. */
9bcb3eef 6037 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6038 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6039 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6040 break;
6041
6042 /* Withdraw static BGP route from routing table. */
40381db7 6043 if (pi) {
ddb5b488
PZ
6044 if (SAFI_UNICAST == safi
6045 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6046 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6047 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6048 }
40381db7
DS
6049 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6050 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6051 bgp_path_info_delete(dest, pi);
6052 bgp_process(bgp, dest, afi, safi);
d62a17ae 6053 }
718e3744 6054
d62a17ae 6055 /* Unlock bgp_node_lookup. */
9bcb3eef 6056 bgp_dest_unlock_node(dest);
718e3744 6057}
6058
137446f9
LB
6059/*
6060 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6061 */
5f040085 6062static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6063 afi_t afi, safi_t safi,
6064 struct prefix_rd *prd)
718e3744 6065{
9bcb3eef 6066 struct bgp_dest *dest;
40381db7 6067 struct bgp_path_info *pi;
718e3744 6068
9bcb3eef 6069 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6070
d62a17ae 6071 /* Check selected route and self inserted route. */
9bcb3eef 6072 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6073 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6074 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6075 break;
718e3744 6076
d62a17ae 6077 /* Withdraw static BGP route from routing table. */
40381db7 6078 if (pi) {
49e5a4a0 6079#ifdef ENABLE_BGP_VNC
d62a17ae 6080 rfapiProcessWithdraw(
40381db7 6081 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6082 1); /* Kill, since it is an administrative change */
65efcfce 6083#endif
ddb5b488
PZ
6084 if (SAFI_MPLS_VPN == safi
6085 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6086 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6087 }
40381db7 6088 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6089 bgp_path_info_delete(dest, pi);
6090 bgp_process(bgp, dest, afi, safi);
d62a17ae 6091 }
718e3744 6092
d62a17ae 6093 /* Unlock bgp_node_lookup. */
9bcb3eef 6094 bgp_dest_unlock_node(dest);
718e3744 6095}
6096
5f040085 6097static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6098 struct bgp_static *bgp_static, afi_t afi,
6099 safi_t safi)
137446f9 6100{
9bcb3eef 6101 struct bgp_dest *dest;
4b7e6066 6102 struct bgp_path_info *new;
d62a17ae 6103 struct attr *attr_new;
6104 struct attr attr = {0};
40381db7 6105 struct bgp_path_info *pi;
49e5a4a0 6106#ifdef ENABLE_BGP_VNC
d62a17ae 6107 mpls_label_t label = 0;
65efcfce 6108#endif
d7c0a89a 6109 uint32_t num_labels = 0;
137446f9 6110
d62a17ae 6111 assert(bgp_static);
137446f9 6112
b57ba6d2
MK
6113 if (bgp_static->label != MPLS_INVALID_LABEL)
6114 num_labels = 1;
9bcb3eef
DS
6115 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6116 &bgp_static->prd);
137446f9 6117
d62a17ae 6118 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 6119
d62a17ae 6120 attr.nexthop = bgp_static->igpnexthop;
6121 attr.med = bgp_static->igpmetric;
6122 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6123
d62a17ae 6124 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6125 || (safi == SAFI_ENCAP)) {
6126 if (afi == AFI_IP) {
6127 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6128 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6129 }
6130 }
6131 if (afi == AFI_L2VPN) {
b04c1e99
IR
6132 if (bgp_static->gatewayIp.family == AF_INET) {
6133 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6134 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6135 &bgp_static->gatewayIp.u.prefix4,
6136 IPV4_MAX_BYTELEN);
b04c1e99
IR
6137 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6138 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6139 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6140 &bgp_static->gatewayIp.u.prefix6,
6141 IPV6_MAX_BYTELEN);
b04c1e99 6142 }
0a50c248 6143 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6144 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6145 struct bgp_encap_type_vxlan bet;
6006b807 6146 memset(&bet, 0, sizeof(bet));
3714a385 6147 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6148 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6149 }
6150 if (bgp_static->router_mac) {
6151 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6152 }
6153 }
6154 /* Apply route-map. */
6155 if (bgp_static->rmap.name) {
6156 struct attr attr_tmp = attr;
40381db7 6157 struct bgp_path_info rmap_path;
b68885f9 6158 route_map_result_t ret;
137446f9 6159
40381db7
DS
6160 rmap_path.peer = bgp->peer_self;
6161 rmap_path.attr = &attr_tmp;
137446f9 6162
d62a17ae 6163 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6164
1782514f 6165 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6166
d62a17ae 6167 bgp->peer_self->rmap_type = 0;
137446f9 6168
d62a17ae 6169 if (ret == RMAP_DENYMATCH) {
6170 /* Free uninterned attribute. */
6171 bgp_attr_flush(&attr_tmp);
137446f9 6172
d62a17ae 6173 /* Unintern original. */
6174 aspath_unintern(&attr.aspath);
6175 bgp_static_withdraw_safi(bgp, p, afi, safi,
6176 &bgp_static->prd);
6177 return;
6178 }
137446f9 6179
d62a17ae 6180 attr_new = bgp_attr_intern(&attr_tmp);
6181 } else {
6182 attr_new = bgp_attr_intern(&attr);
6183 }
137446f9 6184
9bcb3eef 6185 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6186 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6187 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6188 break;
6189
40381db7 6190 if (pi) {
40381db7 6191 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6192 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6193 bgp_dest_unlock_node(dest);
d62a17ae 6194 bgp_attr_unintern(&attr_new);
6195 aspath_unintern(&attr.aspath);
6196 return;
6197 } else {
6198 /* The attribute is changed. */
9bcb3eef 6199 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6200
6201 /* Rewrite BGP route information. */
40381db7 6202 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6203 bgp_path_info_restore(dest, pi);
d62a17ae 6204 else
40381db7
DS
6205 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6206 bgp_attr_unintern(&pi->attr);
6207 pi->attr = attr_new;
6208 pi->uptime = bgp_clock();
49e5a4a0 6209#ifdef ENABLE_BGP_VNC
40381db7
DS
6210 if (pi->extra)
6211 label = decode_label(&pi->extra->label[0]);
65efcfce 6212#endif
137446f9 6213
d62a17ae 6214 /* Process change. */
40381db7 6215 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6216 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6217
6218 if (SAFI_MPLS_VPN == safi
6219 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6220 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6221 }
49e5a4a0 6222#ifdef ENABLE_BGP_VNC
40381db7
DS
6223 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6224 pi->attr, afi, safi, pi->type,
6225 pi->sub_type, &label);
65efcfce 6226#endif
9bcb3eef 6227 bgp_dest_unlock_node(dest);
d62a17ae 6228 aspath_unintern(&attr.aspath);
6229 return;
6230 }
6231 }
137446f9
LB
6232
6233
d62a17ae 6234 /* Make new BGP info. */
6235 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6236 attr_new, dest);
1defdda8 6237 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6238 bgp_path_info_extra_get(new);
b57ba6d2
MK
6239 if (num_labels) {
6240 new->extra->label[0] = bgp_static->label;
6241 new->extra->num_labels = num_labels;
6242 }
49e5a4a0 6243#ifdef ENABLE_BGP_VNC
d62a17ae 6244 label = decode_label(&bgp_static->label);
65efcfce 6245#endif
137446f9 6246
d62a17ae 6247 /* Aggregate address increment. */
6248 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6249
d62a17ae 6250 /* Register new BGP information. */
9bcb3eef 6251 bgp_path_info_add(dest, new);
d62a17ae 6252 /* route_node_get lock */
9bcb3eef 6253 bgp_dest_unlock_node(dest);
137446f9 6254
d62a17ae 6255 /* Process change. */
9bcb3eef 6256 bgp_process(bgp, dest, afi, safi);
137446f9 6257
ddb5b488
PZ
6258 if (SAFI_MPLS_VPN == safi
6259 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6260 vpn_leak_to_vrf_update(bgp, new);
6261 }
49e5a4a0 6262#ifdef ENABLE_BGP_VNC
d62a17ae 6263 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6264 safi, new->type, new->sub_type, &label);
65efcfce
LB
6265#endif
6266
d62a17ae 6267 /* Unintern original. */
6268 aspath_unintern(&attr.aspath);
137446f9
LB
6269}
6270
718e3744 6271/* Configure static BGP network. When user don't run zebra, static
6272 route should be installed as valid. */
585f1adc
IR
6273static int bgp_static_set(struct vty *vty, const char *negate,
6274 const char *ip_str, afi_t afi, safi_t safi,
6275 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6276{
585f1adc
IR
6277 VTY_DECLVAR_CONTEXT(bgp, bgp);
6278 int ret;
d62a17ae 6279 struct prefix p;
6280 struct bgp_static *bgp_static;
9bcb3eef 6281 struct bgp_dest *dest;
d7c0a89a 6282 uint8_t need_update = 0;
d62a17ae 6283
585f1adc
IR
6284 /* Convert IP prefix string to struct prefix. */
6285 ret = str2prefix(ip_str, &p);
6286 if (!ret) {
6287 vty_out(vty, "%% Malformed prefix\n");
6288 return CMD_WARNING_CONFIG_FAILED;
6289 }
6290 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6291 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6292 return CMD_WARNING_CONFIG_FAILED;
6293 }
6294
d62a17ae 6295 apply_mask(&p);
718e3744 6296
e2a86ad9 6297 if (negate) {
718e3744 6298
e2a86ad9 6299 /* Set BGP static route configuration. */
9bcb3eef 6300 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6301
9bcb3eef 6302 if (!dest) {
585f1adc
IR
6303 vty_out(vty, "%% Can't find static route specified\n");
6304 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6305 }
6306
9bcb3eef 6307 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6308
e2a86ad9
DS
6309 if ((label_index != BGP_INVALID_LABEL_INDEX)
6310 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6311 vty_out(vty,
6312 "%% label-index doesn't match static route\n");
70d9b134 6313 bgp_dest_unlock_node(dest);
585f1adc 6314 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6315 }
d62a17ae 6316
e2a86ad9
DS
6317 if ((rmap && bgp_static->rmap.name)
6318 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6319 vty_out(vty,
6320 "%% route-map name doesn't match static route\n");
70d9b134 6321 bgp_dest_unlock_node(dest);
585f1adc 6322 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6323 }
718e3744 6324
e2a86ad9
DS
6325 /* Update BGP RIB. */
6326 if (!bgp_static->backdoor)
6327 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6328
e2a86ad9
DS
6329 /* Clear configuration. */
6330 bgp_static_free(bgp_static);
9bcb3eef
DS
6331 bgp_dest_set_bgp_static_info(dest, NULL);
6332 bgp_dest_unlock_node(dest);
6333 bgp_dest_unlock_node(dest);
e2a86ad9 6334 } else {
718e3744 6335
e2a86ad9 6336 /* Set BGP static route configuration. */
9bcb3eef
DS
6337 dest = bgp_node_get(bgp->route[afi][safi], &p);
6338 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6339 if (bgp_static) {
e2a86ad9 6340 /* Configuration change. */
e2a86ad9
DS
6341 /* Label index cannot be changed. */
6342 if (bgp_static->label_index != label_index) {
585f1adc
IR
6343 vty_out(vty, "%% cannot change label-index\n");
6344 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6345 }
d62a17ae 6346
e2a86ad9 6347 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6348 if (bgp_static->valid
6349 && bgp_static->backdoor != backdoor)
e2a86ad9 6350 need_update = 1;
718e3744 6351
e2a86ad9 6352 bgp_static->backdoor = backdoor;
718e3744 6353
e2a86ad9 6354 if (rmap) {
0a22ddfb
QY
6355 XFREE(MTYPE_ROUTE_MAP_NAME,
6356 bgp_static->rmap.name);
b4897fa5 6357 route_map_counter_decrement(
6358 bgp_static->rmap.map);
e2a86ad9
DS
6359 bgp_static->rmap.name =
6360 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6361 bgp_static->rmap.map =
6362 route_map_lookup_by_name(rmap);
b4897fa5 6363 route_map_counter_increment(
6364 bgp_static->rmap.map);
e2a86ad9 6365 } else {
0a22ddfb
QY
6366 XFREE(MTYPE_ROUTE_MAP_NAME,
6367 bgp_static->rmap.name);
b4897fa5 6368 route_map_counter_decrement(
6369 bgp_static->rmap.map);
e2a86ad9
DS
6370 bgp_static->rmap.map = NULL;
6371 bgp_static->valid = 0;
6372 }
9bcb3eef 6373 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6374 } else {
6375 /* New configuration. */
6376 bgp_static = bgp_static_new();
6377 bgp_static->backdoor = backdoor;
6378 bgp_static->valid = 0;
6379 bgp_static->igpmetric = 0;
975a328e 6380 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6381 bgp_static->label_index = label_index;
718e3744 6382
e2a86ad9 6383 if (rmap) {
0a22ddfb
QY
6384 XFREE(MTYPE_ROUTE_MAP_NAME,
6385 bgp_static->rmap.name);
b4897fa5 6386 route_map_counter_decrement(
6387 bgp_static->rmap.map);
e2a86ad9
DS
6388 bgp_static->rmap.name =
6389 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6390 bgp_static->rmap.map =
6391 route_map_lookup_by_name(rmap);
b4897fa5 6392 route_map_counter_increment(
6393 bgp_static->rmap.map);
e2a86ad9 6394 }
9bcb3eef 6395 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6396 }
d62a17ae 6397
e2a86ad9
DS
6398 bgp_static->valid = 1;
6399 if (need_update)
6400 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6401
e2a86ad9
DS
6402 if (!bgp_static->backdoor)
6403 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6404 }
d62a17ae 6405
585f1adc 6406 return CMD_SUCCESS;
d62a17ae 6407}
6408
6409void bgp_static_add(struct bgp *bgp)
6410{
6411 afi_t afi;
6412 safi_t safi;
9bcb3eef
DS
6413 struct bgp_dest *dest;
6414 struct bgp_dest *rm;
d62a17ae 6415 struct bgp_table *table;
6416 struct bgp_static *bgp_static;
6417
47fc6261 6418 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6419 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6420 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6421 dest = bgp_route_next(dest)) {
6422 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6423 continue;
ea47320b 6424
05c7a1cc
QY
6425 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6426 || (safi == SAFI_EVPN)) {
9bcb3eef 6427 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6428
6429 for (rm = bgp_table_top(table); rm;
6430 rm = bgp_route_next(rm)) {
a78beeb5 6431 bgp_static =
9bcb3eef 6432 bgp_dest_get_bgp_static_info(
5a8ba9fc 6433 rm);
9bcb3eef
DS
6434 bgp_static_update_safi(
6435 bgp, bgp_dest_get_prefix(rm),
6436 bgp_static, afi, safi);
d62a17ae 6437 }
05c7a1cc 6438 } else {
5a8ba9fc 6439 bgp_static_update(
9bcb3eef
DS
6440 bgp, bgp_dest_get_prefix(dest),
6441 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6442 safi);
ea47320b 6443 }
05c7a1cc 6444 }
47fc6261 6445 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6446}
6447
718e3744 6448/* Called from bgp_delete(). Delete all static routes from the BGP
6449 instance. */
d62a17ae 6450void bgp_static_delete(struct bgp *bgp)
6451{
6452 afi_t afi;
6453 safi_t safi;
9bcb3eef
DS
6454 struct bgp_dest *dest;
6455 struct bgp_dest *rm;
d62a17ae 6456 struct bgp_table *table;
6457 struct bgp_static *bgp_static;
6458
05c7a1cc 6459 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6460 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6461 dest = bgp_route_next(dest)) {
6462 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6463 continue;
ea47320b 6464
05c7a1cc
QY
6465 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6466 || (safi == SAFI_EVPN)) {
9bcb3eef 6467 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6468
6469 for (rm = bgp_table_top(table); rm;
6470 rm = bgp_route_next(rm)) {
a78beeb5 6471 bgp_static =
9bcb3eef 6472 bgp_dest_get_bgp_static_info(
5a8ba9fc 6473 rm);
c7d14ba6
PG
6474 if (!bgp_static)
6475 continue;
6476
05c7a1cc 6477 bgp_static_withdraw_safi(
9bcb3eef 6478 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6479 AFI_IP, safi,
6480 (struct prefix_rd *)
9bcb3eef
DS
6481 bgp_dest_get_prefix(
6482 dest));
ea47320b 6483 bgp_static_free(bgp_static);
811c6797 6484 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6485 NULL);
811c6797 6486 bgp_dest_unlock_node(rm);
d62a17ae 6487 }
05c7a1cc 6488 } else {
9bcb3eef 6489 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6490 bgp_static_withdraw(bgp,
9bcb3eef 6491 bgp_dest_get_prefix(dest),
b54892e0 6492 afi, safi);
05c7a1cc 6493 bgp_static_free(bgp_static);
9bcb3eef
DS
6494 bgp_dest_set_bgp_static_info(dest, NULL);
6495 bgp_dest_unlock_node(dest);
ea47320b 6496 }
05c7a1cc 6497 }
d62a17ae 6498}
6499
6500void bgp_static_redo_import_check(struct bgp *bgp)
6501{
6502 afi_t afi;
6503 safi_t safi;
9bcb3eef
DS
6504 struct bgp_dest *dest;
6505 struct bgp_dest *rm;
d62a17ae 6506 struct bgp_table *table;
6507 struct bgp_static *bgp_static;
6508
6509 /* Use this flag to force reprocessing of the route */
892fedb6 6510 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6511 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6512 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6513 dest = bgp_route_next(dest)) {
6514 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6515 continue;
ea47320b 6516
05c7a1cc
QY
6517 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6518 || (safi == SAFI_EVPN)) {
9bcb3eef 6519 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6520
6521 for (rm = bgp_table_top(table); rm;
6522 rm = bgp_route_next(rm)) {
a78beeb5 6523 bgp_static =
9bcb3eef 6524 bgp_dest_get_bgp_static_info(
5a8ba9fc 6525 rm);
9bcb3eef
DS
6526 bgp_static_update_safi(
6527 bgp, bgp_dest_get_prefix(rm),
6528 bgp_static, afi, safi);
d62a17ae 6529 }
05c7a1cc 6530 } else {
9bcb3eef
DS
6531 bgp_static = bgp_dest_get_bgp_static_info(dest);
6532 bgp_static_update(bgp,
6533 bgp_dest_get_prefix(dest),
6534 bgp_static, afi, safi);
ea47320b 6535 }
05c7a1cc
QY
6536 }
6537 }
892fedb6 6538 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6539}
6540
6541static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6542 safi_t safi)
6543{
6544 struct bgp_table *table;
9bcb3eef 6545 struct bgp_dest *dest;
40381db7 6546 struct bgp_path_info *pi;
d62a17ae 6547
dfb6fd1d
NT
6548 /* Do not install the aggregate route if BGP is in the
6549 * process of termination.
6550 */
892fedb6
DA
6551 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6552 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6553 return;
6554
d62a17ae 6555 table = bgp->rib[afi][safi];
9bcb3eef
DS
6556 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6557 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6558 if (pi->peer == bgp->peer_self
6559 && ((pi->type == ZEBRA_ROUTE_BGP
6560 && pi->sub_type == BGP_ROUTE_STATIC)
6561 || (pi->type != ZEBRA_ROUTE_BGP
6562 && pi->sub_type
d62a17ae 6563 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6564 bgp_aggregate_decrement(
6565 bgp, bgp_dest_get_prefix(dest), pi, afi,
6566 safi);
40381db7 6567 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6568 bgp_path_info_delete(dest, pi);
6569 bgp_process(bgp, dest, afi, safi);
d62a17ae 6570 }
6571 }
6572 }
ad4cbda1 6573}
6574
6575/*
6576 * Purge all networks and redistributed routes from routing table.
6577 * Invoked upon the instance going down.
6578 */
d62a17ae 6579void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6580{
d62a17ae 6581 afi_t afi;
6582 safi_t safi;
ad4cbda1 6583
05c7a1cc
QY
6584 FOREACH_AFI_SAFI (afi, safi)
6585 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6586}
6587
137446f9
LB
6588/*
6589 * gpz 110624
6590 * Currently this is used to set static routes for VPN and ENCAP.
6591 * I think it can probably be factored with bgp_static_set.
6592 */
d62a17ae 6593int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6594 const char *ip_str, const char *rd_str,
6595 const char *label_str, const char *rmap_str,
6596 int evpn_type, const char *esi, const char *gwip,
6597 const char *ethtag, const char *routermac)
6598{
6599 VTY_DECLVAR_CONTEXT(bgp, bgp);
6600 int ret;
6601 struct prefix p;
6602 struct prefix_rd prd;
9bcb3eef
DS
6603 struct bgp_dest *pdest;
6604 struct bgp_dest *dest;
d62a17ae 6605 struct bgp_table *table;
6606 struct bgp_static *bgp_static;
6607 mpls_label_t label = MPLS_INVALID_LABEL;
6608 struct prefix gw_ip;
6609
6610 /* validate ip prefix */
6611 ret = str2prefix(ip_str, &p);
6612 if (!ret) {
6613 vty_out(vty, "%% Malformed prefix\n");
6614 return CMD_WARNING_CONFIG_FAILED;
6615 }
6616 apply_mask(&p);
6617 if ((afi == AFI_L2VPN)
6618 && (bgp_build_evpn_prefix(evpn_type,
6619 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6620 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6621 return CMD_WARNING_CONFIG_FAILED;
6622 }
718e3744 6623
d62a17ae 6624 ret = str2prefix_rd(rd_str, &prd);
6625 if (!ret) {
6626 vty_out(vty, "%% Malformed rd\n");
6627 return CMD_WARNING_CONFIG_FAILED;
6628 }
718e3744 6629
d62a17ae 6630 if (label_str) {
6631 unsigned long label_val;
6632 label_val = strtoul(label_str, NULL, 10);
6633 encode_label(label_val, &label);
6634 }
9bedbb1e 6635
d62a17ae 6636 if (safi == SAFI_EVPN) {
6637 if (esi && str2esi(esi, NULL) == 0) {
6638 vty_out(vty, "%% Malformed ESI\n");
6639 return CMD_WARNING_CONFIG_FAILED;
6640 }
6641 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6642 vty_out(vty, "%% Malformed Router MAC\n");
6643 return CMD_WARNING_CONFIG_FAILED;
6644 }
6645 if (gwip) {
6006b807 6646 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6647 ret = str2prefix(gwip, &gw_ip);
6648 if (!ret) {
6649 vty_out(vty, "%% Malformed GatewayIp\n");
6650 return CMD_WARNING_CONFIG_FAILED;
6651 }
6652 if ((gw_ip.family == AF_INET
3714a385 6653 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6654 (struct prefix_evpn *)&p))
6655 || (gw_ip.family == AF_INET6
3714a385 6656 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6657 (struct prefix_evpn *)&p))) {
6658 vty_out(vty,
6659 "%% GatewayIp family differs with IP prefix\n");
6660 return CMD_WARNING_CONFIG_FAILED;
6661 }
6662 }
6663 }
9bcb3eef
DS
6664 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6665 if (!bgp_dest_has_bgp_path_info_data(pdest))
6666 bgp_dest_set_bgp_table_info(pdest,
67009e22 6667 bgp_table_init(bgp, afi, safi));
9bcb3eef 6668 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6669
9bcb3eef 6670 dest = bgp_node_get(table, &p);
d62a17ae 6671
9bcb3eef 6672 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6673 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6674 bgp_dest_unlock_node(dest);
d62a17ae 6675 } else {
6676 /* New configuration. */
6677 bgp_static = bgp_static_new();
6678 bgp_static->backdoor = 0;
6679 bgp_static->valid = 0;
6680 bgp_static->igpmetric = 0;
975a328e 6681 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6682 bgp_static->label = label;
6683 bgp_static->prd = prd;
6684
6685 if (rmap_str) {
0a22ddfb 6686 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6687 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6688 bgp_static->rmap.name =
6689 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6690 bgp_static->rmap.map =
6691 route_map_lookup_by_name(rmap_str);
b4897fa5 6692 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6693 }
718e3744 6694
d62a17ae 6695 if (safi == SAFI_EVPN) {
6696 if (esi) {
6697 bgp_static->eth_s_id =
6698 XCALLOC(MTYPE_ATTR,
0a50c248 6699 sizeof(esi_t));
d62a17ae 6700 str2esi(esi, bgp_static->eth_s_id);
6701 }
6702 if (routermac) {
6703 bgp_static->router_mac =
28328ea9 6704 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6705 (void)prefix_str2mac(routermac,
6706 bgp_static->router_mac);
d62a17ae 6707 }
6708 if (gwip)
6709 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6710 }
9bcb3eef 6711 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6712
d62a17ae 6713 bgp_static->valid = 1;
6714 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6715 }
718e3744 6716
d62a17ae 6717 return CMD_SUCCESS;
718e3744 6718}
6719
6720/* Configure static BGP network. */
d62a17ae 6721int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6722 const char *ip_str, const char *rd_str,
6723 const char *label_str, int evpn_type, const char *esi,
6724 const char *gwip, const char *ethtag)
6725{
6726 VTY_DECLVAR_CONTEXT(bgp, bgp);
6727 int ret;
6728 struct prefix p;
6729 struct prefix_rd prd;
9bcb3eef
DS
6730 struct bgp_dest *pdest;
6731 struct bgp_dest *dest;
d62a17ae 6732 struct bgp_table *table;
6733 struct bgp_static *bgp_static;
6734 mpls_label_t label = MPLS_INVALID_LABEL;
6735
6736 /* Convert IP prefix string to struct prefix. */
6737 ret = str2prefix(ip_str, &p);
6738 if (!ret) {
6739 vty_out(vty, "%% Malformed prefix\n");
6740 return CMD_WARNING_CONFIG_FAILED;
6741 }
6742 apply_mask(&p);
6743 if ((afi == AFI_L2VPN)
6744 && (bgp_build_evpn_prefix(evpn_type,
6745 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6746 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6747 return CMD_WARNING_CONFIG_FAILED;
6748 }
6749 ret = str2prefix_rd(rd_str, &prd);
6750 if (!ret) {
6751 vty_out(vty, "%% Malformed rd\n");
6752 return CMD_WARNING_CONFIG_FAILED;
6753 }
718e3744 6754
d62a17ae 6755 if (label_str) {
6756 unsigned long label_val;
6757 label_val = strtoul(label_str, NULL, 10);
6758 encode_label(label_val, &label);
6759 }
718e3744 6760
9bcb3eef
DS
6761 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6762 if (!bgp_dest_has_bgp_path_info_data(pdest))
6763 bgp_dest_set_bgp_table_info(pdest,
67009e22 6764 bgp_table_init(bgp, afi, safi));
d62a17ae 6765 else
9bcb3eef
DS
6766 bgp_dest_unlock_node(pdest);
6767 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6768
9bcb3eef 6769 dest = bgp_node_lookup(table, &p);
6b0655a2 6770
9bcb3eef 6771 if (dest) {
d62a17ae 6772 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6773
9bcb3eef 6774 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6775 bgp_static_free(bgp_static);
9bcb3eef
DS
6776 bgp_dest_set_bgp_static_info(dest, NULL);
6777 bgp_dest_unlock_node(dest);
6778 bgp_dest_unlock_node(dest);
d62a17ae 6779 } else
6780 vty_out(vty, "%% Can't find the route\n");
6781
6782 return CMD_SUCCESS;
6783}
6784
6785static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6786 const char *rmap_name)
6787{
6788 VTY_DECLVAR_CONTEXT(bgp, bgp);
6789 struct bgp_rmap *rmap;
6790
6791 rmap = &bgp->table_map[afi][safi];
6792 if (rmap_name) {
0a22ddfb 6793 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6794 route_map_counter_decrement(rmap->map);
d62a17ae 6795 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6796 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6797 route_map_counter_increment(rmap->map);
d62a17ae 6798 } else {
0a22ddfb 6799 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6800 route_map_counter_decrement(rmap->map);
d62a17ae 6801 rmap->map = NULL;
6802 }
73ac8160 6803
d62a17ae 6804 if (bgp_fibupd_safi(safi))
6805 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6806
d62a17ae 6807 return CMD_SUCCESS;
73ac8160
DS
6808}
6809
d62a17ae 6810static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6811 const char *rmap_name)
73ac8160 6812{
d62a17ae 6813 VTY_DECLVAR_CONTEXT(bgp, bgp);
6814 struct bgp_rmap *rmap;
73ac8160 6815
d62a17ae 6816 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6817 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6818 route_map_counter_decrement(rmap->map);
d62a17ae 6819 rmap->map = NULL;
73ac8160 6820
d62a17ae 6821 if (bgp_fibupd_safi(safi))
6822 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6823
d62a17ae 6824 return CMD_SUCCESS;
73ac8160
DS
6825}
6826
2b791107 6827void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6828 safi_t safi)
73ac8160 6829{
d62a17ae 6830 if (bgp->table_map[afi][safi].name) {
d62a17ae 6831 vty_out(vty, " table-map %s\n",
6832 bgp->table_map[afi][safi].name);
6833 }
73ac8160
DS
6834}
6835
73ac8160
DS
6836DEFUN (bgp_table_map,
6837 bgp_table_map_cmd,
6838 "table-map WORD",
6839 "BGP table to RIB route download filter\n"
6840 "Name of the route map\n")
6841{
d62a17ae 6842 int idx_word = 1;
6843 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6844 argv[idx_word]->arg);
73ac8160
DS
6845}
6846DEFUN (no_bgp_table_map,
6847 no_bgp_table_map_cmd,
6848 "no table-map WORD",
3a2d747c 6849 NO_STR
73ac8160
DS
6850 "BGP table to RIB route download filter\n"
6851 "Name of the route map\n")
6852{
d62a17ae 6853 int idx_word = 2;
6854 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6855 argv[idx_word]->arg);
73ac8160
DS
6856}
6857
585f1adc
IR
6858DEFPY(bgp_network,
6859 bgp_network_cmd,
6860 "[no] network \
6861 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6862 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6863 backdoor$backdoor}]",
6864 NO_STR
6865 "Specify a network to announce via BGP\n"
6866 "IPv4 prefix\n"
6867 "Network number\n"
6868 "Network mask\n"
6869 "Network mask\n"
6870 "Route-map to modify the attributes\n"
6871 "Name of the route map\n"
6872 "Label index to associate with the prefix\n"
6873 "Label index value\n"
6874 "Specify a BGP backdoor route\n")
6875{
6876 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6877
6878 if (address_str) {
6879 int ret;
718e3744 6880
e2a86ad9 6881 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6882 addr_prefix_str,
6883 sizeof(addr_prefix_str));
e2a86ad9
DS
6884 if (!ret) {
6885 vty_out(vty, "%% Inconsistent address and mask\n");
6886 return CMD_WARNING_CONFIG_FAILED;
6887 }
d62a17ae 6888 }
718e3744 6889
585f1adc
IR
6890 return bgp_static_set(
6891 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6892 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6893 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6894}
6895
585f1adc
IR
6896DEFPY(ipv6_bgp_network,
6897 ipv6_bgp_network_cmd,
6898 "[no] network X:X::X:X/M$prefix \
6899 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6900 NO_STR
6901 "Specify a network to announce via BGP\n"
6902 "IPv6 prefix\n"
6903 "Route-map to modify the attributes\n"
6904 "Name of the route map\n"
6905 "Label index to associate with the prefix\n"
6906 "Label index value\n")
37a87b8f 6907{
585f1adc
IR
6908 return bgp_static_set(
6909 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6910 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6911}
6912
d62a17ae 6913static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6914{
d62a17ae 6915 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6916}
6917
d62a17ae 6918static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6919{
365ab2e7
RZ
6920 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6921 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6922 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6923 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6924 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6925}
718e3744 6926
365ab2e7
RZ
6927/**
6928 * Helper function to avoid repeated code: prepare variables for a
6929 * `route_map_apply` call.
6930 *
6931 * \returns `true` on route map match, otherwise `false`.
6932 */
6933static bool aggr_suppress_map_test(struct bgp *bgp,
6934 struct bgp_aggregate *aggregate,
6935 struct bgp_path_info *pi)
6936{
6937 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6938 route_map_result_t rmr = RMAP_DENYMATCH;
6939 struct bgp_path_info rmap_path = {};
6940 struct attr attr = {};
6941
6942 /* No route map entries created, just don't match. */
6943 if (aggregate->suppress_map == NULL)
6944 return false;
6945
6946 /* Call route map matching and return result. */
6947 attr.aspath = aspath_empty();
6948 rmap_path.peer = bgp->peer_self;
6949 rmap_path.attr = &attr;
6950
6951 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6952 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6953 bgp->peer_self->rmap_type = 0;
6954
6955 bgp_attr_flush(&attr);
afb254d7 6956 aspath_unintern(&attr.aspath);
365ab2e7
RZ
6957
6958 return rmr == RMAP_PERMITMATCH;
6959}
6960
4056a5f6
RZ
6961/** Test whether the aggregation has suppressed this path or not. */
6962static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6963 struct bgp_path_info *pi)
6964{
6965 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6966 return false;
6967
6968 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6969}
6970
6971/**
6972 * Suppress this path and keep the reference.
6973 *
6974 * \returns `true` if needs processing otherwise `false`.
6975 */
6976static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6977 struct bgp_path_info *pi)
6978{
6979 struct bgp_path_info_extra *pie;
6980
6981 /* Path is already suppressed by this aggregation. */
6982 if (aggr_suppress_exists(aggregate, pi))
6983 return false;
6984
6985 pie = bgp_path_info_extra_get(pi);
6986
6987 /* This is the first suppression, allocate memory and list it. */
6988 if (pie->aggr_suppressors == NULL)
6989 pie->aggr_suppressors = list_new();
6990
6991 listnode_add(pie->aggr_suppressors, aggregate);
6992
6993 /* Only mark for processing if suppressed. */
6994 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6995 if (BGP_DEBUG(update, UPDATE_OUT))
6996 zlog_debug("aggregate-address suppressing: %pFX",
6997 bgp_dest_get_prefix(pi->net));
6998
4056a5f6
RZ
6999 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7000 return true;
7001 }
7002
7003 return false;
7004}
7005
7006/**
7007 * Unsuppress this path and remove the reference.
7008 *
7009 * \returns `true` if needs processing otherwise `false`.
7010 */
7011static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7012 struct bgp_path_info *pi)
7013{
7014 /* Path wasn't suppressed. */
7015 if (!aggr_suppress_exists(aggregate, pi))
7016 return false;
7017
7018 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7019
7020 /* Unsuppress and free extra memory if last item. */
7021 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7022 if (BGP_DEBUG(update, UPDATE_OUT))
7023 zlog_debug("aggregate-address unsuppressing: %pFX",
7024 bgp_dest_get_prefix(pi->net));
7025
4056a5f6
RZ
7026 list_delete(&pi->extra->aggr_suppressors);
7027 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7028 return true;
7029 }
7030
7031 return false;
7032}
7033
3dc339cd
DA
7034static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7035 struct aspath *aspath,
7036 struct community *comm,
7037 struct ecommunity *ecomm,
7038 struct lcommunity *lcomm)
eaaf8adb
DS
7039{
7040 static struct aspath *ae = NULL;
7041
7042 if (!ae)
7043 ae = aspath_empty();
7044
40381db7 7045 if (!pi)
3dc339cd 7046 return false;
eaaf8adb 7047
40381db7 7048 if (origin != pi->attr->origin)
3dc339cd 7049 return false;
eaaf8adb 7050
40381db7 7051 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7052 return false;
29f7d023 7053
9a706b42 7054 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7055 return false;
eaaf8adb 7056
b53e67a3 7057 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7058 return false;
eaaf8adb 7059
1bcf3a96 7060 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7061 return false;
dd18c5a9 7062
40381db7 7063 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7064 return false;
7ce8a8e0 7065
3dc339cd 7066 return true;
eaaf8adb
DS
7067}
7068
5f040085
DS
7069static void bgp_aggregate_install(
7070 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7071 uint8_t origin, struct aspath *aspath, struct community *community,
7072 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7073 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7074{
9bcb3eef 7075 struct bgp_dest *dest;
c701010e 7076 struct bgp_table *table;
6f94b685 7077 struct bgp_path_info *pi, *orig, *new;
20894f50 7078 struct attr *attr;
c701010e
DS
7079
7080 table = bgp->rib[afi][safi];
7081
9bcb3eef 7082 dest = bgp_node_get(table, p);
eaaf8adb 7083
9bcb3eef 7084 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7085 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7086 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7087 break;
7088
6aabb15d
RZ
7089 /*
7090 * If we have paths with different MEDs, then don't install
7091 * (or uninstall) the aggregate route.
7092 */
7093 if (aggregate->match_med && aggregate->med_mismatched)
7094 goto uninstall_aggregate_route;
7095
c701010e 7096 if (aggregate->count > 0) {
eaaf8adb
DS
7097 /*
7098 * If the aggregate information has not changed
7099 * no need to re-install it again.
7100 */
6f94b685 7101 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7102 ecommunity, lcommunity)) {
9bcb3eef 7103 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7104
7105 if (aspath)
7106 aspath_free(aspath);
7107 if (community)
3c1f53de 7108 community_free(&community);
3da2cc32
DS
7109 if (ecommunity)
7110 ecommunity_free(&ecommunity);
dd18c5a9
DS
7111 if (lcommunity)
7112 lcommunity_free(&lcommunity);
eaaf8adb
DS
7113
7114 return;
7115 }
7116
7117 /*
7118 * Mark the old as unusable
7119 */
40381db7 7120 if (pi)
9bcb3eef 7121 bgp_path_info_delete(dest, pi);
eaaf8adb 7122
20894f50
DA
7123 attr = bgp_attr_aggregate_intern(
7124 bgp, origin, aspath, community, ecommunity, lcommunity,
7125 aggregate, atomic_aggregate, p);
7126
7127 if (!attr) {
7128 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7129 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7130 zlog_debug("%s: %pFX null attribute", __func__,
7131 p);
20894f50
DA
7132 return;
7133 }
7134
3da2cc32 7135 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7136 bgp->peer_self, attr, dest);
20894f50 7137
1defdda8 7138 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7139
9bcb3eef
DS
7140 bgp_path_info_add(dest, new);
7141 bgp_process(bgp, dest, afi, safi);
c701010e 7142 } else {
6aabb15d 7143 uninstall_aggregate_route:
6f94b685 7144 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7145 if (pi->peer == bgp->peer_self
7146 && pi->type == ZEBRA_ROUTE_BGP
7147 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7148 break;
7149
7150 /* Withdraw static BGP route from routing table. */
40381db7 7151 if (pi) {
9bcb3eef
DS
7152 bgp_path_info_delete(dest, pi);
7153 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7154 }
7155 }
7156
9bcb3eef 7157 bgp_dest_unlock_node(dest);
c701010e
DS
7158}
7159
6aabb15d
RZ
7160/**
7161 * Check if the current path has different MED than other known paths.
7162 *
7163 * \returns `true` if the MED matched the others else `false`.
7164 */
7165static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7166 struct bgp *bgp, struct bgp_path_info *pi)
7167{
7168 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7169
7170 /* This is the first route being analyzed. */
7171 if (!aggregate->med_initialized) {
7172 aggregate->med_initialized = true;
7173 aggregate->med_mismatched = false;
7174 aggregate->med_matched_value = cur_med;
7175 } else {
7176 /* Check if routes with different MED showed up. */
7177 if (cur_med != aggregate->med_matched_value)
7178 aggregate->med_mismatched = true;
7179 }
7180
7181 return !aggregate->med_mismatched;
7182}
7183
7184/**
7185 * Initializes and tests all routes in the aggregate address path for MED
7186 * values.
7187 *
7188 * \returns `true` if all MEDs are the same otherwise `false`.
7189 */
7190static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7191 struct bgp *bgp, const struct prefix *p,
7192 afi_t afi, safi_t safi)
7193{
7194 struct bgp_table *table = bgp->rib[afi][safi];
7195 const struct prefix *dest_p;
7196 struct bgp_dest *dest, *top;
7197 struct bgp_path_info *pi;
7198 bool med_matched = true;
7199
7200 aggregate->med_initialized = false;
7201
7202 top = bgp_node_get(table, p);
7203 for (dest = bgp_node_get(table, p); dest;
7204 dest = bgp_route_next_until(dest, top)) {
7205 dest_p = bgp_dest_get_prefix(dest);
7206 if (dest_p->prefixlen <= p->prefixlen)
7207 continue;
7208
7209 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7210 if (BGP_PATH_HOLDDOWN(pi))
7211 continue;
7212 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7213 continue;
7214 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7215 med_matched = false;
7216 break;
7217 }
7218 }
7219 if (!med_matched)
7220 break;
7221 }
7222 bgp_dest_unlock_node(top);
7223
7224 return med_matched;
7225}
7226
7227/**
7228 * Toggles the route suppression status for this aggregate address
7229 * configuration.
7230 */
4056a5f6
RZ
7231void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7232 struct bgp *bgp, const struct prefix *p,
7233 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7234{
7235 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7236 const struct prefix *dest_p;
7237 struct bgp_dest *dest, *top;
7238 struct bgp_path_info *pi;
7239 bool toggle_suppression;
7240
7241 /* We've found a different MED we must revert any suppressed routes. */
7242 top = bgp_node_get(table, p);
7243 for (dest = bgp_node_get(table, p); dest;
7244 dest = bgp_route_next_until(dest, top)) {
7245 dest_p = bgp_dest_get_prefix(dest);
7246 if (dest_p->prefixlen <= p->prefixlen)
7247 continue;
7248
7249 toggle_suppression = false;
7250 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7251 if (BGP_PATH_HOLDDOWN(pi))
7252 continue;
7253 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7254 continue;
7255
6aabb15d
RZ
7256 /* We are toggling suppression back. */
7257 if (suppress) {
6aabb15d 7258 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7259 if (aggr_suppress_path(aggregate, pi))
7260 toggle_suppression = true;
6aabb15d
RZ
7261 continue;
7262 }
7263
6aabb15d 7264 /* Install route if there is no more suppression. */
4056a5f6 7265 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7266 toggle_suppression = true;
6aabb15d
RZ
7267 }
7268
7269 if (toggle_suppression)
7270 bgp_process(bgp, dest, afi, safi);
7271 }
7272 bgp_dest_unlock_node(top);
7273}
7274
7275/**
7276 * Aggregate address MED matching incremental test: this function is called
7277 * when the initial aggregation occurred and we are only testing a single
7278 * new path.
7279 *
7280 * In addition to testing and setting the MED validity it also installs back
7281 * suppressed routes (if summary is configured).
7282 *
7283 * Must not be called in `bgp_aggregate_route`.
7284 */
7285static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7286 struct bgp *bgp, const struct prefix *p,
7287 afi_t afi, safi_t safi,
7288 struct bgp_path_info *pi, bool is_adding)
7289{
7290 /* MED matching disabled. */
7291 if (!aggregate->match_med)
7292 return;
7293
7294 /* Aggregation with different MED, nothing to do. */
7295 if (aggregate->med_mismatched)
7296 return;
7297
7298 /*
7299 * Test the current entry:
7300 *
7301 * is_adding == true: if the new entry doesn't match then we must
7302 * install all suppressed routes.
7303 *
7304 * is_adding == false: if the entry being removed was the last
7305 * unmatching entry then we can suppress all routes.
7306 */
7307 if (!is_adding) {
7308 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7309 && aggregate->summary_only)
7310 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7311 safi, true);
7312 } else
7313 bgp_aggregate_med_match(aggregate, bgp, pi);
7314
7315 /* No mismatches, just quit. */
7316 if (!aggregate->med_mismatched)
7317 return;
7318
7319 /* Route summarization is disabled. */
7320 if (!aggregate->summary_only)
7321 return;
7322
7323 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7324}
7325
b5d58c32 7326/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7327void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7328 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7329{
7330 struct bgp_table *table;
9bcb3eef
DS
7331 struct bgp_dest *top;
7332 struct bgp_dest *dest;
d7c0a89a 7333 uint8_t origin;
d62a17ae 7334 struct aspath *aspath = NULL;
d62a17ae 7335 struct community *community = NULL;
3da2cc32 7336 struct ecommunity *ecommunity = NULL;
dd18c5a9 7337 struct lcommunity *lcommunity = NULL;
40381db7 7338 struct bgp_path_info *pi;
d62a17ae 7339 unsigned long match = 0;
d7c0a89a 7340 uint8_t atomic_aggregate = 0;
d62a17ae 7341
9f822fa2
S
7342 /* If the bgp instance is being deleted or self peer is deleted
7343 * then do not create aggregate route
7344 */
892fedb6
DA
7345 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7346 || (bgp->peer_self == NULL))
9f822fa2
S
7347 return;
7348
6aabb15d
RZ
7349 /* Initialize and test routes for MED difference. */
7350 if (aggregate->match_med)
7351 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7352
4056a5f6
RZ
7353 /*
7354 * Reset aggregate count: we might've been called from route map
7355 * update so in that case we must retest all more specific routes.
7356 *
7357 * \see `bgp_route_map_process_update`.
7358 */
7359 aggregate->count = 0;
7360 aggregate->incomplete_origin_count = 0;
7361 aggregate->incomplete_origin_count = 0;
7362 aggregate->egp_origin_count = 0;
7363
d62a17ae 7364 /* ORIGIN attribute: If at least one route among routes that are
7365 aggregated has ORIGIN with the value INCOMPLETE, then the
7366 aggregated route must have the ORIGIN attribute with the value
7367 INCOMPLETE. Otherwise, if at least one route among routes that
7368 are aggregated has ORIGIN with the value EGP, then the aggregated
7369 route must have the origin attribute with the value EGP. In all
7370 other case the value of the ORIGIN attribute of the aggregated
7371 route is INTERNAL. */
7372 origin = BGP_ORIGIN_IGP;
718e3744 7373
d62a17ae 7374 table = bgp->rib[afi][safi];
718e3744 7375
d62a17ae 7376 top = bgp_node_get(table, p);
9bcb3eef
DS
7377 for (dest = bgp_node_get(table, p); dest;
7378 dest = bgp_route_next_until(dest, top)) {
7379 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7380
9bcb3eef 7381 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7382 continue;
d62a17ae 7383
a77e2f4b
S
7384 /* If suppress fib is enabled and route not installed
7385 * in FIB, skip the route
7386 */
7387 if (!bgp_check_advertise(bgp, dest))
7388 continue;
7389
c2ff8b3e 7390 match = 0;
d62a17ae 7391
9bcb3eef 7392 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7393 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7394 continue;
718e3744 7395
40381db7 7396 if (pi->attr->flag
c2ff8b3e
DS
7397 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7398 atomic_aggregate = 1;
d62a17ae 7399
40381db7 7400 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7401 continue;
d62a17ae 7402
f273fef1
DS
7403 /*
7404 * summary-only aggregate route suppress
7405 * aggregated route announcements.
6aabb15d
RZ
7406 *
7407 * MED matching:
7408 * Don't create summaries if MED didn't match
7409 * otherwise neither the specific routes and the
7410 * aggregation will be announced.
f273fef1 7411 */
6aabb15d
RZ
7412 if (aggregate->summary_only
7413 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7414 if (aggr_suppress_path(aggregate, pi))
7415 match++;
d62a17ae 7416 }
c2ff8b3e 7417
365ab2e7
RZ
7418 /*
7419 * Suppress more specific routes that match the route
7420 * map results.
7421 *
7422 * MED matching:
7423 * Don't suppress routes if MED matching is enabled and
7424 * it mismatched otherwise we might end up with no
7425 * routes for this path.
7426 */
7427 if (aggregate->suppress_map_name
7428 && AGGREGATE_MED_VALID(aggregate)
7429 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7430 if (aggr_suppress_path(aggregate, pi))
7431 match++;
d62a17ae 7432 }
c2ff8b3e
DS
7433
7434 aggregate->count++;
7435
f273fef1
DS
7436 /*
7437 * If at least one route among routes that are
7438 * aggregated has ORIGIN with the value INCOMPLETE,
7439 * then the aggregated route MUST have the ORIGIN
7440 * attribute with the value INCOMPLETE. Otherwise, if
7441 * at least one route among routes that are aggregated
7442 * has ORIGIN with the value EGP, then the aggregated
7443 * route MUST have the ORIGIN attribute with the value
7444 * EGP.
7445 */
fc968841
NT
7446 switch (pi->attr->origin) {
7447 case BGP_ORIGIN_INCOMPLETE:
7448 aggregate->incomplete_origin_count++;
7449 break;
7450 case BGP_ORIGIN_EGP:
7451 aggregate->egp_origin_count++;
7452 break;
7453 default:
7454 /*Do nothing.
7455 */
7456 break;
7457 }
c2ff8b3e
DS
7458
7459 if (!aggregate->as_set)
7460 continue;
7461
f273fef1
DS
7462 /*
7463 * as-set aggregate route generate origin, as path,
7464 * and community aggregation.
7465 */
fc968841
NT
7466 /* Compute aggregate route's as-path.
7467 */
ef51a7d8 7468 bgp_compute_aggregate_aspath_hash(aggregate,
7469 pi->attr->aspath);
c2ff8b3e 7470
fc968841
NT
7471 /* Compute aggregate route's community.
7472 */
9a706b42 7473 if (bgp_attr_get_community(pi->attr))
21fec674 7474 bgp_compute_aggregate_community_hash(
9a706b42
DA
7475 aggregate,
7476 bgp_attr_get_community(pi->attr));
dd18c5a9 7477
fc968841
NT
7478 /* Compute aggregate route's extended community.
7479 */
b53e67a3 7480 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7481 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7482 aggregate,
7483 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7484
7485 /* Compute aggregate route's large community.
7486 */
1bcf3a96 7487 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7488 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7489 aggregate,
7490 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7491 }
c2ff8b3e 7492 if (match)
9bcb3eef 7493 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7494 }
21fec674 7495 if (aggregate->as_set) {
ef51a7d8 7496 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7497 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7498 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7499 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7500 }
7501
f1eb1f05 7502
9bcb3eef 7503 bgp_dest_unlock_node(top);
718e3744 7504
718e3744 7505
fc968841
NT
7506 if (aggregate->incomplete_origin_count > 0)
7507 origin = BGP_ORIGIN_INCOMPLETE;
7508 else if (aggregate->egp_origin_count > 0)
7509 origin = BGP_ORIGIN_EGP;
d62a17ae 7510
229757f1
DA
7511 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7512 origin = aggregate->origin;
7513
fc968841
NT
7514 if (aggregate->as_set) {
7515 if (aggregate->aspath)
7516 /* Retrieve aggregate route's as-path.
7517 */
7518 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7519
fc968841
NT
7520 if (aggregate->community)
7521 /* Retrieve aggregate route's community.
7522 */
7523 community = community_dup(aggregate->community);
3da2cc32 7524
fc968841
NT
7525 if (aggregate->ecommunity)
7526 /* Retrieve aggregate route's ecommunity.
7527 */
7528 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7529
fc968841
NT
7530 if (aggregate->lcommunity)
7531 /* Retrieve aggregate route's lcommunity.
7532 */
7533 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7534 }
718e3744 7535
c701010e 7536 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7537 ecommunity, lcommunity, atomic_aggregate,
7538 aggregate);
718e3744 7539}
7540
5f040085
DS
7541void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7542 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7543{
7544 struct bgp_table *table;
9bcb3eef
DS
7545 struct bgp_dest *top;
7546 struct bgp_dest *dest;
40381db7 7547 struct bgp_path_info *pi;
3b7db173
DS
7548 unsigned long match;
7549
7550 table = bgp->rib[afi][safi];
7551
7552 /* If routes exists below this node, generate aggregate routes. */
7553 top = bgp_node_get(table, p);
9bcb3eef
DS
7554 for (dest = bgp_node_get(table, p); dest;
7555 dest = bgp_route_next_until(dest, top)) {
7556 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7557
9bcb3eef 7558 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7559 continue;
7560 match = 0;
7561
9bcb3eef 7562 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7563 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7564 continue;
7565
40381db7 7566 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7567 continue;
7568
92b175bd
RZ
7569 /*
7570 * This route is suppressed: attempt to unsuppress it.
7571 *
7572 * `aggr_unsuppress_path` will fail if this particular
7573 * aggregate route was not the suppressor.
7574 */
7575 if (pi->extra && pi->extra->aggr_suppressors &&
7576 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7577 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7578 match++;
3b7db173 7579 }
365ab2e7 7580
3b7db173 7581 aggregate->count--;
fc968841
NT
7582
7583 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7584 aggregate->incomplete_origin_count--;
7585 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7586 aggregate->egp_origin_count--;
7587
7588 if (aggregate->as_set) {
7589 /* Remove as-path from aggregate.
7590 */
ef51a7d8 7591 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7592 aggregate,
7593 pi->attr->aspath);
7594
9a706b42 7595 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7596 /* Remove community from aggregate.
7597 */
21fec674 7598 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7599 aggregate,
7600 bgp_attr_get_community(
7601 pi->attr));
fc968841 7602
b53e67a3 7603 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7604 /* Remove ecommunity from aggregate.
7605 */
4edd83f9 7606 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7607 aggregate,
7608 bgp_attr_get_ecommunity(
7609 pi->attr));
fc968841 7610
1bcf3a96 7611 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7612 /* Remove lcommunity from aggregate.
7613 */
f1eb1f05 7614 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7615 aggregate,
7616 bgp_attr_get_lcommunity(
7617 pi->attr));
fc968841 7618 }
3b7db173
DS
7619 }
7620
7621 /* If this node was suppressed, process the change. */
7622 if (match)
9bcb3eef 7623 bgp_process(bgp, dest, afi, safi);
3b7db173 7624 }
f1eb1f05 7625 if (aggregate->as_set) {
ef51a7d8 7626 aspath_free(aggregate->aspath);
7627 aggregate->aspath = NULL;
21fec674 7628 if (aggregate->community)
7629 community_free(&aggregate->community);
4edd83f9 7630 if (aggregate->ecommunity)
7631 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7632 if (aggregate->lcommunity)
7633 lcommunity_free(&aggregate->lcommunity);
7634 }
7635
9bcb3eef 7636 bgp_dest_unlock_node(top);
3b7db173 7637}
718e3744 7638
5f040085
DS
7639static void bgp_add_route_to_aggregate(struct bgp *bgp,
7640 const struct prefix *aggr_p,
fc968841
NT
7641 struct bgp_path_info *pinew, afi_t afi,
7642 safi_t safi,
7643 struct bgp_aggregate *aggregate)
7644{
7645 uint8_t origin;
7646 struct aspath *aspath = NULL;
7647 uint8_t atomic_aggregate = 0;
7648 struct community *community = NULL;
7649 struct ecommunity *ecommunity = NULL;
7650 struct lcommunity *lcommunity = NULL;
7651
a4559740 7652 /* If the bgp instance is being deleted or self peer is deleted
7653 * then do not create aggregate route
7654 */
7655 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7656 || (bgp->peer_self == NULL))
7657 return;
7658
fc968841
NT
7659 /* ORIGIN attribute: If at least one route among routes that are
7660 * aggregated has ORIGIN with the value INCOMPLETE, then the
7661 * aggregated route must have the ORIGIN attribute with the value
7662 * INCOMPLETE. Otherwise, if at least one route among routes that
7663 * are aggregated has ORIGIN with the value EGP, then the aggregated
7664 * route must have the origin attribute with the value EGP. In all
7665 * other case the value of the ORIGIN attribute of the aggregated
7666 * route is INTERNAL.
7667 */
7668 origin = BGP_ORIGIN_IGP;
7669
7670 aggregate->count++;
7671
6aabb15d
RZ
7672 /*
7673 * This must be called before `summary` check to avoid
7674 * "suppressing" twice.
7675 */
7676 if (aggregate->match_med)
7677 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7678 pinew, true);
7679
7680 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7681 aggr_suppress_path(aggregate, pinew);
fc968841 7682
365ab2e7
RZ
7683 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7684 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7685 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7686
7687 switch (pinew->attr->origin) {
7688 case BGP_ORIGIN_INCOMPLETE:
7689 aggregate->incomplete_origin_count++;
7690 break;
7691 case BGP_ORIGIN_EGP:
7692 aggregate->egp_origin_count++;
7693 break;
7694 default:
7695 /* Do nothing.
7696 */
7697 break;
7698 }
7699
7700 if (aggregate->incomplete_origin_count > 0)
7701 origin = BGP_ORIGIN_INCOMPLETE;
7702 else if (aggregate->egp_origin_count > 0)
7703 origin = BGP_ORIGIN_EGP;
7704
229757f1
DA
7705 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7706 origin = aggregate->origin;
7707
fc968841
NT
7708 if (aggregate->as_set) {
7709 /* Compute aggregate route's as-path.
7710 */
7711 bgp_compute_aggregate_aspath(aggregate,
7712 pinew->attr->aspath);
7713
7714 /* Compute aggregate route's community.
7715 */
9a706b42 7716 if (bgp_attr_get_community(pinew->attr))
fc968841 7717 bgp_compute_aggregate_community(
9a706b42 7718 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7719
7720 /* Compute aggregate route's extended community.
7721 */
b53e67a3 7722 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7723 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7724 aggregate,
7725 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7726
7727 /* Compute aggregate route's large community.
7728 */
1bcf3a96 7729 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7730 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7731 aggregate,
7732 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7733
7734 /* Retrieve aggregate route's as-path.
7735 */
7736 if (aggregate->aspath)
7737 aspath = aspath_dup(aggregate->aspath);
7738
7739 /* Retrieve aggregate route's community.
7740 */
7741 if (aggregate->community)
7742 community = community_dup(aggregate->community);
7743
7744 /* Retrieve aggregate route's ecommunity.
7745 */
7746 if (aggregate->ecommunity)
7747 ecommunity = ecommunity_dup(aggregate->ecommunity);
7748
7749 /* Retrieve aggregate route's lcommunity.
7750 */
7751 if (aggregate->lcommunity)
7752 lcommunity = lcommunity_dup(aggregate->lcommunity);
7753 }
7754
7755 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7756 aspath, community, ecommunity,
7757 lcommunity, atomic_aggregate, aggregate);
7758}
7759
7760static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7761 safi_t safi,
7762 struct bgp_path_info *pi,
7763 struct bgp_aggregate *aggregate,
5f040085 7764 const struct prefix *aggr_p)
fc968841
NT
7765{
7766 uint8_t origin;
7767 struct aspath *aspath = NULL;
7768 uint8_t atomic_aggregate = 0;
7769 struct community *community = NULL;
7770 struct ecommunity *ecommunity = NULL;
7771 struct lcommunity *lcommunity = NULL;
7772 unsigned long match = 0;
7773
a4559740 7774 /* If the bgp instance is being deleted or self peer is deleted
7775 * then do not create aggregate route
7776 */
7777 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7778 || (bgp->peer_self == NULL))
7779 return;
7780
fc968841
NT
7781 if (BGP_PATH_HOLDDOWN(pi))
7782 return;
7783
7784 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7785 return;
7786
4056a5f6
RZ
7787 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7788 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7789 match++;
fc968841 7790
365ab2e7 7791 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7792 && aggr_suppress_map_test(bgp, aggregate, pi))
7793 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7794 match++;
fc968841 7795
6aabb15d 7796 /*
365ab2e7 7797 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7798 * "unsuppressing" twice.
7799 */
7800 if (aggregate->match_med)
7801 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7802 true);
7803
fc968841
NT
7804 if (aggregate->count > 0)
7805 aggregate->count--;
7806
7807 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7808 aggregate->incomplete_origin_count--;
7809 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7810 aggregate->egp_origin_count--;
7811
7812 if (aggregate->as_set) {
7813 /* Remove as-path from aggregate.
7814 */
7815 bgp_remove_aspath_from_aggregate(aggregate,
7816 pi->attr->aspath);
7817
9a706b42 7818 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7819 /* Remove community from aggregate.
7820 */
7821 bgp_remove_community_from_aggregate(
9a706b42 7822 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7823
b53e67a3 7824 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7825 /* Remove ecommunity from aggregate.
7826 */
7827 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7828 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7829
1bcf3a96 7830 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7831 /* Remove lcommunity from aggregate.
7832 */
7833 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7834 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7835 }
7836
7837 /* If this node was suppressed, process the change. */
7838 if (match)
7839 bgp_process(bgp, pi->net, afi, safi);
7840
7841 origin = BGP_ORIGIN_IGP;
7842 if (aggregate->incomplete_origin_count > 0)
7843 origin = BGP_ORIGIN_INCOMPLETE;
7844 else if (aggregate->egp_origin_count > 0)
7845 origin = BGP_ORIGIN_EGP;
7846
229757f1
DA
7847 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7848 origin = aggregate->origin;
7849
fc968841
NT
7850 if (aggregate->as_set) {
7851 /* Retrieve aggregate route's as-path.
7852 */
7853 if (aggregate->aspath)
7854 aspath = aspath_dup(aggregate->aspath);
7855
7856 /* Retrieve aggregate route's community.
7857 */
7858 if (aggregate->community)
7859 community = community_dup(aggregate->community);
7860
7861 /* Retrieve aggregate route's ecommunity.
7862 */
7863 if (aggregate->ecommunity)
7864 ecommunity = ecommunity_dup(aggregate->ecommunity);
7865
7866 /* Retrieve aggregate route's lcommunity.
7867 */
7868 if (aggregate->lcommunity)
7869 lcommunity = lcommunity_dup(aggregate->lcommunity);
7870 }
7871
7872 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7873 aspath, community, ecommunity,
7874 lcommunity, atomic_aggregate, aggregate);
7875}
7876
5a1ae2c2 7877void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7878 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7879{
9bcb3eef
DS
7880 struct bgp_dest *child;
7881 struct bgp_dest *dest;
d62a17ae 7882 struct bgp_aggregate *aggregate;
7883 struct bgp_table *table;
718e3744 7884
d62a17ae 7885 table = bgp->aggregate[afi][safi];
f018db83 7886
d62a17ae 7887 /* No aggregates configured. */
7888 if (bgp_table_top_nolock(table) == NULL)
7889 return;
f018db83 7890
d62a17ae 7891 if (p->prefixlen == 0)
7892 return;
718e3744 7893
40381db7 7894 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7895 return;
718e3744 7896
a77e2f4b
S
7897 /* If suppress fib is enabled and route not installed
7898 * in FIB, do not update the aggregate route
7899 */
7900 if (!bgp_check_advertise(bgp, pi->net))
7901 return;
7902
d62a17ae 7903 child = bgp_node_get(table, p);
718e3744 7904
d62a17ae 7905 /* Aggregate address configuration check. */
9bcb3eef
DS
7906 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7907 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7908
9bcb3eef
DS
7909 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7910 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7911 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7912 aggregate);
d62a17ae 7913 }
b1e62edd 7914 }
9bcb3eef 7915 bgp_dest_unlock_node(child);
718e3744 7916}
7917
5a1ae2c2 7918void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7919 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7920{
9bcb3eef
DS
7921 struct bgp_dest *child;
7922 struct bgp_dest *dest;
d62a17ae 7923 struct bgp_aggregate *aggregate;
7924 struct bgp_table *table;
718e3744 7925
d62a17ae 7926 table = bgp->aggregate[afi][safi];
718e3744 7927
d62a17ae 7928 /* No aggregates configured. */
7929 if (bgp_table_top_nolock(table) == NULL)
7930 return;
718e3744 7931
d62a17ae 7932 if (p->prefixlen == 0)
7933 return;
718e3744 7934
d62a17ae 7935 child = bgp_node_get(table, p);
718e3744 7936
d62a17ae 7937 /* Aggregate address configuration check. */
9bcb3eef
DS
7938 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7939 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7940
9bcb3eef
DS
7941 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7942 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7943 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7944 aggregate, dest_p);
d62a17ae 7945 }
b1e62edd 7946 }
9bcb3eef 7947 bgp_dest_unlock_node(child);
d62a17ae 7948}
718e3744 7949
718e3744 7950/* Aggregate route attribute. */
7951#define AGGREGATE_SUMMARY_ONLY 1
7952#define AGGREGATE_AS_SET 1
fb29348a 7953#define AGGREGATE_AS_UNSET 0
718e3744 7954
229757f1
DA
7955static const char *bgp_origin2str(uint8_t origin)
7956{
7957 switch (origin) {
7958 case BGP_ORIGIN_IGP:
7959 return "igp";
7960 case BGP_ORIGIN_EGP:
7961 return "egp";
7962 case BGP_ORIGIN_INCOMPLETE:
7963 return "incomplete";
7964 }
7965 return "n/a";
7966}
7967
fdeb5a81 7968static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7969{
7970 switch (v_state) {
fdeb5a81
DS
7971 case RPKI_NOT_BEING_USED:
7972 return "not used";
7973 case RPKI_VALID:
b5b99af8 7974 return "valid";
fdeb5a81 7975 case RPKI_NOTFOUND:
b5b99af8 7976 return "not found";
fdeb5a81 7977 case RPKI_INVALID:
b5b99af8 7978 return "invalid";
b5b99af8 7979 }
fdeb5a81
DS
7980
7981 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7982 return "ERROR";
7983}
7984
585f1adc
IR
7985static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7986 afi_t afi, safi_t safi)
718e3744 7987{
585f1adc
IR
7988 VTY_DECLVAR_CONTEXT(bgp, bgp);
7989 int ret;
7990 struct prefix p;
9bcb3eef 7991 struct bgp_dest *dest;
d62a17ae 7992 struct bgp_aggregate *aggregate;
718e3744 7993
585f1adc
IR
7994 /* Convert string to prefix structure. */
7995 ret = str2prefix(prefix_str, &p);
7996 if (!ret) {
7997 vty_out(vty, "Malformed prefix\n");
7998 return CMD_WARNING_CONFIG_FAILED;
7999 }
8000 apply_mask(&p);
a4559740 8001
d62a17ae 8002 /* Old configuration check. */
585f1adc 8003 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8004 if (!dest) {
585f1adc
IR
8005 vty_out(vty,
8006 "%% There is no aggregate-address configuration.\n");
8007 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8008 }
f6269b4f 8009
9bcb3eef 8010 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8011 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8012 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8013 NULL, NULL, 0, aggregate);
d62a17ae 8014
8015 /* Unlock aggregate address configuration. */
9bcb3eef 8016 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8017
8018 if (aggregate->community)
8019 community_free(&aggregate->community);
8020
8021 if (aggregate->community_hash) {
8022 /* Delete all communities in the hash.
8023 */
8024 hash_clean(aggregate->community_hash,
8025 bgp_aggr_community_remove);
8026 /* Free up the community_hash.
8027 */
8028 hash_free(aggregate->community_hash);
8029 }
8030
8031 if (aggregate->ecommunity)
8032 ecommunity_free(&aggregate->ecommunity);
8033
8034 if (aggregate->ecommunity_hash) {
8035 /* Delete all ecommunities in the hash.
8036 */
8037 hash_clean(aggregate->ecommunity_hash,
8038 bgp_aggr_ecommunity_remove);
8039 /* Free up the ecommunity_hash.
8040 */
8041 hash_free(aggregate->ecommunity_hash);
8042 }
8043
8044 if (aggregate->lcommunity)
8045 lcommunity_free(&aggregate->lcommunity);
8046
8047 if (aggregate->lcommunity_hash) {
8048 /* Delete all lcommunities in the hash.
8049 */
8050 hash_clean(aggregate->lcommunity_hash,
8051 bgp_aggr_lcommunity_remove);
8052 /* Free up the lcommunity_hash.
8053 */
8054 hash_free(aggregate->lcommunity_hash);
8055 }
8056
8057 if (aggregate->aspath)
8058 aspath_free(aggregate->aspath);
8059
8060 if (aggregate->aspath_hash) {
8061 /* Delete all as-paths in the hash.
8062 */
8063 hash_clean(aggregate->aspath_hash,
8064 bgp_aggr_aspath_remove);
8065 /* Free up the aspath_hash.
8066 */
8067 hash_free(aggregate->aspath_hash);
8068 }
8069
d62a17ae 8070 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8071 bgp_dest_unlock_node(dest);
8072 bgp_dest_unlock_node(dest);
d62a17ae 8073
585f1adc 8074 return CMD_SUCCESS;
d62a17ae 8075}
8076
585f1adc
IR
8077static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8078 safi_t safi, const char *rmap,
8079 uint8_t summary_only, uint8_t as_set,
8080 uint8_t origin, bool match_med,
8081 const char *suppress_map)
d62a17ae 8082{
585f1adc 8083 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8084 int ret;
585f1adc 8085 struct prefix p;
9bcb3eef 8086 struct bgp_dest *dest;
d62a17ae 8087 struct bgp_aggregate *aggregate;
fb29348a 8088 uint8_t as_set_new = as_set;
d62a17ae 8089
365ab2e7 8090 if (suppress_map && summary_only) {
585f1adc 8091 vty_out(vty,
365ab2e7 8092 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8093 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8094 }
8095
585f1adc
IR
8096 /* Convert string to prefix structure. */
8097 ret = str2prefix(prefix_str, &p);
8098 if (!ret) {
8099 vty_out(vty, "Malformed prefix\n");
8100 return CMD_WARNING_CONFIG_FAILED;
8101 }
8102 apply_mask(&p);
d62a17ae 8103
585f1adc
IR
8104 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8105 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8106 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8107 prefix_str);
8108 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8109 }
8110
d62a17ae 8111 /* Old configuration check. */
585f1adc 8112 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8113 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8114
20894f50 8115 if (aggregate) {
585f1adc 8116 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8117 /* try to remove the old entry */
585f1adc 8118 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8119 if (ret) {
585f1adc 8120 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8121 bgp_dest_unlock_node(dest);
585f1adc 8122 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8123 }
8124 }
718e3744 8125
d62a17ae 8126 /* Make aggregate address structure. */
8127 aggregate = bgp_aggregate_new();
8128 aggregate->summary_only = summary_only;
6aabb15d 8129 aggregate->match_med = match_med;
fb29348a
DA
8130
8131 /* Network operators MUST NOT locally generate any new
8132 * announcements containing AS_SET or AS_CONFED_SET. If they have
8133 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8134 * SHOULD withdraw those routes and re-announce routes for the
8135 * aggregate or component prefixes (i.e., the more-specific routes
8136 * subsumed by the previously aggregated route) without AS_SET
8137 * or AS_CONFED_SET in the updates.
8138 */
7f972cd8 8139 if (bgp->reject_as_sets) {
fb29348a
DA
8140 if (as_set == AGGREGATE_AS_SET) {
8141 as_set_new = AGGREGATE_AS_UNSET;
8142 zlog_warn(
63efca0e 8143 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8144 __func__);
585f1adc 8145 vty_out(vty,
fb29348a
DA
8146 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8147 }
8148 }
8149
8150 aggregate->as_set = as_set_new;
d62a17ae 8151 aggregate->safi = safi;
229757f1
DA
8152 /* Override ORIGIN attribute if defined.
8153 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8154 * to IGP which is not what rfc4271 says.
8155 * This enables the same behavior, optionally.
8156 */
8157 aggregate->origin = origin;
20894f50
DA
8158
8159 if (rmap) {
8160 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8161 route_map_counter_decrement(aggregate->rmap.map);
8162 aggregate->rmap.name =
8163 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8164 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8165 route_map_counter_increment(aggregate->rmap.map);
8166 }
365ab2e7
RZ
8167
8168 if (suppress_map) {
8169 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8170 route_map_counter_decrement(aggregate->suppress_map);
8171
8172 aggregate->suppress_map_name =
8173 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8174 aggregate->suppress_map =
8175 route_map_lookup_by_name(aggregate->suppress_map_name);
8176 route_map_counter_increment(aggregate->suppress_map);
8177 }
8178
9bcb3eef 8179 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8180
d62a17ae 8181 /* Aggregate address insert into BGP routing table. */
585f1adc 8182 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8183
585f1adc 8184 return CMD_SUCCESS;
718e3744 8185}
8186
585f1adc
IR
8187DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8188 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8189 "as-set$as_set_s"
8190 "|summary-only$summary_only"
cacba915 8191 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8192 "|origin <egp|igp|incomplete>$origin_s"
8193 "|matching-MED-only$match_med"
cacba915 8194 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8195 "}]",
8196 NO_STR
8197 "Configure BGP aggregate entries\n"
764402fe
DA
8198 "Aggregate prefix\n"
8199 "Aggregate address\n"
8200 "Aggregate mask\n"
585f1adc
IR
8201 "Generate AS set path information\n"
8202 "Filter more specific routes from updates\n"
8203 "Apply route map to aggregate network\n"
8204 "Route map name\n"
8205 "BGP origin code\n"
8206 "Remote EGP\n"
8207 "Local IGP\n"
8208 "Unknown heritage\n"
8209 "Only aggregate routes with matching MED\n"
8210 "Suppress the selected more specific routes\n"
8211 "Route map with the route selectors\n")
8212{
8213 const char *prefix_s = NULL;
554b3b10 8214 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8215 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8216 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8217 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8218
554b3b10 8219 if (addr_str) {
7533cad7
QY
8220 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8221 sizeof(prefix_buf))
554b3b10
RZ
8222 == 0) {
8223 vty_out(vty, "%% Inconsistent address and mask\n");
8224 return CMD_WARNING_CONFIG_FAILED;
8225 }
585f1adc
IR
8226 prefix_s = prefix_buf;
8227 } else
8228 prefix_s = prefix_str;
37a87b8f 8229
585f1adc
IR
8230 if (origin_s) {
8231 if (strcmp(origin_s, "egp") == 0)
8232 origin = BGP_ORIGIN_EGP;
8233 else if (strcmp(origin_s, "igp") == 0)
8234 origin = BGP_ORIGIN_IGP;
8235 else if (strcmp(origin_s, "incomplete") == 0)
8236 origin = BGP_ORIGIN_INCOMPLETE;
8237 }
90e21f35 8238
585f1adc
IR
8239 if (as_set_s)
8240 as_set = AGGREGATE_AS_SET;
554b3b10 8241
585f1adc 8242 /* Handle configuration removal, otherwise installation. */
554b3b10 8243 if (no)
585f1adc
IR
8244 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8245
8246 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8247 summary_only != NULL, as_set, origin,
8248 match_med != NULL, suppress_map);
8249}
8250
8251DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8252 "[no] aggregate-address X:X::X:X/M$prefix [{"
8253 "as-set$as_set_s"
8254 "|summary-only$summary_only"
cacba915 8255 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8256 "|origin <egp|igp|incomplete>$origin_s"
8257 "|matching-MED-only$match_med"
cacba915 8258 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8259 "}]",
8260 NO_STR
8261 "Configure BGP aggregate entries\n"
8262 "Aggregate prefix\n"
8263 "Generate AS set path information\n"
8264 "Filter more specific routes from updates\n"
8265 "Apply route map to aggregate network\n"
8266 "Route map name\n"
8267 "BGP origin code\n"
8268 "Remote EGP\n"
8269 "Local IGP\n"
8270 "Unknown heritage\n"
8271 "Only aggregate routes with matching MED\n"
8272 "Suppress the selected more specific routes\n"
8273 "Route map with the route selectors\n")
8274{
8275 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8276 int as_set = AGGREGATE_AS_UNSET;
8277
8278 if (origin_s) {
8279 if (strcmp(origin_s, "egp") == 0)
8280 origin = BGP_ORIGIN_EGP;
8281 else if (strcmp(origin_s, "igp") == 0)
8282 origin = BGP_ORIGIN_IGP;
8283 else if (strcmp(origin_s, "incomplete") == 0)
8284 origin = BGP_ORIGIN_INCOMPLETE;
8285 }
8286
8287 if (as_set_s)
8288 as_set = AGGREGATE_AS_SET;
8289
8290 /* Handle configuration removal, otherwise installation. */
554b3b10 8291 if (no)
585f1adc
IR
8292 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8293 SAFI_UNICAST);
554b3b10 8294
585f1adc
IR
8295 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8296 rmap_name, summary_only != NULL, as_set,
8297 origin, match_med != NULL, suppress_map);
718e3744 8298}
8299
718e3744 8300/* Redistribute route treatment. */
d62a17ae 8301void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8302 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8303 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8304 enum blackhole_type bhtype, uint32_t metric,
8305 uint8_t type, unsigned short instance,
8306 route_tag_t tag)
d62a17ae 8307{
4b7e6066 8308 struct bgp_path_info *new;
40381db7
DS
8309 struct bgp_path_info *bpi;
8310 struct bgp_path_info rmap_path;
9bcb3eef 8311 struct bgp_dest *bn;
d62a17ae 8312 struct attr attr;
8313 struct attr *new_attr;
8314 afi_t afi;
b68885f9 8315 route_map_result_t ret;
d62a17ae 8316 struct bgp_redist *red;
8317
8318 /* Make default attribute. */
8319 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8320 /*
8321 * This must not be NULL to satisfy Coverity SA
8322 */
8323 assert(attr.aspath);
9de1f7ff 8324
a4d82a8a 8325 switch (nhtype) {
9de1f7ff
DS
8326 case NEXTHOP_TYPE_IFINDEX:
8327 break;
8328 case NEXTHOP_TYPE_IPV4:
8329 case NEXTHOP_TYPE_IPV4_IFINDEX:
8330 attr.nexthop = nexthop->ipv4;
8331 break;
8332 case NEXTHOP_TYPE_IPV6:
8333 case NEXTHOP_TYPE_IPV6_IFINDEX:
8334 attr.mp_nexthop_global = nexthop->ipv6;
8335 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8336 break;
8337 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8338 switch (p->family) {
8339 case AF_INET:
9de1f7ff 8340 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8341 break;
8342 case AF_INET6:
9de1f7ff
DS
8343 memset(&attr.mp_nexthop_global, 0,
8344 sizeof(attr.mp_nexthop_global));
74489921 8345 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8346 break;
74489921 8347 }
0789eb69 8348 attr.bh_type = bhtype;
9de1f7ff 8349 break;
d62a17ae 8350 }
0789eb69 8351 attr.nh_type = nhtype;
74489921 8352 attr.nh_ifindex = ifindex;
f04a80a5 8353
d62a17ae 8354 attr.med = metric;
957f74c3 8355 attr.distance = distance;
d62a17ae 8356 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8357 attr.tag = tag;
718e3744 8358
d62a17ae 8359 afi = family2afi(p->family);
6aeb9e78 8360
d62a17ae 8361 red = bgp_redist_lookup(bgp, afi, type, instance);
8362 if (red) {
8363 struct attr attr_new;
718e3744 8364
d62a17ae 8365 /* Copy attribute for modification. */
6f4f49b2 8366 attr_new = attr;
718e3744 8367
d62a17ae 8368 if (red->redist_metric_flag)
8369 attr_new.med = red->redist_metric;
718e3744 8370
d62a17ae 8371 /* Apply route-map. */
8372 if (red->rmap.name) {
6006b807 8373 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8374 rmap_path.peer = bgp->peer_self;
8375 rmap_path.attr = &attr_new;
718e3744 8376
d62a17ae 8377 SET_FLAG(bgp->peer_self->rmap_type,
8378 PEER_RMAP_TYPE_REDISTRIBUTE);
8379
1782514f 8380 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8381
8382 bgp->peer_self->rmap_type = 0;
8383
8384 if (ret == RMAP_DENYMATCH) {
8385 /* Free uninterned attribute. */
8386 bgp_attr_flush(&attr_new);
8387
8388 /* Unintern original. */
8389 aspath_unintern(&attr.aspath);
8390 bgp_redistribute_delete(bgp, p, type, instance);
8391 return;
8392 }
8393 }
8394
637e5ba4 8395 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8396 bgp_attr_add_gshut_community(&attr_new);
8397
d62a17ae 8398 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8399 SAFI_UNICAST, p, NULL);
8400
8401 new_attr = bgp_attr_intern(&attr_new);
8402
9bcb3eef 8403 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8404 if (bpi->peer == bgp->peer_self
8405 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8406 break;
8407
40381db7 8408 if (bpi) {
d62a17ae 8409 /* Ensure the (source route) type is updated. */
40381db7
DS
8410 bpi->type = type;
8411 if (attrhash_cmp(bpi->attr, new_attr)
8412 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8413 bgp_attr_unintern(&new_attr);
8414 aspath_unintern(&attr.aspath);
9bcb3eef 8415 bgp_dest_unlock_node(bn);
d62a17ae 8416 return;
8417 } else {
8418 /* The attribute is changed. */
40381db7 8419 bgp_path_info_set_flag(bn, bpi,
18ee8310 8420 BGP_PATH_ATTR_CHANGED);
d62a17ae 8421
8422 /* Rewrite BGP route information. */
40381db7
DS
8423 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8424 bgp_path_info_restore(bn, bpi);
d62a17ae 8425 else
40381db7
DS
8426 bgp_aggregate_decrement(
8427 bgp, p, bpi, afi, SAFI_UNICAST);
8428 bgp_attr_unintern(&bpi->attr);
8429 bpi->attr = new_attr;
8430 bpi->uptime = bgp_clock();
d62a17ae 8431
8432 /* Process change. */
40381db7 8433 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8434 SAFI_UNICAST);
8435 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8436 bgp_dest_unlock_node(bn);
d62a17ae 8437 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8438
8439 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8440 || (bgp->inst_type
8441 == BGP_INSTANCE_TYPE_DEFAULT)) {
8442
8443 vpn_leak_from_vrf_update(
40381db7 8444 bgp_get_default(), bgp, bpi);
ddb5b488 8445 }
d62a17ae 8446 return;
8447 }
8448 }
8449
8450 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8451 bgp->peer_self, new_attr, bn);
1defdda8 8452 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8453
8454 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8455 bgp_path_info_add(bn, new);
9bcb3eef 8456 bgp_dest_unlock_node(bn);
be785e35 8457 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8458 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8459
8460 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8461 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8462
8463 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8464 }
d62a17ae 8465 }
8466
8467 /* Unintern original. */
8468 aspath_unintern(&attr.aspath);
718e3744 8469}
8470
d7c0a89a
QY
8471void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8472 unsigned short instance)
718e3744 8473{
d62a17ae 8474 afi_t afi;
9bcb3eef 8475 struct bgp_dest *dest;
40381db7 8476 struct bgp_path_info *pi;
d62a17ae 8477 struct bgp_redist *red;
718e3744 8478
d62a17ae 8479 afi = family2afi(p->family);
718e3744 8480
d62a17ae 8481 red = bgp_redist_lookup(bgp, afi, type, instance);
8482 if (red) {
9bcb3eef
DS
8483 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8484 SAFI_UNICAST, p, NULL);
d62a17ae 8485
9bcb3eef 8486 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8487 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8488 break;
8489
40381db7 8490 if (pi) {
ddb5b488
PZ
8491 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8492 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8493
8494 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8495 bgp, pi);
ddb5b488 8496 }
40381db7 8497 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8498 bgp_path_info_delete(dest, pi);
8499 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8500 }
9bcb3eef 8501 bgp_dest_unlock_node(dest);
d62a17ae 8502 }
8503}
8504
8505/* Withdraw specified route type's route. */
8506void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8507 unsigned short instance)
d62a17ae 8508{
9bcb3eef 8509 struct bgp_dest *dest;
40381db7 8510 struct bgp_path_info *pi;
d62a17ae 8511 struct bgp_table *table;
8512
8513 table = bgp->rib[afi][SAFI_UNICAST];
8514
9bcb3eef
DS
8515 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8516 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8517 if (pi->peer == bgp->peer_self && pi->type == type
8518 && pi->instance == instance)
d62a17ae 8519 break;
8520
40381db7 8521 if (pi) {
ddb5b488
PZ
8522 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8523 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8524
8525 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8526 bgp, pi);
ddb5b488 8527 }
9bcb3eef 8528 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8529 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8530 bgp_path_info_delete(dest, pi);
8531 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8532 }
718e3744 8533 }
718e3744 8534}
6b0655a2 8535
718e3744 8536/* Static function to display route. */
7d3cae70
DA
8537static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8538 struct vty *vty, json_object *json, bool wide)
718e3744 8539{
be054588 8540 int len = 0;
d62a17ae 8541 char buf[BUFSIZ];
718e3744 8542
d62a17ae 8543 if (p->family == AF_INET) {
c6462ff4 8544 if (!json) {
8228a9a7 8545 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8546 } else {
8547 json_object_string_add(json, "prefix",
8548 inet_ntop(p->family,
8549 &p->u.prefix, buf,
8550 BUFSIZ));
8551 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8552 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8553 json_object_int_add(json, "version", dest->version);
c6462ff4 8554 }
d62a17ae 8555 } else if (p->family == AF_ETHERNET) {
8228a9a7 8556 len = vty_out(vty, "%pFX", p);
b03b8898 8557 } else if (p->family == AF_EVPN) {
57f7feb6 8558 if (!json)
2dbe669b 8559 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8560 else
60466a63 8561 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8562 } else if (p->family == AF_FLOWSPEC) {
8563 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8564 json ?
8565 NLRI_STRING_FORMAT_JSON_SIMPLE :
8566 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8567 } else {
c6462ff4 8568 if (!json)
8228a9a7 8569 len = vty_out(vty, "%pFX", p);
50e05855
AD
8570 else {
8571 json_object_string_add(json, "prefix",
8572 inet_ntop(p->family,
8573 &p->u.prefix, buf,
8574 BUFSIZ));
8575 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8576 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8577 json_object_int_add(json, "version", dest->version);
37d4e0df 8578 }
9c92b5f7 8579 }
d62a17ae 8580
9c92b5f7 8581 if (!json) {
ae248832 8582 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8583 if (len < 1)
8584 vty_out(vty, "\n%*s", 20, " ");
8585 else
8586 vty_out(vty, "%*s", len, " ");
8587 }
718e3744 8588}
8589
d62a17ae 8590enum bgp_display_type {
8591 normal_list,
718e3744 8592};
8593
1d7260a1 8594const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8595{
8596 switch (reason) {
8597 case bgp_path_selection_none:
8598 return "Nothing to Select";
8599 case bgp_path_selection_first:
8600 return "First path received";
8601 case bgp_path_selection_evpn_sticky_mac:
8602 return "EVPN Sticky Mac";
8603 case bgp_path_selection_evpn_seq:
8604 return "EVPN sequence number";
8605 case bgp_path_selection_evpn_lower_ip:
8606 return "EVPN lower IP";
8607 case bgp_path_selection_evpn_local_path:
8608 return "EVPN local ES path";
8609 case bgp_path_selection_evpn_non_proxy:
8610 return "EVPN non proxy";
8611 case bgp_path_selection_weight:
8612 return "Weight";
8613 case bgp_path_selection_local_pref:
8614 return "Local Pref";
8615 case bgp_path_selection_local_route:
8616 return "Local Route";
8617 case bgp_path_selection_confed_as_path:
8618 return "Confederation based AS Path";
8619 case bgp_path_selection_as_path:
8620 return "AS Path";
8621 case bgp_path_selection_origin:
8622 return "Origin";
8623 case bgp_path_selection_med:
8624 return "MED";
8625 case bgp_path_selection_peer:
8626 return "Peer Type";
8627 case bgp_path_selection_confed:
8628 return "Confed Peer Type";
8629 case bgp_path_selection_igp_metric:
8630 return "IGP Metric";
8631 case bgp_path_selection_older:
8632 return "Older Path";
8633 case bgp_path_selection_router_id:
8634 return "Router ID";
8635 case bgp_path_selection_cluster_length:
bcab253c 8636 return "Cluster length";
bbb46eb5
DA
8637 case bgp_path_selection_stale:
8638 return "Path Staleness";
8639 case bgp_path_selection_local_configured:
8640 return "Locally configured route";
8641 case bgp_path_selection_neighbor_ip:
8642 return "Neighbor IP";
8643 case bgp_path_selection_default:
8644 return "Nothing left to compare";
8645 }
8646 return "Invalid (internal error)";
8647}
8648
18ee8310 8649/* Print the short form route status for a bgp_path_info */
4b7e6066 8650static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8651 struct bgp_path_info *path,
82c298be 8652 const struct prefix *p,
d62a17ae 8653 json_object *json_path)
718e3744 8654{
82c298be
DA
8655 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8656
d62a17ae 8657 if (json_path) {
b05a1c8b 8658
d62a17ae 8659 /* Route status display. */
9b6d8fcf 8660 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8661 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8662
9b6d8fcf 8663 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8664 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8665
4056a5f6 8666 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8667 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8668
9b6d8fcf
DS
8669 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8670 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8671 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8672
d62a17ae 8673 /* Selected */
9b6d8fcf 8674 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8675 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8676
9b6d8fcf 8677 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8678 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8679
bbb46eb5 8680 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8681 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8682 json_object_string_add(json_path, "selectionReason",
8683 bgp_path_selection_reason2str(
8684 path->net->reason));
8685 }
b05a1c8b 8686
9b6d8fcf 8687 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8688 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8689
d62a17ae 8690 /* Internal route. */
9b6d8fcf
DS
8691 if ((path->peer->as)
8692 && (path->peer->as == path->peer->local_as))
d62a17ae 8693 json_object_string_add(json_path, "pathFrom",
8694 "internal");
8695 else
8696 json_object_string_add(json_path, "pathFrom",
8697 "external");
b05a1c8b 8698
d62a17ae 8699 return;
8700 }
b05a1c8b 8701
82c298be
DA
8702 /* RPKI validation state */
8703 rpki_state =
8704 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8705
8706 if (rpki_state == RPKI_VALID)
8707 vty_out(vty, "V");
8708 else if (rpki_state == RPKI_INVALID)
8709 vty_out(vty, "I");
8710 else if (rpki_state == RPKI_NOTFOUND)
8711 vty_out(vty, "N");
8712
d62a17ae 8713 /* Route status display. */
9b6d8fcf 8714 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8715 vty_out(vty, "R");
9b6d8fcf 8716 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8717 vty_out(vty, "S");
4056a5f6 8718 else if (bgp_path_suppressed(path))
d62a17ae 8719 vty_out(vty, "s");
9b6d8fcf
DS
8720 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8721 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8722 vty_out(vty, "*");
8723 else
8724 vty_out(vty, " ");
8725
8726 /* Selected */
9b6d8fcf 8727 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8728 vty_out(vty, "h");
9b6d8fcf 8729 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8730 vty_out(vty, "d");
9b6d8fcf 8731 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8732 vty_out(vty, ">");
9b6d8fcf 8733 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8734 vty_out(vty, "=");
8735 else
8736 vty_out(vty, " ");
718e3744 8737
d62a17ae 8738 /* Internal route. */
9b6d8fcf
DS
8739 if (path->peer && (path->peer->as)
8740 && (path->peer->as == path->peer->local_as))
d62a17ae 8741 vty_out(vty, "i");
8742 else
8743 vty_out(vty, " ");
b40d939b 8744}
8745
2ba93fd6
DA
8746static char *bgp_nexthop_hostname(struct peer *peer,
8747 struct bgp_nexthop_cache *bnc)
25b5da8d 8748{
892fedb6 8749 if (peer->hostname
aef999a2 8750 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8751 return peer->hostname;
8752 return NULL;
8753}
8754
b40d939b 8755/* called from terminal list command */
bd494ec5 8756void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8757 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8758 json_object *json_paths, bool wide)
d62a17ae 8759{
aef999a2 8760 int len;
515c2602 8761 struct attr *attr = path->attr;
d62a17ae 8762 json_object *json_path = NULL;
8763 json_object *json_nexthops = NULL;
8764 json_object *json_nexthop_global = NULL;
8765 json_object *json_nexthop_ll = NULL;
6f214dd3 8766 json_object *json_ext_community = NULL;
9df8b37c 8767 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8768 bool nexthop_self =
9b6d8fcf 8769 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8770 bool nexthop_othervrf = false;
43089216 8771 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8772 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8773 char *nexthop_hostname =
8774 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8775 char esi_buf[ESI_STR_LEN];
d62a17ae 8776
8777 if (json_paths)
8778 json_path = json_object_new_object();
8779
8780 /* short status lead text */
82c298be 8781 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8782
8783 if (!json_paths) {
8784 /* print prefix and mask */
8785 if (!display)
7d3cae70 8786 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8787 else
ae248832 8788 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8789 } else {
7d3cae70 8790 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8791 }
47fc97cc 8792
9df8b37c
PZ
8793 /*
8794 * If vrf id of nexthop is different from that of prefix,
8795 * set up printable string to append
8796 */
9b6d8fcf 8797 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8798 const char *self = "";
8799
8800 if (nexthop_self)
8801 self = "<";
8802
8803 nexthop_othervrf = true;
9b6d8fcf 8804 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8805
9b6d8fcf 8806 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8807 snprintf(vrf_id_str, sizeof(vrf_id_str),
8808 "@%s%s", VRFID_NONE_STR, self);
8809 else
8810 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8811 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8812
9b6d8fcf
DS
8813 if (path->extra->bgp_orig->inst_type
8814 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8815
9b6d8fcf 8816 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8817 } else {
8818 const char *self = "";
8819
8820 if (nexthop_self)
8821 self = "<";
8822
8823 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8824 }
8825
445c2480
DS
8826 /*
8827 * For ENCAP and EVPN routes, nexthop address family is not
8828 * neccessarily the same as the prefix address family.
8829 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8830 * EVPN routes are also exchanged with a MP nexthop. Currently,
8831 * this
8832 * is only IPv4, the value will be present in either
8833 * attr->nexthop or
8834 * attr->mp_nexthop_global_in
8835 */
8836 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8837 char buf[BUFSIZ];
8838 char nexthop[128];
8839 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8840
8841 switch (af) {
8842 case AF_INET:
772270f3
QY
8843 snprintf(nexthop, sizeof(nexthop), "%s",
8844 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8845 BUFSIZ));
445c2480
DS
8846 break;
8847 case AF_INET6:
772270f3
QY
8848 snprintf(nexthop, sizeof(nexthop), "%s",
8849 inet_ntop(af, &attr->mp_nexthop_global, buf,
8850 BUFSIZ));
445c2480
DS
8851 break;
8852 default:
772270f3 8853 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8854 break;
d62a17ae 8855 }
d62a17ae 8856
445c2480
DS
8857 if (json_paths) {
8858 json_nexthop_global = json_object_new_object();
8859
515c2602
DA
8860 json_object_string_add(json_nexthop_global, "ip",
8861 nexthop);
8862
939a97f4 8863 if (path->peer->hostname)
515c2602
DA
8864 json_object_string_add(json_nexthop_global,
8865 "hostname",
939a97f4 8866 path->peer->hostname);
515c2602
DA
8867
8868 json_object_string_add(json_nexthop_global, "afi",
8869 (af == AF_INET) ? "ipv4"
8870 : "ipv6");
445c2480
DS
8871 json_object_boolean_true_add(json_nexthop_global,
8872 "used");
aef999a2
DA
8873 } else {
8874 if (nexthop_hostname)
8875 len = vty_out(vty, "%s(%s)%s", nexthop,
8876 nexthop_hostname, vrf_id_str);
8877 else
8878 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8879
ae248832 8880 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8881 if (len < 1)
8882 vty_out(vty, "\n%*s", 36, " ");
8883 else
8884 vty_out(vty, "%*s", len, " ");
8885 }
445c2480
DS
8886 } else if (safi == SAFI_EVPN) {
8887 if (json_paths) {
8888 json_nexthop_global = json_object_new_object();
8889
c949c771
DA
8890 json_object_string_addf(json_nexthop_global, "ip",
8891 "%pI4", &attr->nexthop);
515c2602 8892
939a97f4 8893 if (path->peer->hostname)
515c2602
DA
8894 json_object_string_add(json_nexthop_global,
8895 "hostname",
939a97f4 8896 path->peer->hostname);
515c2602 8897
a4d82a8a
PZ
8898 json_object_string_add(json_nexthop_global, "afi",
8899 "ipv4");
445c2480
DS
8900 json_object_boolean_true_add(json_nexthop_global,
8901 "used");
aef999a2
DA
8902 } else {
8903 if (nexthop_hostname)
8904 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8905 nexthop_hostname, vrf_id_str);
8906 else
8907 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8908 vrf_id_str);
8909
ae248832 8910 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8911 if (len < 1)
8912 vty_out(vty, "\n%*s", 36, " ");
8913 else
8914 vty_out(vty, "%*s", len, " ");
8915 }
d33fc23b 8916 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8917 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8918 if (json_paths) {
8919 json_nexthop_global = json_object_new_object();
515c2602 8920
026b914a
PG
8921 json_object_string_add(json_nexthop_global,
8922 "afi", "ipv4");
c949c771
DA
8923 json_object_string_addf(json_nexthop_global,
8924 "ip", "%pI4",
8925 &attr->nexthop);
515c2602 8926
939a97f4 8927 if (path->peer->hostname)
515c2602
DA
8928 json_object_string_add(
8929 json_nexthop_global, "hostname",
939a97f4 8930 path->peer->hostname);
515c2602 8931
50e05855
AD
8932 json_object_boolean_true_add(
8933 json_nexthop_global,
026b914a
PG
8934 "used");
8935 } else {
aef999a2
DA
8936 if (nexthop_hostname)
8937 len = vty_out(vty, "%pI4(%s)%s",
8938 &attr->nexthop,
8939 nexthop_hostname,
8940 vrf_id_str);
8941 else
8942 len = vty_out(vty, "%pI4%s",
8943 &attr->nexthop,
8944 vrf_id_str);
8945
ae248832 8946 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8947 if (len < 1)
8948 vty_out(vty, "\n%*s", 36, " ");
8949 else
8950 vty_out(vty, "%*s", len, " ");
026b914a
PG
8951 }
8952 }
d33fc23b 8953 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8954 if (json_paths) {
8955 json_nexthop_global = json_object_new_object();
d62a17ae 8956
c949c771
DA
8957 json_object_string_addf(json_nexthop_global, "ip",
8958 "%pI4", &attr->nexthop);
515c2602 8959
939a97f4 8960 if (path->peer->hostname)
515c2602
DA
8961 json_object_string_add(json_nexthop_global,
8962 "hostname",
939a97f4 8963 path->peer->hostname);
445c2480 8964
a4d82a8a
PZ
8965 json_object_string_add(json_nexthop_global, "afi",
8966 "ipv4");
445c2480
DS
8967 json_object_boolean_true_add(json_nexthop_global,
8968 "used");
8969 } else {
aef999a2
DA
8970 if (nexthop_hostname)
8971 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8972 nexthop_hostname, vrf_id_str);
8973 else
8974 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8975 vrf_id_str);
9df8b37c 8976
ae248832 8977 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8978 if (len < 1)
8979 vty_out(vty, "\n%*s", 36, " ");
8980 else
8981 vty_out(vty, "%*s", len, " ");
d62a17ae 8982 }
445c2480 8983 }
b05a1c8b 8984
445c2480 8985 /* IPv6 Next Hop */
a4d82a8a 8986 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8987 if (json_paths) {
8988 json_nexthop_global = json_object_new_object();
c949c771
DA
8989 json_object_string_addf(json_nexthop_global, "ip",
8990 "%pI6",
8991 &attr->mp_nexthop_global);
515c2602 8992
939a97f4 8993 if (path->peer->hostname)
515c2602
DA
8994 json_object_string_add(json_nexthop_global,
8995 "hostname",
939a97f4 8996 path->peer->hostname);
515c2602 8997
a4d82a8a
PZ
8998 json_object_string_add(json_nexthop_global, "afi",
8999 "ipv6");
9000 json_object_string_add(json_nexthop_global, "scope",
9001 "global");
445c2480
DS
9002
9003 /* We display both LL & GL if both have been
9004 * received */
0606039c
DA
9005 if ((attr->mp_nexthop_len
9006 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9007 || (path->peer->conf_if)) {
a4d82a8a 9008 json_nexthop_ll = json_object_new_object();
c949c771
DA
9009 json_object_string_addf(
9010 json_nexthop_ll, "ip", "%pI6",
9011 &attr->mp_nexthop_local);
515c2602 9012
939a97f4 9013 if (path->peer->hostname)
515c2602
DA
9014 json_object_string_add(
9015 json_nexthop_ll, "hostname",
939a97f4 9016 path->peer->hostname);
515c2602 9017
a4d82a8a
PZ
9018 json_object_string_add(json_nexthop_ll, "afi",
9019 "ipv6");
9020 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9021 "link-local");
d62a17ae 9022
a4d82a8a
PZ
9023 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9024 &attr->mp_nexthop_local)
445c2480
DS
9025 != 0)
9026 && !attr->mp_nexthop_prefer_global)
d62a17ae 9027 json_object_boolean_true_add(
a4d82a8a 9028 json_nexthop_ll, "used");
445c2480
DS
9029 else
9030 json_object_boolean_true_add(
a4d82a8a 9031 json_nexthop_global, "used");
445c2480
DS
9032 } else
9033 json_object_boolean_true_add(
9034 json_nexthop_global, "used");
9035 } else {
9036 /* Display LL if LL/Global both in table unless
9037 * prefer-global is set */
0606039c
DA
9038 if (((attr->mp_nexthop_len
9039 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9040 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9041 || (path->peer->conf_if)) {
9042 if (path->peer->conf_if) {
a4d82a8a 9043 len = vty_out(vty, "%s",
9b6d8fcf 9044 path->peer->conf_if);
ae248832
MK
9045 /* len of IPv6 addr + max len of def
9046 * ifname */
9047 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9048
9049 if (len < 1)
a4d82a8a 9050 vty_out(vty, "\n%*s", 36, " ");
445c2480 9051 else
a4d82a8a 9052 vty_out(vty, "%*s", len, " ");
d62a17ae 9053 } else {
aef999a2
DA
9054 if (nexthop_hostname)
9055 len = vty_out(
9056 vty, "%pI6(%s)%s",
9057 &attr->mp_nexthop_local,
9058 nexthop_hostname,
9059 vrf_id_str);
9060 else
9061 len = vty_out(
9062 vty, "%pI6%s",
9063 &attr->mp_nexthop_local,
9064 vrf_id_str);
9065
ae248832 9066 len = wide ? (41 - len) : (16 - len);
d62a17ae 9067
9068 if (len < 1)
a4d82a8a 9069 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9070 else
a4d82a8a 9071 vty_out(vty, "%*s", len, " ");
d62a17ae 9072 }
445c2480 9073 } else {
aef999a2
DA
9074 if (nexthop_hostname)
9075 len = vty_out(vty, "%pI6(%s)%s",
9076 &attr->mp_nexthop_global,
9077 nexthop_hostname,
9078 vrf_id_str);
9079 else
9080 len = vty_out(vty, "%pI6%s",
9081 &attr->mp_nexthop_global,
9082 vrf_id_str);
9083
ae248832 9084 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9085
9086 if (len < 1)
9087 vty_out(vty, "\n%*s", 36, " ");
9088 else
9089 vty_out(vty, "%*s", len, " ");
d62a17ae 9090 }
9091 }
445c2480 9092 }
718e3744 9093
445c2480
DS
9094 /* MED/Metric */
9095 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9096 if (json_paths)
50e05855 9097 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9098 else if (wide)
9099 vty_out(vty, "%7u", attr->med);
0fbac0b4 9100 else
445c2480 9101 vty_out(vty, "%10u", attr->med);
ae248832
MK
9102 else if (!json_paths) {
9103 if (wide)
9104 vty_out(vty, "%*s", 7, " ");
9105 else
9106 vty_out(vty, "%*s", 10, " ");
9107 }
d62a17ae 9108
445c2480
DS
9109 /* Local Pref */
9110 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9111 if (json_paths)
50e05855 9112 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9113 attr->local_pref);
9114 else
445c2480
DS
9115 vty_out(vty, "%7u", attr->local_pref);
9116 else if (!json_paths)
9117 vty_out(vty, " ");
d62a17ae 9118
445c2480
DS
9119 if (json_paths)
9120 json_object_int_add(json_path, "weight", attr->weight);
9121 else
9122 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9123
445c2480
DS
9124 if (json_paths) {
9125 char buf[BUFSIZ];
a4d82a8a
PZ
9126 json_object_string_add(
9127 json_path, "peerId",
9b6d8fcf 9128 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 9129 }
b05a1c8b 9130
445c2480
DS
9131 /* Print aspath */
9132 if (attr->aspath) {
0fbac0b4 9133 if (json_paths)
50e05855 9134 json_object_string_add(json_path, "path",
0fbac0b4
DA
9135 attr->aspath->str);
9136 else
445c2480 9137 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9138 }
f1aa5d8a 9139
445c2480
DS
9140 /* Print origin */
9141 if (json_paths)
a4d82a8a
PZ
9142 json_object_string_add(json_path, "origin",
9143 bgp_origin_long_str[attr->origin]);
445c2480
DS
9144 else
9145 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9146
9df8b37c 9147 if (json_paths) {
d071f237 9148 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9149 json_object_string_add(json_path, "esi",
9150 esi_to_str(&attr->esi,
9151 esi_buf, sizeof(esi_buf)));
9152 }
6f214dd3
CS
9153 if (safi == SAFI_EVPN &&
9154 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9155 json_ext_community = json_object_new_object();
b53e67a3
DA
9156 json_object_string_add(
9157 json_ext_community, "string",
9158 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9159 json_object_object_add(json_path,
9160 "extendedCommunity",
9161 json_ext_community);
9162 }
9163
9df8b37c
PZ
9164 if (nexthop_self)
9165 json_object_boolean_true_add(json_path,
9166 "announceNexthopSelf");
9167 if (nexthop_othervrf) {
9168 json_object_string_add(json_path, "nhVrfName",
9169 nexthop_vrfname);
9170
9171 json_object_int_add(json_path, "nhVrfId",
9172 ((nexthop_vrfid == VRF_UNKNOWN)
9173 ? -1
9174 : (int)nexthop_vrfid));
9175 }
9176 }
9177
d62a17ae 9178 if (json_paths) {
9179 if (json_nexthop_global || json_nexthop_ll) {
9180 json_nexthops = json_object_new_array();
f1aa5d8a 9181
d62a17ae 9182 if (json_nexthop_global)
9183 json_object_array_add(json_nexthops,
9184 json_nexthop_global);
f1aa5d8a 9185
d62a17ae 9186 if (json_nexthop_ll)
9187 json_object_array_add(json_nexthops,
9188 json_nexthop_ll);
f1aa5d8a 9189
d62a17ae 9190 json_object_object_add(json_path, "nexthops",
9191 json_nexthops);
9192 }
9193
9194 json_object_array_add(json_paths, json_path);
9195 } else {
9196 vty_out(vty, "\n");
6f214dd3 9197
b5e140c8 9198 if (safi == SAFI_EVPN) {
d071f237 9199 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9200 /* XXX - add these params to the json out */
b5e140c8 9201 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9202 vty_out(vty, "ESI:%s",
9203 esi_to_str(&attr->esi, esi_buf,
9204 sizeof(esi_buf)));
60605cbc 9205
229587fb 9206 vty_out(vty, "\n");
b5e140c8
AK
9207 }
9208 if (attr->flag &
9209 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9210 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9211 vty_out(vty, "%s\n",
9212 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9213 }
6f214dd3
CS
9214 }
9215
49e5a4a0 9216#ifdef ENABLE_BGP_VNC
d62a17ae 9217 /* prints an additional line, indented, with VNC info, if
9218 * present */
9219 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9220 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9221#endif
d62a17ae 9222 }
9223}
718e3744 9224
9225/* called from terminal list command */
7d3cae70
DA
9226void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9227 const struct prefix *p, struct attr *attr, safi_t safi,
9228 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9229{
9230 json_object *json_status = NULL;
9231 json_object *json_net = NULL;
aef999a2 9232 int len;
d62a17ae 9233 char buff[BUFSIZ];
dc387b0f 9234
d62a17ae 9235 /* Route status display. */
9236 if (use_json) {
9237 json_status = json_object_new_object();
9238 json_net = json_object_new_object();
9239 } else {
9240 vty_out(vty, "*");
9241 vty_out(vty, ">");
9242 vty_out(vty, " ");
9243 }
718e3744 9244
d62a17ae 9245 /* print prefix and mask */
50e05855 9246 if (use_json) {
dc387b0f
LK
9247 if (safi == SAFI_EVPN)
9248 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9249 else if (p->family == AF_INET || p->family == AF_INET6) {
9250 json_object_string_add(
9251 json_net, "addrPrefix",
9252 inet_ntop(p->family, &p->u.prefix, buff,
9253 BUFSIZ));
9254 json_object_int_add(json_net, "prefixLen",
9255 p->prefixlen);
67d7e256 9256 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9257 }
50e05855 9258 } else
7d3cae70 9259 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9260
9261 /* Print attribute */
9262 if (attr) {
9263 if (use_json) {
9264 if (p->family == AF_INET
9265 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9266 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9267 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9268 json_object_string_addf(
9269 json_net, "nextHop", "%pI4",
9270 &attr->mp_nexthop_global_in);
d62a17ae 9271 else
c949c771
DA
9272 json_object_string_addf(
9273 json_net, "nextHop", "%pI4",
9274 &attr->nexthop);
d62a17ae 9275 } else if (p->family == AF_INET6
9276 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9277 json_object_string_addf(
9278 json_net, "nextHopGlobal", "%pI6",
9279 &attr->mp_nexthop_global);
23d0a753
DA
9280 } else if (p->family == AF_EVPN
9281 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9282 json_object_string_addf(
9283 json_net, "nextHop", "%pI4",
9284 &attr->mp_nexthop_global_in);
23d0a753 9285 }
d62a17ae 9286
9287 if (attr->flag
9288 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9289 json_object_int_add(json_net, "metric",
9290 attr->med);
9291
0fbac0b4 9292 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9293 json_object_int_add(json_net, "locPrf",
0fbac0b4 9294 attr->local_pref);
d62a17ae 9295
9296 json_object_int_add(json_net, "weight", attr->weight);
9297
9298 /* Print aspath */
0fbac0b4 9299 if (attr->aspath)
50e05855 9300 json_object_string_add(json_net, "path",
0fbac0b4 9301 attr->aspath->str);
d62a17ae 9302
9303 /* Print origin */
9304 json_object_string_add(json_net, "bgpOriginCode",
9305 bgp_origin_str[attr->origin]);
9306 } else {
9307 if (p->family == AF_INET
9308 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9309 || safi == SAFI_EVPN
9310 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9311 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9312 || safi == SAFI_EVPN)
23d0a753
DA
9313 vty_out(vty, "%-16pI4",
9314 &attr->mp_nexthop_global_in);
ae248832 9315 else if (wide)
23d0a753 9316 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9317 else
23d0a753 9318 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9319 } else if (p->family == AF_INET6
9320 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9321 char buf[BUFSIZ];
9322
9323 len = vty_out(
9324 vty, "%s",
9325 inet_ntop(AF_INET6,
9326 &attr->mp_nexthop_global, buf,
9327 BUFSIZ));
ae248832 9328 len = wide ? (41 - len) : (16 - len);
d62a17ae 9329 if (len < 1)
9330 vty_out(vty, "\n%*s", 36, " ");
9331 else
9332 vty_out(vty, "%*s", len, " ");
9333 }
9334 if (attr->flag
9335 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9336 if (wide)
9337 vty_out(vty, "%7u", attr->med);
9338 else
9339 vty_out(vty, "%10u", attr->med);
9340 else if (wide)
9341 vty_out(vty, " ");
d62a17ae 9342 else
9343 vty_out(vty, " ");
718e3744 9344
d62a17ae 9345 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9346 vty_out(vty, "%7u", attr->local_pref);
9347 else
9348 vty_out(vty, " ");
9349
9350 vty_out(vty, "%7u ", attr->weight);
9351
9352 /* Print aspath */
9353 if (attr->aspath)
9354 aspath_print_vty(vty, "%s", attr->aspath, " ");
9355
9356 /* Print origin */
9357 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9358 }
9359 }
9360 if (use_json) {
9361 json_object_boolean_true_add(json_status, "*");
9362 json_object_boolean_true_add(json_status, ">");
9363 json_object_object_add(json_net, "appliedStatusSymbols",
9364 json_status);
1608ff77 9365
dc387b0f
LK
9366 prefix2str(p, buff, PREFIX_STRLEN);
9367 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9368 } else
9369 vty_out(vty, "\n");
9370}
9371
bd494ec5 9372void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9373 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9374 json_object *json)
9375{
9376 json_object *json_out = NULL;
9377 struct attr *attr;
9378 mpls_label_t label = MPLS_INVALID_LABEL;
9379
9b6d8fcf 9380 if (!path->extra)
d62a17ae 9381 return;
9382
9383 if (json)
9384 json_out = json_object_new_object();
9385
9386 /* short status lead text */
82c298be 9387 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9388
9389 /* print prefix and mask */
9390 if (json == NULL) {
9391 if (!display)
7d3cae70 9392 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9393 else
9394 vty_out(vty, "%*s", 17, " ");
9395 }
9396
9397 /* Print attribute */
9b6d8fcf 9398 attr = path->attr;
05864da7
DS
9399 if (((p->family == AF_INET)
9400 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9401 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9402 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9403 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9404 || safi == SAFI_EVPN) {
9405 if (json)
c949c771
DA
9406 json_object_string_addf(
9407 json_out, "mpNexthopGlobalIn", "%pI4",
9408 &attr->mp_nexthop_global_in);
05864da7 9409 else
23d0a753
DA
9410 vty_out(vty, "%-16pI4",
9411 &attr->mp_nexthop_global_in);
05864da7
DS
9412 } else {
9413 if (json)
c949c771
DA
9414 json_object_string_addf(json_out, "nexthop",
9415 "%pI4", &attr->nexthop);
05864da7 9416 else
23d0a753 9417 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9418 }
9419 } else if (((p->family == AF_INET6)
9420 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9421 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9422 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9423 char buf_a[512];
9424
9425 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9426 if (json)
c949c771
DA
9427 json_object_string_addf(
9428 json_out, "mpNexthopGlobalIn", "%pI6",
9429 &attr->mp_nexthop_global);
05864da7
DS
9430 else
9431 vty_out(vty, "%s",
9432 inet_ntop(AF_INET6,
9433 &attr->mp_nexthop_global,
9434 buf_a, sizeof(buf_a)));
9435 } else if (attr->mp_nexthop_len
9436 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9437 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9438 &attr->mp_nexthop_global,
9439 &attr->mp_nexthop_local);
9440 if (json)
9441 json_object_string_add(json_out,
9442 "mpNexthopGlobalLocal",
9443 buf_a);
9444 else
9445 vty_out(vty, "%s", buf_a);
d62a17ae 9446 }
9447 }
9448
9b6d8fcf 9449 label = decode_label(&path->extra->label[0]);
d62a17ae 9450
9451 if (bgp_is_valid_label(&label)) {
9452 if (json) {
9453 json_object_int_add(json_out, "notag", label);
9454 json_object_array_add(json, json_out);
9455 } else {
9456 vty_out(vty, "notag/%d", label);
9457 vty_out(vty, "\n");
9458 }
700ddfed
PG
9459 } else if (!json)
9460 vty_out(vty, "\n");
d62a17ae 9461}
718e3744 9462
bd494ec5 9463void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9464 struct bgp_path_info *path, int display,
d62a17ae 9465 json_object *json_paths)
718e3744 9466{
d62a17ae 9467 struct attr *attr;
d62a17ae 9468 json_object *json_path = NULL;
14f51eba
LK
9469 json_object *json_nexthop = NULL;
9470 json_object *json_overlay = NULL;
856ca177 9471
9b6d8fcf 9472 if (!path->extra)
d62a17ae 9473 return;
718e3744 9474
14f51eba
LK
9475 if (json_paths) {
9476 json_path = json_object_new_object();
9477 json_overlay = json_object_new_object();
9478 json_nexthop = json_object_new_object();
9479 }
9480
d62a17ae 9481 /* short status lead text */
82c298be 9482 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9483
d62a17ae 9484 /* print prefix and mask */
9485 if (!display)
7d3cae70 9486 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9487 else
9488 vty_out(vty, "%*s", 17, " ");
9489
9490 /* Print attribute */
9b6d8fcf 9491 attr = path->attr;
05864da7 9492 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9493
05864da7
DS
9494 switch (af) {
9495 case AF_INET:
05864da7 9496 if (!json_path) {
db66cf7c 9497 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9498 } else {
db66cf7c
DA
9499 json_object_string_addf(json_nexthop, "ip", "%pI4",
9500 &attr->mp_nexthop_global_in);
14f51eba 9501
05864da7 9502 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9503
05864da7
DS
9504 json_object_object_add(json_path, "nexthop",
9505 json_nexthop);
9506 }
9507 break;
9508 case AF_INET6:
05864da7 9509 if (!json_path) {
db66cf7c
DA
9510 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9511 &attr->mp_nexthop_local);
05864da7 9512 } else {
db66cf7c
DA
9513 json_object_string_addf(json_nexthop, "ipv6Global",
9514 "%pI6",
9515 &attr->mp_nexthop_global);
14f51eba 9516
db66cf7c
DA
9517 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9518 "%pI6",
9519 &attr->mp_nexthop_local);
14f51eba 9520
05864da7 9521 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9522
05864da7
DS
9523 json_object_object_add(json_path, "nexthop",
9524 json_nexthop);
9525 }
9526 break;
9527 default:
9528 if (!json_path) {
9529 vty_out(vty, "?");
9530 } else {
9531 json_object_string_add(json_nexthop, "Error",
9532 "Unsupported address-family");
77a2f8e5
DA
9533 json_object_string_add(json_nexthop, "error",
9534 "Unsupported address-family");
d62a17ae 9535 }
05864da7 9536 }
988258b4 9537
6c924775
DS
9538 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9539
05864da7 9540 if (!json_path)
db66cf7c 9541 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9542 else
db66cf7c 9543 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9544
b53e67a3 9545 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9546 char *mac = NULL;
9547 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9548 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9549 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9550
9551 if (routermac)
9552 mac = ecom_mac2str((char *)routermac->val);
9553 if (mac) {
9554 if (!json_path) {
c4efd0f4 9555 vty_out(vty, "/%s", mac);
05864da7
DS
9556 } else {
9557 json_object_string_add(json_overlay, "rmac",
9558 mac);
988258b4 9559 }
05864da7 9560 XFREE(MTYPE_TMP, mac);
988258b4 9561 }
05864da7 9562 }
718e3744 9563
05864da7
DS
9564 if (!json_path) {
9565 vty_out(vty, "\n");
9566 } else {
9567 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9568
05864da7 9569 json_object_array_add(json_paths, json_path);
14f51eba 9570 }
d62a17ae 9571}
718e3744 9572
d62a17ae 9573/* dampening route */
5f040085
DS
9574static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9575 struct bgp_path_info *path, int display,
9576 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9577 json_object *json_paths)
d62a17ae 9578{
e5be8c1d 9579 struct attr *attr = path->attr;
d62a17ae 9580 int len;
9581 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9582 json_object *json_path = NULL;
9583
9584 if (use_json)
9585 json_path = json_object_new_object();
d62a17ae 9586
9587 /* short status lead text */
e5be8c1d 9588 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9589
9590 /* print prefix and mask */
9591 if (!use_json) {
9592 if (!display)
7d3cae70 9593 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9594 else
9595 vty_out(vty, "%*s", 17, " ");
d62a17ae 9596
e5be8c1d
DA
9597 len = vty_out(vty, "%s", path->peer->host);
9598 len = 17 - len;
9599
9600 if (len < 1)
d62a17ae 9601 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9602 else
9603 vty_out(vty, "%*s", len, " ");
d62a17ae 9604
9b6d8fcf
DS
9605 vty_out(vty, "%s ",
9606 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9607 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9608 use_json, NULL));
d62a17ae 9609
e5be8c1d 9610 if (attr->aspath)
05864da7 9611 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9612
05864da7
DS
9613 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9614
d62a17ae 9615 vty_out(vty, "\n");
e5be8c1d
DA
9616 } else {
9617 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9618 safi, use_json, json_path);
9619
9620 if (attr->aspath)
9621 json_object_string_add(json_path, "asPath",
9622 attr->aspath->str);
9623
9624 json_object_string_add(json_path, "origin",
9625 bgp_origin_str[attr->origin]);
9626 json_object_string_add(json_path, "peerHost", path->peer->host);
9627
9628 json_object_array_add(json_paths, json_path);
9629 }
d62a17ae 9630}
718e3744 9631
d62a17ae 9632/* flap route */
5f040085
DS
9633static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9634 struct bgp_path_info *path, int display,
9635 afi_t afi, safi_t safi, bool use_json,
31258046 9636 json_object *json_paths)
784d3a42 9637{
31258046 9638 struct attr *attr = path->attr;
d62a17ae 9639 struct bgp_damp_info *bdi;
9640 char timebuf[BGP_UPTIME_LEN];
9641 int len;
31258046 9642 json_object *json_path = NULL;
784d3a42 9643
9b6d8fcf 9644 if (!path->extra)
d62a17ae 9645 return;
784d3a42 9646
31258046
DA
9647 if (use_json)
9648 json_path = json_object_new_object();
9649
9b6d8fcf 9650 bdi = path->extra->damp_info;
784d3a42 9651
d62a17ae 9652 /* short status lead text */
31258046 9653 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9654
d62a17ae 9655 if (!use_json) {
9656 if (!display)
7d3cae70 9657 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9658 else
9659 vty_out(vty, "%*s", 17, " ");
784d3a42 9660
31258046
DA
9661 len = vty_out(vty, "%s", path->peer->host);
9662 len = 16 - len;
9663 if (len < 1)
d62a17ae 9664 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9665 else
9666 vty_out(vty, "%*s", len, " ");
784d3a42 9667
31258046
DA
9668 len = vty_out(vty, "%d", bdi->flap);
9669 len = 5 - len;
9670 if (len < 1)
d62a17ae 9671 vty_out(vty, " ");
d62a17ae 9672 else
9673 vty_out(vty, "%*s", len, " ");
d62a17ae 9674
996c9314
LB
9675 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9676 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9677
31258046
DA
9678 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9679 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9680 vty_out(vty, "%s ",
9b6d8fcf 9681 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9682 BGP_UPTIME_LEN, afi,
31258046
DA
9683 safi, use_json, NULL));
9684 else
d62a17ae 9685 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9686
31258046 9687 if (attr->aspath)
05864da7 9688 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9689
05864da7
DS
9690 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9691
d62a17ae 9692 vty_out(vty, "\n");
31258046
DA
9693 } else {
9694 json_object_string_add(json_path, "peerHost", path->peer->host);
9695 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9696
9697 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9698 json_path);
9699
9700 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9701 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9702 bgp_damp_reuse_time_vty(vty, path, timebuf,
9703 BGP_UPTIME_LEN, afi, safi,
9704 use_json, json_path);
9705
9706 if (attr->aspath)
9707 json_object_string_add(json_path, "asPath",
9708 attr->aspath->str);
9709
9710 json_object_string_add(json_path, "origin",
9711 bgp_origin_str[attr->origin]);
9712
9713 json_object_array_add(json_paths, json_path);
9714 }
d62a17ae 9715}
9716
9717static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9718 int *first, const char *header,
9719 json_object *json_adv_to)
9720{
9721 char buf1[INET6_ADDRSTRLEN];
9722 json_object *json_peer = NULL;
9723
9724 if (json_adv_to) {
9725 /* 'advertised-to' is a dictionary of peers we have advertised
9726 * this
9727 * prefix too. The key is the peer's IP or swpX, the value is
9728 * the
9729 * hostname if we know it and "" if not.
9730 */
9731 json_peer = json_object_new_object();
9732
9733 if (peer->hostname)
9734 json_object_string_add(json_peer, "hostname",
9735 peer->hostname);
9736
9737 if (peer->conf_if)
9738 json_object_object_add(json_adv_to, peer->conf_if,
9739 json_peer);
9740 else
9741 json_object_object_add(
9742 json_adv_to,
9743 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9744 json_peer);
9745 } else {
9746 if (*first) {
9747 vty_out(vty, "%s", header);
9748 *first = 0;
9749 }
9750
9751 if (peer->hostname
892fedb6 9752 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9753 if (peer->conf_if)
9754 vty_out(vty, " %s(%s)", peer->hostname,
9755 peer->conf_if);
9756 else
9757 vty_out(vty, " %s(%s)", peer->hostname,
9758 sockunion2str(&peer->su, buf1,
9759 SU_ADDRSTRLEN));
9760 } else {
9761 if (peer->conf_if)
9762 vty_out(vty, " %s", peer->conf_if);
9763 else
9764 vty_out(vty, " %s",
9765 sockunion2str(&peer->su, buf1,
9766 SU_ADDRSTRLEN));
9767 }
9768 }
784d3a42
PG
9769}
9770
dcc68b5e
MS
9771static void route_vty_out_tx_ids(struct vty *vty,
9772 struct bgp_addpath_info_data *d)
9773{
9774 int i;
9775
9776 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9777 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9778 d->addpath_tx_id[i],
9779 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9780 }
9781}
9782
5e4d4c8a 9783static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9784 struct bgp_path_info *pi,
9785 struct attr *attr,
9786 json_object *json_path)
5e4d4c8a
AK
9787{
9788 char esi_buf[ESI_STR_LEN];
9789 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9790 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9791 ATTR_ES_PEER_ROUTER);
9792 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9793 ATTR_ES_PEER_ACTIVE);
9794 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9795 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9796 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9797 if (json_path) {
9798 json_object *json_es_info = NULL;
9799
9800 json_object_string_add(
9801 json_path, "esi",
9802 esi_buf);
9803 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9804 json_es_info = json_object_new_object();
9805 if (es_local)
9806 json_object_boolean_true_add(
9807 json_es_info, "localEs");
9808 if (peer_active)
9809 json_object_boolean_true_add(
9810 json_es_info, "peerActive");
9811 if (peer_proxy)
9812 json_object_boolean_true_add(
9813 json_es_info, "peerProxy");
9814 if (peer_router)
9815 json_object_boolean_true_add(
9816 json_es_info, "peerRouter");
9817 if (attr->mm_sync_seqnum)
9818 json_object_int_add(
9819 json_es_info, "peerSeq",
9820 attr->mm_sync_seqnum);
9821 json_object_object_add(
9822 json_path, "es_info",
9823 json_es_info);
9824 }
9825 } else {
9826 if (bgp_evpn_attr_is_sync(attr))
9827 vty_out(vty,
9828 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9829 esi_buf,
9830 es_local ? "local-es":"",
9831 peer_proxy ? "proxy " : "",
9832 peer_active ? "active ":"",
9833 peer_router ? "router ":"",
9834 attr->mm_sync_seqnum);
9835 else
9836 vty_out(vty, " ESI %s %s\n",
9837 esi_buf,
9838 es_local ? "local-es":"");
9839 }
9840}
9841
4933eaaf
DS
9842void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9843 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9844 enum rpki_states rpki_curr_state,
9845 json_object *json_paths)
d62a17ae 9846{
9847 char buf[INET6_ADDRSTRLEN];
9848 char buf1[BUFSIZ];
515c2602 9849 struct attr *attr = path->attr;
d62a17ae 9850 time_t tbuf;
9851 json_object *json_bestpath = NULL;
9852 json_object *json_cluster_list = NULL;
9853 json_object *json_cluster_list_list = NULL;
9854 json_object *json_ext_community = NULL;
9855 json_object *json_last_update = NULL;
7fd077aa 9856 json_object *json_pmsi = NULL;
d62a17ae 9857 json_object *json_nexthop_global = NULL;
9858 json_object *json_nexthop_ll = NULL;
9859 json_object *json_nexthops = NULL;
9860 json_object *json_path = NULL;
9861 json_object *json_peer = NULL;
9862 json_object *json_string = NULL;
9863 json_object *json_adv_to = NULL;
9864 int first = 0;
9865 struct listnode *node, *nnode;
9866 struct peer *peer;
be92fc9f 9867 bool addpath_capable;
d62a17ae 9868 int has_adj;
9869 unsigned int first_as;
1defdda8 9870 bool nexthop_self =
9b6d8fcf 9871 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9872 int i;
2ba93fd6
DA
9873 char *nexthop_hostname =
9874 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
9875 uint32_t ttl = 0;
9876 uint32_t bos = 0;
9877 uint32_t exp = 0;
9878 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 9879
9880 if (json_paths) {
9881 json_path = json_object_new_object();
9882 json_peer = json_object_new_object();
9883 json_nexthop_global = json_object_new_object();
9884 }
9885
8304dabf
AD
9886 if (safi == SAFI_EVPN) {
9887 if (!json_paths)
9888 vty_out(vty, " Route %pRN", bn);
9889 }
9890
44c69747 9891 if (path->extra) {
b57ba6d2 9892 char tag_buf[30];
d62a17ae 9893
d62a17ae 9894 tag_buf[0] = '\0';
9b6d8fcf
DS
9895 if (path->extra && path->extra->num_labels) {
9896 bgp_evpn_label2str(path->extra->label,
9897 path->extra->num_labels, tag_buf,
a4d82a8a 9898 sizeof(tag_buf));
d62a17ae 9899 }
d7325ee7 9900 if (safi == SAFI_EVPN) {
44c69747 9901 if (!json_paths) {
44c69747
LK
9902 if (tag_buf[0] != '\0')
9903 vty_out(vty, " VNI %s", tag_buf);
44c69747 9904 } else {
77a2f8e5 9905 if (tag_buf[0]) {
44c69747
LK
9906 json_object_string_add(json_path, "VNI",
9907 tag_buf);
77a2f8e5
DA
9908 json_object_string_add(json_path, "vni",
9909 tag_buf);
9910 }
44c69747 9911 }
d7325ee7
DD
9912 }
9913
44c69747 9914 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9915 struct bgp_path_info *parent_ri;
9bcb3eef 9916 struct bgp_dest *dest, *pdest;
d62a17ae 9917
9b6d8fcf 9918 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9919 dest = parent_ri->net;
9920 if (dest && dest->pdest) {
9921 pdest = dest->pdest;
9922 prefix_rd2str(
9923 (struct prefix_rd *)bgp_dest_get_prefix(
9924 pdest),
9925 buf1, sizeof(buf1));
d7325ee7 9926 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9927 vty_out(vty,
58bff4d1 9928 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9929 buf1,
9930 (struct prefix_evpn *)
9931 bgp_dest_get_prefix(
9932 dest),
9933 tag_buf);
58bff4d1
AK
9934 if (attr->es_flags & ATTR_ES_L3_NHG)
9935 vty_out(vty, ", L3NHG %s",
9936 (attr->es_flags
9937 & ATTR_ES_L3_NHG_ACTIVE)
9938 ? "active"
9939 : "inactive");
9940 vty_out(vty, "\n");
9941
d7325ee7 9942 } else
2dbe669b
DA
9943 vty_out(vty,
9944 " Imported from %s:%pFX\n",
9945 buf1,
9946 (struct prefix_evpn *)
9947 bgp_dest_get_prefix(
9948 dest));
d62a17ae 9949 }
9950 }
9951 }
d62a17ae 9952
8304dabf
AD
9953 if (safi == SAFI_EVPN
9954 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9955 char gwip_buf[INET6_ADDRSTRLEN];
9956
860e740b
IR
9957 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
9958 sizeof(gwip_buf));
8304dabf
AD
9959
9960 if (json_paths)
9961 json_object_string_add(json_path, "gatewayIP",
9962 gwip_buf);
9963 else
9964 vty_out(vty, " Gateway IP %s", gwip_buf);
9965 }
9966
9967 if (safi == SAFI_EVPN)
9968 vty_out(vty, "\n");
9969
05864da7
DS
9970 /* Line1 display AS-path, Aggregator */
9971 if (attr->aspath) {
9972 if (json_paths) {
9973 if (!attr->aspath->json)
9974 aspath_str_update(attr->aspath, true);
9975 json_object_lock(attr->aspath->json);
9976 json_object_object_add(json_path, "aspath",
9977 attr->aspath->json);
9978 } else {
9979 if (attr->aspath->segments)
9980 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9981 else
05864da7 9982 vty_out(vty, " Local");
d62a17ae 9983 }
05864da7 9984 }
d62a17ae 9985
05864da7
DS
9986 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9987 if (json_paths)
9988 json_object_boolean_true_add(json_path, "removed");
9989 else
9990 vty_out(vty, ", (removed)");
9991 }
d62a17ae 9992
05864da7
DS
9993 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9994 if (json_paths)
9995 json_object_boolean_true_add(json_path, "stale");
9996 else
9997 vty_out(vty, ", (stale)");
9998 }
d62a17ae 9999
05864da7
DS
10000 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10001 if (json_paths) {
10002 json_object_int_add(json_path, "aggregatorAs",
10003 attr->aggregator_as);
c949c771
DA
10004 json_object_string_addf(json_path, "aggregatorId",
10005 "%pI4", &attr->aggregator_addr);
05864da7 10006 } else {
88d495a9
DA
10007 vty_out(vty, ", (aggregated by %u %pI4)",
10008 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10009 }
05864da7 10010 }
d62a17ae 10011
05864da7
DS
10012 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10013 PEER_FLAG_REFLECTOR_CLIENT)) {
10014 if (json_paths)
10015 json_object_boolean_true_add(json_path,
10016 "rxedFromRrClient");
10017 else
10018 vty_out(vty, ", (Received from a RR-client)");
10019 }
d62a17ae 10020
05864da7
DS
10021 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10022 PEER_FLAG_RSERVER_CLIENT)) {
10023 if (json_paths)
10024 json_object_boolean_true_add(json_path,
10025 "rxedFromRsClient");
10026 else
10027 vty_out(vty, ", (Received from a RS-client)");
10028 }
d62a17ae 10029
05864da7
DS
10030 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10031 if (json_paths)
10032 json_object_boolean_true_add(json_path,
10033 "dampeningHistoryEntry");
10034 else
10035 vty_out(vty, ", (history entry)");
10036 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10037 if (json_paths)
10038 json_object_boolean_true_add(json_path,
10039 "dampeningSuppressed");
10040 else
10041 vty_out(vty, ", (suppressed due to dampening)");
10042 }
d62a17ae 10043
05864da7
DS
10044 if (!json_paths)
10045 vty_out(vty, "\n");
d62a17ae 10046
05864da7
DS
10047 /* Line2 display Next-hop, Neighbor, Router-id */
10048 /* Display the nexthop */
9bcb3eef 10049 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10050
10051 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10052 || bn_p->family == AF_EVPN)
05864da7
DS
10053 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10054 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10055 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10056 || safi == SAFI_EVPN) {
515c2602 10057 if (json_paths) {
c949c771
DA
10058 json_object_string_addf(
10059 json_nexthop_global, "ip", "%pI4",
10060 &attr->mp_nexthop_global_in);
515c2602 10061
939a97f4 10062 if (path->peer->hostname)
515c2602
DA
10063 json_object_string_add(
10064 json_nexthop_global, "hostname",
939a97f4 10065 path->peer->hostname);
aef999a2
DA
10066 } else {
10067 if (nexthop_hostname)
10068 vty_out(vty, " %pI4(%s)",
10069 &attr->mp_nexthop_global_in,
10070 nexthop_hostname);
10071 else
10072 vty_out(vty, " %pI4",
10073 &attr->mp_nexthop_global_in);
10074 }
d62a17ae 10075 } else {
515c2602 10076 if (json_paths) {
c949c771
DA
10077 json_object_string_addf(json_nexthop_global,
10078 "ip", "%pI4",
10079 &attr->nexthop);
515c2602 10080
939a97f4 10081 if (path->peer->hostname)
515c2602
DA
10082 json_object_string_add(
10083 json_nexthop_global, "hostname",
939a97f4 10084 path->peer->hostname);
aef999a2
DA
10085 } else {
10086 if (nexthop_hostname)
10087 vty_out(vty, " %pI4(%s)",
10088 &attr->nexthop,
10089 nexthop_hostname);
10090 else
10091 vty_out(vty, " %pI4",
10092 &attr->nexthop);
10093 }
d62a17ae 10094 }
10095
05864da7
DS
10096 if (json_paths)
10097 json_object_string_add(json_nexthop_global, "afi",
10098 "ipv4");
10099 } else {
10100 if (json_paths) {
c949c771
DA
10101 json_object_string_addf(json_nexthop_global, "ip",
10102 "%pI6",
10103 &attr->mp_nexthop_global);
515c2602 10104
939a97f4 10105 if (path->peer->hostname)
515c2602
DA
10106 json_object_string_add(json_nexthop_global,
10107 "hostname",
939a97f4 10108 path->peer->hostname);
515c2602 10109
05864da7
DS
10110 json_object_string_add(json_nexthop_global, "afi",
10111 "ipv6");
10112 json_object_string_add(json_nexthop_global, "scope",
10113 "global");
10114 } else {
aef999a2
DA
10115 if (nexthop_hostname)
10116 vty_out(vty, " %pI6(%s)",
10117 &attr->mp_nexthop_global,
10118 nexthop_hostname);
10119 else
10120 vty_out(vty, " %pI6",
10121 &attr->mp_nexthop_global);
d62a17ae 10122 }
05864da7 10123 }
d62a17ae 10124
05864da7
DS
10125 /* Display the IGP cost or 'inaccessible' */
10126 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10127 if (json_paths)
10128 json_object_boolean_false_add(json_nexthop_global,
10129 "accessible");
10130 else
10131 vty_out(vty, " (inaccessible)");
10132 } else {
10133 if (path->extra && path->extra->igpmetric) {
d62a17ae 10134 if (json_paths)
05864da7
DS
10135 json_object_int_add(json_nexthop_global,
10136 "metric",
10137 path->extra->igpmetric);
d62a17ae 10138 else
05864da7
DS
10139 vty_out(vty, " (metric %u)",
10140 path->extra->igpmetric);
d62a17ae 10141 }
10142
05864da7 10143 /* IGP cost is 0, display this only for json */
d62a17ae 10144 else {
d62a17ae 10145 if (json_paths)
05864da7
DS
10146 json_object_int_add(json_nexthop_global,
10147 "metric", 0);
d62a17ae 10148 }
d62a17ae 10149
05864da7
DS
10150 if (json_paths)
10151 json_object_boolean_true_add(json_nexthop_global,
10152 "accessible");
10153 }
d62a17ae 10154
05864da7
DS
10155 /* Display peer "from" output */
10156 /* This path was originated locally */
10157 if (path->peer == bgp->peer_self) {
d62a17ae 10158
05864da7 10159 if (safi == SAFI_EVPN
b54892e0 10160 || (bn_p->family == AF_INET
05864da7 10161 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10162 if (json_paths)
05864da7
DS
10163 json_object_string_add(json_peer, "peerId",
10164 "0.0.0.0");
d62a17ae 10165 else
05864da7
DS
10166 vty_out(vty, " from 0.0.0.0 ");
10167 } else {
d62a17ae 10168 if (json_paths)
05864da7
DS
10169 json_object_string_add(json_peer, "peerId",
10170 "::");
d62a17ae 10171 else
05864da7 10172 vty_out(vty, " from :: ");
d62a17ae 10173 }
d62a17ae 10174
4e9a9863 10175 if (json_paths)
c949c771
DA
10176 json_object_string_addf(json_peer, "routerId", "%pI4",
10177 &bgp->router_id);
4e9a9863 10178 else
23d0a753 10179 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10180 }
d62a17ae 10181
05864da7
DS
10182 /* We RXed this path from one of our peers */
10183 else {
10184
10185 if (json_paths) {
10186 json_object_string_add(json_peer, "peerId",
10187 sockunion2str(&path->peer->su,
10188 buf,
10189 SU_ADDRSTRLEN));
c949c771
DA
10190 json_object_string_addf(json_peer, "routerId", "%pI4",
10191 &path->peer->remote_id);
05864da7
DS
10192
10193 if (path->peer->hostname)
10194 json_object_string_add(json_peer, "hostname",
10195 path->peer->hostname);
10196
10197 if (path->peer->domainname)
10198 json_object_string_add(json_peer, "domainname",
10199 path->peer->domainname);
10200
10201 if (path->peer->conf_if)
10202 json_object_string_add(json_peer, "interface",
10203 path->peer->conf_if);
10204 } else {
10205 if (path->peer->conf_if) {
10206 if (path->peer->hostname
892fedb6
DA
10207 && CHECK_FLAG(path->peer->bgp->flags,
10208 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10209 vty_out(vty, " from %s(%s)",
10210 path->peer->hostname,
10211 path->peer->conf_if);
d62a17ae 10212 else
05864da7 10213 vty_out(vty, " from %s",
9b6d8fcf 10214 path->peer->conf_if);
d62a17ae 10215 } else {
05864da7 10216 if (path->peer->hostname
892fedb6
DA
10217 && CHECK_FLAG(path->peer->bgp->flags,
10218 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10219 vty_out(vty, " from %s(%s)",
10220 path->peer->hostname,
10221 path->peer->host);
d62a17ae 10222 else
05864da7
DS
10223 vty_out(vty, " from %s",
10224 sockunion2str(&path->peer->su,
10225 buf,
10226 SU_ADDRSTRLEN));
d62a17ae 10227 }
d62a17ae 10228
05864da7 10229 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10230 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10231 else
10232 vty_out(vty, " (%s)",
10233 inet_ntop(AF_INET,
10234 &path->peer->remote_id, buf1,
10235 sizeof(buf1)));
d62a17ae 10236 }
05864da7 10237 }
9df8b37c 10238
05864da7
DS
10239 /*
10240 * Note when vrfid of nexthop is different from that of prefix
10241 */
10242 if (path->extra && path->extra->bgp_orig) {
10243 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10244
05864da7
DS
10245 if (json_paths) {
10246 const char *vn;
9df8b37c 10247
05864da7
DS
10248 if (path->extra->bgp_orig->inst_type
10249 == BGP_INSTANCE_TYPE_DEFAULT)
10250 vn = VRF_DEFAULT_NAME;
10251 else
10252 vn = path->extra->bgp_orig->name;
9df8b37c 10253
05864da7 10254 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10255
05864da7
DS
10256 if (nexthop_vrfid == VRF_UNKNOWN) {
10257 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10258 } else {
05864da7
DS
10259 json_object_int_add(json_path, "nhVrfId",
10260 (int)nexthop_vrfid);
9df8b37c 10261 }
05864da7
DS
10262 } else {
10263 if (nexthop_vrfid == VRF_UNKNOWN)
10264 vty_out(vty, " vrf ?");
137147c6
DS
10265 else {
10266 struct vrf *vrf;
10267
10268 vrf = vrf_lookup_by_id(nexthop_vrfid);
10269 vty_out(vty, " vrf %s(%u)",
10270 VRF_LOGNAME(vrf), nexthop_vrfid);
10271 }
9df8b37c 10272 }
05864da7 10273 }
9df8b37c 10274
05864da7
DS
10275 if (nexthop_self) {
10276 if (json_paths) {
10277 json_object_boolean_true_add(json_path,
10278 "announceNexthopSelf");
10279 } else {
10280 vty_out(vty, " announce-nh-self");
9df8b37c 10281 }
05864da7 10282 }
9df8b37c 10283
05864da7
DS
10284 if (!json_paths)
10285 vty_out(vty, "\n");
d62a17ae 10286
05864da7
DS
10287 /* display the link-local nexthop */
10288 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10289 if (json_paths) {
10290 json_nexthop_ll = json_object_new_object();
c949c771
DA
10291 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10292 &attr->mp_nexthop_local);
515c2602 10293
939a97f4 10294 if (path->peer->hostname)
515c2602
DA
10295 json_object_string_add(json_nexthop_ll,
10296 "hostname",
939a97f4 10297 path->peer->hostname);
515c2602 10298
05864da7
DS
10299 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10300 json_object_string_add(json_nexthop_ll, "scope",
10301 "link-local");
d62a17ae 10302
05864da7
DS
10303 json_object_boolean_true_add(json_nexthop_ll,
10304 "accessible");
d62a17ae 10305
05864da7 10306 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10307 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10308 "used");
10309 else
10310 json_object_boolean_true_add(
10311 json_nexthop_global, "used");
10312 } else {
10313 vty_out(vty, " (%s) %s\n",
10314 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10315 buf, INET6_ADDRSTRLEN),
10316 attr->mp_nexthop_prefer_global
10317 ? "(prefer-global)"
10318 : "(used)");
d62a17ae 10319 }
05864da7
DS
10320 }
10321 /* If we do not have a link-local nexthop then we must flag the
10322 global as "used" */
10323 else {
10324 if (json_paths)
10325 json_object_boolean_true_add(json_nexthop_global,
10326 "used");
10327 }
d62a17ae 10328
b5e140c8 10329 if (safi == SAFI_EVPN &&
5e4d4c8a 10330 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10331 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10332 }
10333
05864da7
DS
10334 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10335 * Int/Ext/Local, Atomic, best */
10336 if (json_paths)
10337 json_object_string_add(json_path, "origin",
10338 bgp_origin_long_str[attr->origin]);
10339 else
10340 vty_out(vty, " Origin %s",
10341 bgp_origin_long_str[attr->origin]);
9df8b37c 10342
05864da7 10343 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10344 if (json_paths)
05864da7 10345 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10346 else
05864da7
DS
10347 vty_out(vty, ", metric %u", attr->med);
10348 }
9df8b37c 10349
05864da7
DS
10350 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10351 if (json_paths)
0fbac0b4 10352 json_object_int_add(json_path, "locPrf",
05864da7
DS
10353 attr->local_pref);
10354 else
10355 vty_out(vty, ", localpref %u", attr->local_pref);
10356 }
9df8b37c 10357
05864da7
DS
10358 if (attr->weight != 0) {
10359 if (json_paths)
10360 json_object_int_add(json_path, "weight", attr->weight);
10361 else
10362 vty_out(vty, ", weight %u", attr->weight);
10363 }
9df8b37c 10364
05864da7
DS
10365 if (attr->tag != 0) {
10366 if (json_paths)
10367 json_object_int_add(json_path, "tag", attr->tag);
10368 else
10369 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10370 }
9df8b37c 10371
05864da7
DS
10372 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10373 if (json_paths)
10374 json_object_boolean_false_add(json_path, "valid");
10375 else
10376 vty_out(vty, ", invalid");
10377 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10378 if (json_paths)
10379 json_object_boolean_true_add(json_path, "valid");
10380 else
10381 vty_out(vty, ", valid");
10382 }
9df8b37c 10383
7d3cae70
DA
10384 if (json_paths)
10385 json_object_int_add(json_path, "version", bn->version);
10386
05864da7
DS
10387 if (path->peer != bgp->peer_self) {
10388 if (path->peer->as == path->peer->local_as) {
10389 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10390 if (json_paths)
10391 json_object_string_add(
10392 json_peer, "type",
10393 "confed-internal");
d62a17ae 10394 else
05864da7 10395 vty_out(vty, ", confed-internal");
d62a17ae 10396 } else {
05864da7
DS
10397 if (json_paths)
10398 json_object_string_add(
10399 json_peer, "type", "internal");
10400 else
10401 vty_out(vty, ", internal");
9df8b37c 10402 }
05864da7
DS
10403 } else {
10404 if (bgp_confederation_peers_check(bgp,
10405 path->peer->as)) {
10406 if (json_paths)
10407 json_object_string_add(
10408 json_peer, "type",
10409 "confed-external");
d62a17ae 10410 else
05864da7 10411 vty_out(vty, ", confed-external");
d62a17ae 10412 } else {
05864da7
DS
10413 if (json_paths)
10414 json_object_string_add(
10415 json_peer, "type", "external");
10416 else
10417 vty_out(vty, ", external");
d62a17ae 10418 }
10419 }
05864da7
DS
10420 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10421 if (json_paths) {
10422 json_object_boolean_true_add(json_path, "aggregated");
10423 json_object_boolean_true_add(json_path, "local");
10424 } else {
10425 vty_out(vty, ", aggregated, local");
10426 }
10427 } else if (path->type != ZEBRA_ROUTE_BGP) {
10428 if (json_paths)
10429 json_object_boolean_true_add(json_path, "sourced");
10430 else
10431 vty_out(vty, ", sourced");
10432 } else {
10433 if (json_paths) {
10434 json_object_boolean_true_add(json_path, "sourced");
10435 json_object_boolean_true_add(json_path, "local");
10436 } else {
10437 vty_out(vty, ", sourced, local");
d62a17ae 10438 }
05864da7 10439 }
718e3744 10440
05864da7 10441 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10442 if (json_paths)
05864da7
DS
10443 json_object_boolean_true_add(json_path,
10444 "atomicAggregate");
d62a17ae 10445 else
05864da7
DS
10446 vty_out(vty, ", atomic-aggregate");
10447 }
d62a17ae 10448
05864da7
DS
10449 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10450 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10451 && bgp_path_info_mpath_count(path))) {
10452 if (json_paths)
10453 json_object_boolean_true_add(json_path, "multipath");
10454 else
10455 vty_out(vty, ", multipath");
10456 }
50e05855 10457
05864da7
DS
10458 // Mark the bestpath(s)
10459 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10460 first_as = aspath_get_first_as(attr->aspath);
718e3744 10461
05864da7
DS
10462 if (json_paths) {
10463 if (!json_bestpath)
10464 json_bestpath = json_object_new_object();
10465 json_object_int_add(json_bestpath, "bestpathFromAs",
10466 first_as);
10467 } else {
10468 if (first_as)
10469 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10470 else
05864da7 10471 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10472 }
05864da7 10473 }
718e3744 10474
05864da7
DS
10475 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10476 if (json_paths) {
10477 if (!json_bestpath)
10478 json_bestpath = json_object_new_object();
10479 json_object_boolean_true_add(json_bestpath, "overall");
10480 json_object_string_add(
10481 json_bestpath, "selectionReason",
10482 bgp_path_selection_reason2str(bn->reason));
10483 } else {
10484 vty_out(vty, ", best");
10485 vty_out(vty, " (%s)",
10486 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10487 }
05864da7 10488 }
718e3744 10489
4027d19b 10490 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10491 if (json_paths)
10492 json_object_string_add(
10493 json_path, "rpkiValidationState",
4027d19b 10494 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10495 else
1d327209 10496 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10497 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10498 }
10499
05864da7
DS
10500 if (json_bestpath)
10501 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10502
05864da7
DS
10503 if (!json_paths)
10504 vty_out(vty, "\n");
10505
10506 /* Line 4 display Community */
29e72930 10507 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10508 if (json_paths) {
9a706b42
DA
10509 if (!bgp_attr_get_community(attr)->json)
10510 community_str(bgp_attr_get_community(attr),
c0945b78 10511 true, true);
9a706b42
DA
10512 json_object_lock(bgp_attr_get_community(attr)->json);
10513 json_object_object_add(
10514 json_path, "community",
10515 bgp_attr_get_community(attr)->json);
05864da7
DS
10516 } else {
10517 vty_out(vty, " Community: %s\n",
9a706b42 10518 bgp_attr_get_community(attr)->str);
d62a17ae 10519 }
05864da7 10520 }
718e3744 10521
05864da7
DS
10522 /* Line 5 display Extended-community */
10523 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10524 if (json_paths) {
10525 json_ext_community = json_object_new_object();
b53e67a3
DA
10526 json_object_string_add(
10527 json_ext_community, "string",
10528 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10529 json_object_object_add(json_path, "extendedCommunity",
10530 json_ext_community);
d62a17ae 10531 } else {
05864da7 10532 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10533 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10534 }
05864da7 10535 }
718e3744 10536
05864da7
DS
10537 /* Line 6 display Large community */
10538 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10539 if (json_paths) {
1bcf3a96
DA
10540 if (!bgp_attr_get_lcommunity(attr)->json)
10541 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10542 true, true);
1bcf3a96
DA
10543 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10544 json_object_object_add(
10545 json_path, "largeCommunity",
10546 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10547 } else {
10548 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10549 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10550 }
05864da7 10551 }
718e3744 10552
05864da7
DS
10553 /* Line 7 display Originator, Cluster-id */
10554 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10555 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10556 char buf[BUFSIZ] = {0};
10557
05864da7 10558 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10559 if (json_paths)
c949c771
DA
10560 json_object_string_addf(json_path,
10561 "originatorId", "%pI4",
10562 &attr->originator_id);
d62a17ae 10563 else
23d0a753
DA
10564 vty_out(vty, " Originator: %pI4",
10565 &attr->originator_id);
d62a17ae 10566 }
856ca177 10567
05864da7 10568 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10569 struct cluster_list *cluster =
10570 bgp_attr_get_cluster(attr);
05864da7 10571 int i;
d62a17ae 10572
10573 if (json_paths) {
05864da7
DS
10574 json_cluster_list = json_object_new_object();
10575 json_cluster_list_list =
10576 json_object_new_array();
10577
779fee93 10578 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10579 json_string = json_object_new_string(
779fee93
DS
10580 inet_ntop(AF_INET,
10581 &cluster->list[i],
10582 buf, sizeof(buf)));
05864da7
DS
10583 json_object_array_add(
10584 json_cluster_list_list,
10585 json_string);
10586 }
718e3744 10587
05864da7
DS
10588 /*
10589 * struct cluster_list does not have
10590 * "str" variable like aspath and community
10591 * do. Add this someday if someone asks
10592 * for it.
10593 * json_object_string_add(json_cluster_list,
779fee93 10594 * "string", cluster->str);
05864da7
DS
10595 */
10596 json_object_object_add(json_cluster_list,
10597 "list",
10598 json_cluster_list_list);
10599 json_object_object_add(json_path, "clusterList",
10600 json_cluster_list);
0dc8ee70 10601 } else {
05864da7
DS
10602 vty_out(vty, ", Cluster list: ");
10603
779fee93 10604 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10605 vty_out(vty, "%pI4 ",
779fee93 10606 &cluster->list[i]);
05864da7 10607 }
0dc8ee70 10608 }
d62a17ae 10609 }
718e3744 10610
d62a17ae 10611 if (!json_paths)
10612 vty_out(vty, "\n");
05864da7 10613 }
d62a17ae 10614
05864da7 10615 if (path->extra && path->extra->damp_info)
b4f7f45b 10616 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10617
05864da7
DS
10618 /* Remote Label */
10619 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10620 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10621 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10622 &bos);
d62a17ae 10623
05864da7
DS
10624 if (json_paths)
10625 json_object_int_add(json_path, "remoteLabel", label);
10626 else
10627 vty_out(vty, " Remote label: %d\n", label);
10628 }
d62a17ae 10629
e496b420
HS
10630 /* Remote SID */
10631 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10632 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10633 if (json_paths)
10634 json_object_string_add(json_path, "remoteSid", buf);
10635 else
10636 vty_out(vty, " Remote SID: %s\n", buf);
10637 }
10638
05864da7
DS
10639 /* Label Index */
10640 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10641 if (json_paths)
10642 json_object_int_add(json_path, "labelIndex",
10643 attr->label_index);
10644 else
10645 vty_out(vty, " Label Index: %d\n",
10646 attr->label_index);
10647 }
d62a17ae 10648
05864da7
DS
10649 /* Line 8 display Addpath IDs */
10650 if (path->addpath_rx_id
10651 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10652 if (json_paths) {
10653 json_object_int_add(json_path, "addpathRxId",
10654 path->addpath_rx_id);
d62a17ae 10655
05864da7
DS
10656 /* Keep backwards compatibility with the old API
10657 * by putting TX All's ID in the old field
10658 */
10659 json_object_int_add(
10660 json_path, "addpathTxId",
10661 path->tx_addpath
10662 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10663
05864da7
DS
10664 /* ... but create a specific field for each
10665 * strategy
10666 */
10667 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10668 json_object_int_add(
10669 json_path,
10670 bgp_addpath_names(i)->id_json_name,
10671 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10672 }
05864da7
DS
10673 } else {
10674 vty_out(vty, " AddPath ID: RX %u, ",
10675 path->addpath_rx_id);
d62a17ae 10676
05864da7 10677 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10678 }
05864da7 10679 }
520d5d76 10680
05864da7
DS
10681 /* If we used addpath to TX a non-bestpath we need to display
10682 * "Advertised to" on a path-by-path basis
10683 */
10684 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10685 first = 1;
dcc68b5e 10686
05864da7
DS
10687 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10688 addpath_capable =
10689 bgp_addpath_encode_tx(peer, afi, safi);
10690 has_adj = bgp_adj_out_lookup(
10691 peer, path->net,
10692 bgp_addpath_id_for_peer(peer, afi, safi,
10693 &path->tx_addpath));
10694
10695 if ((addpath_capable && has_adj)
10696 || (!addpath_capable && has_adj
10697 && CHECK_FLAG(path->flags,
10698 BGP_PATH_SELECTED))) {
10699 if (json_path && !json_adv_to)
10700 json_adv_to = json_object_new_object();
dcc68b5e 10701
05864da7
DS
10702 route_vty_out_advertised_to(
10703 vty, peer, &first,
10704 " Advertised to:", json_adv_to);
d62a17ae 10705 }
10706 }
718e3744 10707
05864da7
DS
10708 if (json_path) {
10709 if (json_adv_to) {
10710 json_object_object_add(
10711 json_path, "advertisedTo", json_adv_to);
d62a17ae 10712 }
05864da7
DS
10713 } else {
10714 if (!first) {
10715 vty_out(vty, "\n");
d62a17ae 10716 }
10717 }
05864da7 10718 }
b05a1c8b 10719
05864da7
DS
10720 /* Line 9 display Uptime */
10721 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10722 if (json_paths) {
10723 json_last_update = json_object_new_object();
10724 json_object_int_add(json_last_update, "epoch", tbuf);
10725 json_object_string_add(json_last_update, "string",
10726 ctime(&tbuf));
10727 json_object_object_add(json_path, "lastUpdate",
10728 json_last_update);
10729 } else
10730 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10731
05864da7
DS
10732 /* Line 10 display PMSI tunnel attribute, if present */
10733 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10734 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10735 bgp_attr_get_pmsi_tnl_type(attr),
10736 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10737
05864da7
DS
10738 if (json_paths) {
10739 json_pmsi = json_object_new_object();
10740 json_object_string_add(json_pmsi, "tunnelType", str);
10741 json_object_int_add(json_pmsi, "label",
10742 label2vni(&attr->label));
10743 json_object_object_add(json_path, "pmsi", json_pmsi);
10744 } else
10745 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10746 str, label2vni(&attr->label));
d62a17ae 10747 }
f1aa5d8a 10748
848e8cf6
DA
10749 if (path->peer->t_gr_restart &&
10750 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10751 unsigned long gr_remaining =
10752 thread_timer_remain_second(path->peer->t_gr_restart);
10753
10754 if (json_paths) {
10755 json_object_int_add(json_path,
10756 "gracefulRestartSecondsRemaining",
10757 gr_remaining);
10758 } else
10759 vty_out(vty,
10760 " Time until Graceful Restart stale route deleted: %lu\n",
10761 gr_remaining);
10762 }
10763
9a706b42
DA
10764 if (path->peer->t_llgr_stale[afi][safi] &&
10765 bgp_attr_get_community(attr) &&
10766 community_include(bgp_attr_get_community(attr),
10767 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10768 unsigned long llgr_remaining = thread_timer_remain_second(
10769 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10770
48ebba04
DA
10771 if (json_paths) {
10772 json_object_int_add(json_path, "llgrSecondsRemaining",
10773 llgr_remaining);
10774 } else
10775 vty_out(vty,
10776 " Time until Long-lived stale route deleted: %lu\n",
10777 llgr_remaining);
10778 }
10779
92269aa2
DS
10780 /* Output some debug about internal state of the dest flags */
10781 if (json_paths) {
10782 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10783 json_object_boolean_true_add(json_path, "processScheduled");
10784 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10785 json_object_boolean_true_add(json_path, "userCleared");
10786 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10787 json_object_boolean_true_add(json_path, "labelChanged");
10788 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10789 json_object_boolean_true_add(json_path, "registeredForLabel");
10790 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10791 json_object_boolean_true_add(json_path, "selectDefered");
10792 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10793 json_object_boolean_true_add(json_path, "fibInstalled");
10794 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10795 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10796
d62a17ae 10797 if (json_nexthop_global || json_nexthop_ll) {
10798 json_nexthops = json_object_new_array();
f1aa5d8a 10799
d62a17ae 10800 if (json_nexthop_global)
10801 json_object_array_add(json_nexthops,
10802 json_nexthop_global);
f1aa5d8a 10803
d62a17ae 10804 if (json_nexthop_ll)
10805 json_object_array_add(json_nexthops,
10806 json_nexthop_ll);
f1aa5d8a 10807
d62a17ae 10808 json_object_object_add(json_path, "nexthops",
10809 json_nexthops);
10810 }
10811
10812 json_object_object_add(json_path, "peer", json_peer);
10813 json_object_array_add(json_paths, json_path);
05864da7 10814 }
b366b518
BB
10815}
10816
96ade3ed 10817#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10818#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10819#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10820
a4d82a8a 10821static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10822 afi_t afi, safi_t safi, enum bgp_show_type type,
10823 bool use_json);
7f323236
DW
10824static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10825 const char *comstr, int exact, afi_t afi,
96c81f66 10826 safi_t safi, uint16_t show_flags);
d62a17ae 10827
1ae44dfc 10828static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10829 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10830 void *output_arg, const char *rd, int is_last,
96f3485c 10831 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10832 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10833 enum rpki_states rpki_target_state)
d62a17ae 10834{
40381db7 10835 struct bgp_path_info *pi;
9bcb3eef 10836 struct bgp_dest *dest;
2aad8c42
MS
10837 bool header = true;
10838 bool json_detail_header = false;
d62a17ae 10839 int display;
1ae44dfc
LB
10840 unsigned long output_count = 0;
10841 unsigned long total_count = 0;
d62a17ae 10842 struct prefix *p;
d62a17ae 10843 json_object *json_paths = NULL;
10844 int first = 1;
96f3485c
MK
10845 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10846 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10847 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10848
1ae44dfc 10849 if (output_cum && *output_cum != 0)
2aad8c42 10850 header = false;
1ae44dfc 10851
9386b588 10852 if (use_json && !*json_header_depth) {
96f3485c
MK
10853 if (all)
10854 *json_header_depth = 1;
10855 else {
10856 vty_out(vty, "{\n");
10857 *json_header_depth = 2;
10858 }
10859
d62a17ae 10860 vty_out(vty,
23d0a753
DA
10861 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10862 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10863 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10864 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10865 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10866 ? VRF_DEFAULT_NAME
10867 : bgp->name,
10868 table->version, &bgp->router_id,
01eced22 10869 bgp->default_local_pref, bgp->as);
9386b588 10870 if (rd) {
445c2480 10871 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10872 ++*json_header_depth;
10873 }
d62a17ae 10874 }
718e3744 10875
445c2480
DS
10876 if (use_json && rd) {
10877 vty_out(vty, " \"%s\" : { ", rd);
10878 }
10879
2aad8c42
MS
10880 /* Check for 'json detail', where we need header output once per dest */
10881 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10882 type != bgp_show_type_dampend_paths &&
10883 type != bgp_show_type_damp_neighbor &&
10884 type != bgp_show_type_flap_statistics &&
10885 type != bgp_show_type_flap_neighbor)
10886 json_detail_header = true;
10887
d62a17ae 10888 /* Start processing of routes. */
9bcb3eef
DS
10889 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10890 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10891 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10892 bool json_detail = json_detail_header;
b54892e0 10893
9bcb3eef 10894 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10895 if (pi == NULL)
98ce9a06 10896 continue;
d62a17ae 10897
98ce9a06 10898 display = 0;
98ce9a06
DS
10899 if (use_json)
10900 json_paths = json_object_new_array();
10901 else
10902 json_paths = NULL;
d62a17ae 10903
6f94b685 10904 for (; pi; pi = pi->next) {
9a706b42
DA
10905 struct community *picomm = NULL;
10906
10907 picomm = bgp_attr_get_community(pi->attr);
10908
98ce9a06 10909 total_count++;
1e2ce4f1 10910
7d3cae70
DA
10911 if (type == bgp_show_type_prefix_version) {
10912 uint32_t version =
10913 strtoul(output_arg, NULL, 10);
10914 if (dest->version < version)
10915 continue;
10916 }
10917
a70a28a5
DA
10918 if (type == bgp_show_type_community_alias) {
10919 char *alias = output_arg;
10920 char **communities;
10921 int num;
10922 bool found = false;
10923
9a706b42
DA
10924 if (picomm) {
10925 frrstr_split(picomm->str, " ",
10926 &communities, &num);
a70a28a5
DA
10927 for (int i = 0; i < num; i++) {
10928 const char *com2alias =
10929 bgp_community2alias(
10930 communities[i]);
cd9cc0e6
IR
10931 if (!found
10932 && strcmp(alias, com2alias)
10933 == 0)
a70a28a5 10934 found = true;
cd9cc0e6
IR
10935 XFREE(MTYPE_TMP,
10936 communities[i]);
a70a28a5 10937 }
cd9cc0e6 10938 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10939 }
10940
1bcf3a96
DA
10941 if (!found &&
10942 bgp_attr_get_lcommunity(pi->attr)) {
10943 frrstr_split(bgp_attr_get_lcommunity(
10944 pi->attr)
10945 ->str,
a70a28a5
DA
10946 " ", &communities, &num);
10947 for (int i = 0; i < num; i++) {
10948 const char *com2alias =
10949 bgp_community2alias(
10950 communities[i]);
cd9cc0e6
IR
10951 if (!found
10952 && strcmp(alias, com2alias)
10953 == 0)
a70a28a5 10954 found = true;
cd9cc0e6
IR
10955 XFREE(MTYPE_TMP,
10956 communities[i]);
a70a28a5 10957 }
cd9cc0e6 10958 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10959 }
10960
10961 if (!found)
10962 continue;
10963 }
10964
1e2ce4f1
DS
10965 if (type == bgp_show_type_rpki) {
10966 if (dest_p->family == AF_INET
10967 || dest_p->family == AF_INET6)
4027d19b 10968 rpki_curr_state = hook_call(
1e2ce4f1
DS
10969 bgp_rpki_prefix_status,
10970 pi->peer, pi->attr, dest_p);
4027d19b
DS
10971 if (rpki_target_state != RPKI_NOT_BEING_USED
10972 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10973 continue;
10974 }
10975
98ce9a06
DS
10976 if (type == bgp_show_type_flap_statistics
10977 || type == bgp_show_type_flap_neighbor
10978 || type == bgp_show_type_dampend_paths
10979 || type == bgp_show_type_damp_neighbor) {
40381db7 10980 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10981 continue;
10982 }
10983 if (type == bgp_show_type_regexp) {
10984 regex_t *regex = output_arg;
d62a17ae 10985
40381db7 10986 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10987 == REG_NOMATCH)
10988 continue;
10989 }
10990 if (type == bgp_show_type_prefix_list) {
10991 struct prefix_list *plist = output_arg;
d62a17ae 10992
9bcb3eef 10993 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10994 != PREFIX_PERMIT)
10995 continue;
10996 }
10997 if (type == bgp_show_type_filter_list) {
10998 struct as_list *as_list = output_arg;
d62a17ae 10999
40381db7 11000 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11001 != AS_FILTER_PERMIT)
11002 continue;
11003 }
11004 if (type == bgp_show_type_route_map) {
11005 struct route_map *rmap = output_arg;
9b6d8fcf 11006 struct bgp_path_info path;
98ce9a06 11007 struct attr dummy_attr;
b68885f9 11008 route_map_result_t ret;
d62a17ae 11009
6f4f49b2 11010 dummy_attr = *pi->attr;
d62a17ae 11011
40381db7 11012 path.peer = pi->peer;
9b6d8fcf 11013 path.attr = &dummy_attr;
d62a17ae 11014
1782514f 11015 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11016 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11017 if (ret == RMAP_DENYMATCH)
11018 continue;
11019 }
11020 if (type == bgp_show_type_neighbor
11021 || type == bgp_show_type_flap_neighbor
11022 || type == bgp_show_type_damp_neighbor) {
11023 union sockunion *su = output_arg;
11024
40381db7
DS
11025 if (pi->peer == NULL
11026 || pi->peer->su_remote == NULL
11027 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11028 continue;
11029 }
11030 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11031 uint32_t destination;
d62a17ae 11032
9bcb3eef 11033 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11034 if (IN_CLASSC(destination)
9bcb3eef 11035 && dest_p->prefixlen == 24)
98ce9a06
DS
11036 continue;
11037 if (IN_CLASSB(destination)
9bcb3eef 11038 && dest_p->prefixlen == 16)
98ce9a06
DS
11039 continue;
11040 if (IN_CLASSA(destination)
9bcb3eef 11041 && dest_p->prefixlen == 8)
98ce9a06
DS
11042 continue;
11043 }
11044 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11045 p = output_arg;
9bcb3eef 11046 if (!prefix_match(p, dest_p))
98ce9a06
DS
11047 continue;
11048 }
11049 if (type == bgp_show_type_community_all) {
9a706b42 11050 if (!picomm)
98ce9a06
DS
11051 continue;
11052 }
11053 if (type == bgp_show_type_community) {
11054 struct community *com = output_arg;
d62a17ae 11055
9a706b42 11056 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11057 continue;
11058 }
11059 if (type == bgp_show_type_community_exact) {
11060 struct community *com = output_arg;
d62a17ae 11061
9a706b42 11062 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11063 continue;
11064 }
11065 if (type == bgp_show_type_community_list) {
11066 struct community_list *list = output_arg;
d62a17ae 11067
9a706b42 11068 if (!community_list_match(picomm, list))
98ce9a06
DS
11069 continue;
11070 }
a4d82a8a 11071 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11072 struct community_list *list = output_arg;
d62a17ae 11073
9a706b42 11074 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11075 continue;
11076 }
11077 if (type == bgp_show_type_lcommunity) {
11078 struct lcommunity *lcom = output_arg;
d62a17ae 11079
1bcf3a96
DA
11080 if (!bgp_attr_get_lcommunity(pi->attr) ||
11081 !lcommunity_match(
11082 bgp_attr_get_lcommunity(pi->attr),
11083 lcom))
98ce9a06
DS
11084 continue;
11085 }
36a206db 11086
11087 if (type == bgp_show_type_lcommunity_exact) {
11088 struct lcommunity *lcom = output_arg;
11089
1bcf3a96
DA
11090 if (!bgp_attr_get_lcommunity(pi->attr) ||
11091 !lcommunity_cmp(
11092 bgp_attr_get_lcommunity(pi->attr),
11093 lcom))
36a206db 11094 continue;
11095 }
98ce9a06
DS
11096 if (type == bgp_show_type_lcommunity_list) {
11097 struct community_list *list = output_arg;
d62a17ae 11098
1bcf3a96
DA
11099 if (!lcommunity_list_match(
11100 bgp_attr_get_lcommunity(pi->attr),
11101 list))
98ce9a06
DS
11102 continue;
11103 }
36a206db 11104 if (type
11105 == bgp_show_type_lcommunity_list_exact) {
11106 struct community_list *list = output_arg;
11107
11108 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11109 bgp_attr_get_lcommunity(pi->attr),
11110 list))
36a206db 11111 continue;
11112 }
98ce9a06 11113 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11114 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11115 continue;
11116 }
11117 if (type == bgp_show_type_dampend_paths
11118 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11119 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11120 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11121 continue;
11122 }
11123
11124 if (!use_json && header) {
23d0a753
DA
11125 vty_out(vty,
11126 "BGP table version is %" PRIu64
11127 ", local router ID is %pI4, vrf id ",
11128 table->version, &bgp->router_id);
9df8b37c
PZ
11129 if (bgp->vrf_id == VRF_UNKNOWN)
11130 vty_out(vty, "%s", VRFID_NONE_STR);
11131 else
11132 vty_out(vty, "%u", bgp->vrf_id);
11133 vty_out(vty, "\n");
01eced22
AD
11134 vty_out(vty, "Default local pref %u, ",
11135 bgp->default_local_pref);
11136 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11137 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11138 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11139 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11140 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11141 if (type == bgp_show_type_dampend_paths
11142 || type == bgp_show_type_damp_neighbor)
98ce9a06 11143 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11144 else if (type == bgp_show_type_flap_statistics
11145 || type == bgp_show_type_flap_neighbor)
98ce9a06 11146 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11147 else
ae248832
MK
11148 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11149 : BGP_SHOW_HEADER));
2aad8c42
MS
11150 header = false;
11151
11152 } else if (json_detail && json_paths != NULL) {
11153 const struct prefix_rd *prd;
11154 json_object *jtemp;
11155
11156 /* Use common detail header, for most types;
11157 * need a json 'object'.
11158 */
11159
11160 jtemp = json_object_new_object();
11161 prd = bgp_rd_from_dest(dest, safi);
11162
11163 route_vty_out_detail_header(
11164 vty, bgp, dest, prd, table->afi,
11165 safi, jtemp);
11166
11167 json_object_array_add(json_paths, jtemp);
11168
11169 json_detail = false;
d62a17ae 11170 }
2aad8c42 11171
98ce9a06
DS
11172 if (rd != NULL && !display && !output_count) {
11173 if (!use_json)
11174 vty_out(vty,
11175 "Route Distinguisher: %s\n",
11176 rd);
d62a17ae 11177 }
98ce9a06
DS
11178 if (type == bgp_show_type_dampend_paths
11179 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11180 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11181 AFI_IP, safi, use_json,
11182 json_paths);
98ce9a06
DS
11183 else if (type == bgp_show_type_flap_statistics
11184 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11185 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11186 AFI_IP, safi, use_json,
11187 json_paths);
f280c93b
DA
11188 else {
11189 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11190 route_vty_out_detail(
11191 vty, bgp, dest, pi,
11192 family2afi(dest_p->family),
11193 safi, RPKI_NOT_BEING_USED,
11194 json_paths);
11195 else
11196 route_vty_out(vty, dest_p, pi, display,
11197 safi, json_paths, wide);
11198 }
98ce9a06 11199 display++;
d62a17ae 11200 }
11201
98ce9a06
DS
11202 if (display) {
11203 output_count++;
11204 if (!use_json)
11205 continue;
11206
625d2931 11207 /* encode prefix */
9bcb3eef 11208 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11209 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11210
1840384b 11211
b54892e0
DS
11212 bgp_fs_nlri_get_string(
11213 (unsigned char *)
9bcb3eef
DS
11214 dest_p->u.prefix_flowspec.ptr,
11215 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11216 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11217 family2afi(dest_p->u
11218 .prefix_flowspec.family));
625d2931 11219 if (first)
b54892e0 11220 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11221 dest_p->u.prefix_flowspec
b54892e0 11222 .prefixlen);
625d2931 11223 else
b54892e0 11224 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11225 dest_p->u.prefix_flowspec
b54892e0 11226 .prefixlen);
625d2931 11227 } else {
625d2931 11228 if (first)
1b78780b 11229 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11230 else
1b78780b 11231 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11232 }
3757f964 11233 vty_json(vty, json_paths);
449feb8e 11234 json_paths = NULL;
98ce9a06 11235 first = 0;
1f83ed02
DS
11236 } else
11237 json_object_free(json_paths);
98ce9a06
DS
11238 }
11239
1ae44dfc
LB
11240 if (output_cum) {
11241 output_count += *output_cum;
11242 *output_cum = output_count;
11243 }
11244 if (total_cum) {
11245 total_count += *total_cum;
11246 *total_cum = total_count;
11247 }
d62a17ae 11248 if (use_json) {
9386b588 11249 if (rd) {
a4d82a8a 11250 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11251 }
11252 if (is_last) {
a4d82a8a
PZ
11253 unsigned long i;
11254 for (i = 0; i < *json_header_depth; ++i)
11255 vty_out(vty, " } ");
96f3485c
MK
11256 if (!all)
11257 vty_out(vty, "\n");
9386b588 11258 }
d62a17ae 11259 } else {
1ae44dfc
LB
11260 if (is_last) {
11261 /* No route is displayed */
11262 if (output_count == 0) {
11263 if (type == bgp_show_type_normal)
11264 vty_out(vty,
11265 "No BGP prefixes displayed, %ld exist\n",
11266 total_count);
11267 } else
d62a17ae 11268 vty_out(vty,
1ae44dfc
LB
11269 "\nDisplayed %ld routes and %ld total paths\n",
11270 output_count, total_count);
11271 }
d62a17ae 11272 }
718e3744 11273
d62a17ae 11274 return CMD_SUCCESS;
718e3744 11275}
11276
1ae44dfc
LB
11277int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11278 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11279 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11280{
9bcb3eef 11281 struct bgp_dest *dest, *next;
1ae44dfc
LB
11282 unsigned long output_cum = 0;
11283 unsigned long total_cum = 0;
9386b588 11284 unsigned long json_header_depth = 0;
67009e22 11285 struct bgp_table *itable;
0136788c 11286 bool show_msg;
96c81f66 11287 uint16_t show_flags = 0;
0136788c
LB
11288
11289 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11290
96f3485c
MK
11291 if (use_json)
11292 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11293
9bcb3eef
DS
11294 for (dest = bgp_table_top(table); dest; dest = next) {
11295 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11296
9bcb3eef
DS
11297 next = bgp_route_next(dest);
11298 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11299 continue;
67009e22 11300
9bcb3eef 11301 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11302 if (itable != NULL) {
1ae44dfc 11303 struct prefix_rd prd;
06b9f471 11304 char rd[RD_ADDRSTRLEN];
1ae44dfc 11305
9bcb3eef 11306 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11307 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11308 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11309 rd, next == NULL, &output_cum,
11310 &total_cum, &json_header_depth,
1e2ce4f1 11311 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11312 if (next == NULL)
11313 show_msg = false;
1ae44dfc
LB
11314 }
11315 }
0136788c
LB
11316 if (show_msg) {
11317 if (output_cum == 0)
11318 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11319 total_cum);
11320 else
11321 vty_out(vty,
11322 "\nDisplayed %ld routes and %ld total paths\n",
11323 output_cum, total_cum);
11324 }
1ae44dfc
LB
11325 return CMD_SUCCESS;
11326}
2aad8c42 11327
d62a17ae 11328static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11329 enum bgp_show_type type, void *output_arg,
96c81f66 11330 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11331{
d62a17ae 11332 struct bgp_table *table;
9386b588 11333 unsigned long json_header_depth = 0;
96f3485c 11334 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11335
d62a17ae 11336 if (bgp == NULL) {
11337 bgp = bgp_get_default();
11338 }
fee0f4c6 11339
d62a17ae 11340 if (bgp == NULL) {
11341 if (!use_json)
11342 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11343 else
11344 vty_out(vty, "{}\n");
d62a17ae 11345 return CMD_WARNING;
11346 }
4dd6177e 11347
cd8c2a27
MS
11348 /* Labeled-unicast routes live in the unicast table. */
11349 if (safi == SAFI_LABELED_UNICAST)
11350 safi = SAFI_UNICAST;
11351
1ae44dfc 11352 table = bgp->rib[afi][safi];
d62a17ae 11353 /* use MPLS and ENCAP specific shows until they are merged */
11354 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11355 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11356 output_arg, use_json);
d62a17ae 11357 }
dba3c1d3
PG
11358
11359 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11360 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11361 output_arg, use_json,
11362 1, NULL, NULL);
11363 }
fee0f4c6 11364
96f3485c 11365 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11366 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11367 rpki_target_state);
fee0f4c6 11368}
11369
d62a17ae 11370static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11371 safi_t safi, uint16_t show_flags)
f186de26 11372{
d62a17ae 11373 struct listnode *node, *nnode;
11374 struct bgp *bgp;
11375 int is_first = 1;
9f049418 11376 bool route_output = false;
96f3485c 11377 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11378
d62a17ae 11379 if (use_json)
11380 vty_out(vty, "{\n");
9f689658 11381
d62a17ae 11382 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11383 route_output = true;
d62a17ae 11384 if (use_json) {
11385 if (!is_first)
11386 vty_out(vty, ",\n");
11387 else
11388 is_first = 0;
11389
11390 vty_out(vty, "\"%s\":",
11391 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11392 ? VRF_DEFAULT_NAME
d62a17ae 11393 : bgp->name);
11394 } else {
11395 vty_out(vty, "\nInstance %s:\n",
11396 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11397 ? VRF_DEFAULT_NAME
d62a17ae 11398 : bgp->name);
11399 }
11400 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11401 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11402 }
9f689658 11403
d62a17ae 11404 if (use_json)
11405 vty_out(vty, "}\n");
9f049418
DS
11406 else if (!route_output)
11407 vty_out(vty, "%% BGP instance not found\n");
f186de26 11408}
11409
718e3744 11410/* Header of detailed BGP route information */
d62a17ae 11411void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11412 struct bgp_dest *dest,
11413 const struct prefix_rd *prd,
d62a17ae 11414 afi_t afi, safi_t safi, json_object *json)
11415{
40381db7 11416 struct bgp_path_info *pi;
b54892e0 11417 const struct prefix *p;
d62a17ae 11418 struct peer *peer;
11419 struct listnode *node, *nnode;
06b9f471 11420 char buf1[RD_ADDRSTRLEN];
d62a17ae 11421 int count = 0;
11422 int best = 0;
11423 int suppress = 0;
c5f1e1b2
C
11424 int accept_own = 0;
11425 int route_filter_translated_v4 = 0;
11426 int route_filter_v4 = 0;
11427 int route_filter_translated_v6 = 0;
11428 int route_filter_v6 = 0;
11429 int llgr_stale = 0;
11430 int no_llgr = 0;
11431 int accept_own_nexthop = 0;
11432 int blackhole = 0;
d62a17ae 11433 int no_export = 0;
11434 int no_advertise = 0;
11435 int local_as = 0;
c5f1e1b2 11436 int no_peer = 0;
d62a17ae 11437 int first = 1;
11438 int has_valid_label = 0;
11439 mpls_label_t label = 0;
11440 json_object *json_adv_to = NULL;
67f67ba4
DA
11441 uint32_t ttl = 0;
11442 uint32_t bos = 0;
11443 uint32_t exp = 0;
9bedbb1e 11444
67f67ba4 11445 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11446
67f67ba4
DA
11447 p = bgp_dest_get_prefix(dest);
11448 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11449
44c69747 11450 if (safi == SAFI_EVPN) {
d62a17ae 11451
44c69747 11452 if (!json) {
2dbe669b 11453 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11454 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11455 : "",
2dbe669b 11456 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11457 } else {
11458 json_object_string_add(json, "rd",
11459 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11460 "");
11461 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11462 }
11463 } else {
11464 if (!json) {
9119ef3a
DA
11465 vty_out(vty,
11466 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11467 "\n",
d62a17ae 11468 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11469 ? prefix_rd2str(prd, buf1,
11470 sizeof(buf1))
11471 : ""),
9119ef3a
DA
11472 safi == SAFI_MPLS_VPN ? ":" : "", p,
11473 dest->version);
cd1964ff 11474
9119ef3a 11475 } else {
67d7e256 11476 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11477 json_object_int_add(json, "version", dest->version);
11478
11479 }
44c69747
LK
11480 }
11481
11482 if (has_valid_label) {
11483 if (json)
11484 json_object_int_add(json, "localLabel", label);
11485 else
d62a17ae 11486 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11487 }
11488
11489 if (!json)
d62a17ae 11490 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11491 vty_out(vty, "not allocated\n");
718e3744 11492
9bcb3eef 11493 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11494 struct community *picomm = NULL;
11495
11496 picomm = bgp_attr_get_community(pi->attr);
11497
d62a17ae 11498 count++;
40381db7 11499 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11500 best = count;
4056a5f6 11501 if (bgp_path_suppressed(pi))
d62a17ae 11502 suppress = 1;
cee9c031 11503
9a706b42 11504 if (!picomm)
cee9c031
QY
11505 continue;
11506
11507 no_advertise += community_include(
9a706b42
DA
11508 picomm, COMMUNITY_NO_ADVERTISE);
11509 no_export +=
11510 community_include(picomm, COMMUNITY_NO_EXPORT);
11511 local_as +=
11512 community_include(picomm, COMMUNITY_LOCAL_AS);
11513 accept_own +=
11514 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11515 route_filter_translated_v4 += community_include(
9a706b42 11516 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11517 route_filter_translated_v6 += community_include(
9a706b42 11518 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11519 route_filter_v4 += community_include(
9a706b42 11520 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11521 route_filter_v6 += community_include(
9a706b42
DA
11522 picomm, COMMUNITY_ROUTE_FILTER_v6);
11523 llgr_stale +=
11524 community_include(picomm, COMMUNITY_LLGR_STALE);
11525 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11526 accept_own_nexthop += community_include(
11527 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11528 blackhole +=
11529 community_include(picomm, COMMUNITY_BLACKHOLE);
11530 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11531 }
718e3744 11532 }
718e3744 11533
d62a17ae 11534 if (!json) {
11535 vty_out(vty, "Paths: (%d available", count);
11536 if (best) {
11537 vty_out(vty, ", best #%d", best);
b84060bb
PG
11538 if (safi == SAFI_UNICAST) {
11539 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11540 vty_out(vty, ", table %s",
11541 VRF_DEFAULT_NAME);
11542 else
11543 vty_out(vty, ", vrf %s",
11544 bgp->name);
11545 }
d62a17ae 11546 } else
11547 vty_out(vty, ", no best path");
11548
c5f1e1b2
C
11549 if (accept_own)
11550 vty_out(vty,
11551 ", accept own local route exported and imported in different VRF");
11552 else if (route_filter_translated_v4)
11553 vty_out(vty,
11554 ", mark translated RTs for VPNv4 route filtering");
11555 else if (route_filter_v4)
11556 vty_out(vty,
11557 ", attach RT as-is for VPNv4 route filtering");
11558 else if (route_filter_translated_v6)
11559 vty_out(vty,
11560 ", mark translated RTs for VPNv6 route filtering");
11561 else if (route_filter_v6)
11562 vty_out(vty,
11563 ", attach RT as-is for VPNv6 route filtering");
11564 else if (llgr_stale)
11565 vty_out(vty,
1479ed2f 11566 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11567 else if (no_llgr)
11568 vty_out(vty,
11569 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11570 else if (accept_own_nexthop)
11571 vty_out(vty,
11572 ", accept local nexthop");
11573 else if (blackhole)
11574 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11575 else if (no_export)
11576 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11577 else if (no_advertise)
11578 vty_out(vty, ", not advertised to any peer");
d62a17ae 11579 else if (local_as)
11580 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11581 else if (no_peer)
11582 vty_out(vty,
11583 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11584
11585 if (suppress)
11586 vty_out(vty,
11587 ", Advertisements suppressed by an aggregate.");
11588 vty_out(vty, ")\n");
11589 }
718e3744 11590
d62a17ae 11591 /* If we are not using addpath then we can display Advertised to and
11592 * that will
11593 * show what peers we advertised the bestpath to. If we are using
11594 * addpath
11595 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11596 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11597 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11598 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11599 if (json && !json_adv_to)
11600 json_adv_to = json_object_new_object();
11601
11602 route_vty_out_advertised_to(
11603 vty, peer, &first,
11604 " Advertised to non peer-group peers:\n ",
11605 json_adv_to);
11606 }
11607 }
11608
11609 if (json) {
11610 if (json_adv_to) {
11611 json_object_object_add(json, "advertisedTo",
11612 json_adv_to);
11613 }
11614 } else {
11615 if (first)
11616 vty_out(vty, " Not advertised to any peer");
11617 vty_out(vty, "\n");
11618 }
11619 }
718e3744 11620}
11621
edfee30d 11622static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11623 struct bgp_dest *bgp_node, struct vty *vty,
11624 struct bgp *bgp, afi_t afi, safi_t safi,
11625 json_object *json, enum bgp_path_type pathtype,
4027d19b 11626 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11627{
11628 struct bgp_path_info *pi;
11629 int header = 1;
11630 char rdbuf[RD_ADDRSTRLEN];
11631 json_object *json_header = NULL;
11632 json_object *json_paths = NULL;
4933eaaf 11633 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11634
9bcb3eef 11635 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11636 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11637
11638 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11639 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11640 pi->peer, pi->attr, p);
4933eaaf 11641
4027d19b
DS
11642 if (rpki_target_state != RPKI_NOT_BEING_USED
11643 && rpki_curr_state != rpki_target_state)
4933eaaf 11644 continue;
44c69747
LK
11645
11646 if (json && !json_paths) {
11647 /* Instantiate json_paths only if path is valid */
11648 json_paths = json_object_new_array();
11649 if (pfx_rd) {
11650 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11651 json_header = json_object_new_object();
11652 } else
11653 json_header = json;
11654 }
11655
11656 if (header) {
11657 route_vty_out_detail_header(
11658 vty, bgp, bgp_node, pfx_rd,
11659 AFI_IP, safi, json_header);
11660 header = 0;
11661 }
11662 (*display)++;
11663
11664 if (pathtype == BGP_PATH_SHOW_ALL
11665 || (pathtype == BGP_PATH_SHOW_BESTPATH
11666 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11667 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11668 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11669 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11670 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11671 safi, rpki_curr_state, json_paths);
44c69747
LK
11672 }
11673
11674 if (json && json_paths) {
11675 json_object_object_add(json_header, "paths", json_paths);
11676
11677 if (pfx_rd)
11678 json_object_object_add(json, rdbuf, json_header);
11679 }
11680}
11681
2aad8c42
MS
11682/*
11683 * Return rd based on safi
11684 */
11685static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11686 safi_t safi)
11687{
11688 switch (safi) {
11689 case SAFI_MPLS_VPN:
11690 case SAFI_ENCAP:
11691 case SAFI_EVPN:
11692 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11693 default:
11694 return NULL;
11695
11696 }
11697}
11698
718e3744 11699/* Display specified route of BGP table. */
d62a17ae 11700static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11701 struct bgp_table *rib, const char *ip_str,
11702 afi_t afi, safi_t safi,
4027d19b 11703 enum rpki_states rpki_target_state,
d62a17ae 11704 struct prefix_rd *prd, int prefix_check,
9f049418 11705 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11706{
11707 int ret;
d62a17ae 11708 int display = 0;
11709 struct prefix match;
9bcb3eef
DS
11710 struct bgp_dest *dest;
11711 struct bgp_dest *rm;
d62a17ae 11712 struct bgp_table *table;
11713 json_object *json = NULL;
11714 json_object *json_paths = NULL;
11715
11716 /* Check IP address argument. */
11717 ret = str2prefix(ip_str, &match);
11718 if (!ret) {
11719 vty_out(vty, "address is malformed\n");
11720 return CMD_WARNING;
11721 }
718e3744 11722
d62a17ae 11723 match.family = afi2family(afi);
b05a1c8b 11724
44c69747 11725 if (use_json)
d62a17ae 11726 json = json_object_new_object();
718e3744 11727
44c69747 11728 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11729 for (dest = bgp_table_top(rib); dest;
11730 dest = bgp_route_next(dest)) {
11731 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11732
9bcb3eef 11733 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11734 continue;
9bcb3eef 11735 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11736 if (!table)
ea47320b 11737 continue;
d62a17ae 11738
4953391b
DA
11739 rm = bgp_node_match(table, &match);
11740 if (rm == NULL)
ea47320b 11741 continue;
d62a17ae 11742
9bcb3eef 11743 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11744 if (prefix_check
b54892e0 11745 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11746 bgp_dest_unlock_node(rm);
ea47320b
DL
11747 continue;
11748 }
d62a17ae 11749
9bcb3eef 11750 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11751 bgp, afi, safi, json, pathtype,
4027d19b 11752 &display, rpki_target_state);
44c69747 11753
9bcb3eef 11754 bgp_dest_unlock_node(rm);
44c69747
LK
11755 }
11756 } else if (safi == SAFI_EVPN) {
9bcb3eef 11757 struct bgp_dest *longest_pfx;
cded3b72 11758 bool is_exact_pfxlen_match = false;
44c69747 11759
9bcb3eef
DS
11760 for (dest = bgp_table_top(rib); dest;
11761 dest = bgp_route_next(dest)) {
11762 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11763
9bcb3eef 11764 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11765 continue;
9bcb3eef 11766 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11767 if (!table)
11768 continue;
11769
11770 longest_pfx = NULL;
cded3b72 11771 is_exact_pfxlen_match = false;
44c69747
LK
11772 /*
11773 * Search through all the prefixes for a match. The
11774 * pfx's are enumerated in ascending order of pfxlens.
11775 * So, the last pfx match is the longest match. Set
11776 * is_exact_pfxlen_match when we get exact pfxlen match
11777 */
11778 for (rm = bgp_table_top(table); rm;
11779 rm = bgp_route_next(rm)) {
b54892e0 11780 const struct prefix *rm_p =
9bcb3eef 11781 bgp_dest_get_prefix(rm);
44c69747
LK
11782 /*
11783 * Get prefixlen of the ip-prefix within type5
11784 * evpn route
11785 */
b54892e0
DS
11786 if (evpn_type5_prefix_match(rm_p, &match)
11787 && rm->info) {
44c69747
LK
11788 longest_pfx = rm;
11789 int type5_pfxlen =
b54892e0
DS
11790 bgp_evpn_get_type5_prefixlen(
11791 rm_p);
44c69747 11792 if (type5_pfxlen == match.prefixlen) {
cded3b72 11793 is_exact_pfxlen_match = true;
9bcb3eef 11794 bgp_dest_unlock_node(rm);
44c69747
LK
11795 break;
11796 }
d62a17ae 11797 }
11798 }
ea47320b 11799
44c69747
LK
11800 if (!longest_pfx)
11801 continue;
11802
11803 if (prefix_check && !is_exact_pfxlen_match)
11804 continue;
11805
11806 rm = longest_pfx;
9bcb3eef 11807 bgp_dest_lock_node(rm);
44c69747 11808
9bcb3eef 11809 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11810 bgp, afi, safi, json, pathtype,
4027d19b 11811 &display, rpki_target_state);
44c69747 11812
9bcb3eef 11813 bgp_dest_unlock_node(rm);
d62a17ae 11814 }
98a9dbc7 11815 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11816 if (use_json)
11817 json_paths = json_object_new_array();
11818
63a0b7a9
PG
11819 display = bgp_flowspec_display_match_per_ip(afi, rib,
11820 &match, prefix_check,
11821 vty,
11822 use_json,
11823 json_paths);
d5f20468
SP
11824 if (use_json) {
11825 if (display)
11826 json_object_object_add(json, "paths",
11827 json_paths);
11828 else
11829 json_object_free(json_paths);
11830 }
d62a17ae 11831 } else {
4953391b
DA
11832 dest = bgp_node_match(rib, &match);
11833 if (dest != NULL) {
9bcb3eef 11834 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11835 if (!prefix_check
9bcb3eef
DS
11836 || dest_p->prefixlen == match.prefixlen) {
11837 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11838 safi, json, pathtype,
4027d19b 11839 &display, rpki_target_state);
d62a17ae 11840 }
11841
9bcb3eef 11842 bgp_dest_unlock_node(dest);
d62a17ae 11843 }
11844 }
e5eee9af 11845
d62a17ae 11846 if (use_json) {
75eeda93 11847 vty_json(vty, json);
d62a17ae 11848 } else {
11849 if (!display) {
11850 vty_out(vty, "%% Network not in table\n");
11851 return CMD_WARNING;
11852 }
11853 }
b05a1c8b 11854
d62a17ae 11855 return CMD_SUCCESS;
718e3744 11856}
11857
fee0f4c6 11858/* Display specified route of Main RIB */
d62a17ae 11859static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11860 afi_t afi, safi_t safi, struct prefix_rd *prd,
11861 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11862 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11863{
9b86009a 11864 if (!bgp) {
d62a17ae 11865 bgp = bgp_get_default();
9b86009a
RW
11866 if (!bgp) {
11867 if (!use_json)
11868 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11869 else
11870 vty_out(vty, "{}\n");
9b86009a
RW
11871 return CMD_WARNING;
11872 }
11873 }
d62a17ae 11874
11875 /* labeled-unicast routes live in the unicast table */
11876 if (safi == SAFI_LABELED_UNICAST)
11877 safi = SAFI_UNICAST;
11878
11879 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11880 afi, safi, rpki_target_state, prd,
8aa22bbb 11881 prefix_check, pathtype, use_json);
d62a17ae 11882}
11883
11884static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11885 struct cmd_token **argv, bool exact, afi_t afi,
11886 safi_t safi, bool uj)
d62a17ae 11887{
11888 struct lcommunity *lcom;
11889 struct buffer *b;
11890 int i;
11891 char *str;
11892 int first = 0;
96c81f66 11893 uint16_t show_flags = 0;
4f28b2b5 11894 int ret;
96f3485c
MK
11895
11896 if (uj)
11897 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11898
11899 b = buffer_new(1024);
11900 for (i = 0; i < argc; i++) {
11901 if (first)
11902 buffer_putc(b, ' ');
11903 else {
11904 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11905 first = 1;
11906 buffer_putstr(b, argv[i]->arg);
11907 }
11908 }
11909 }
11910 buffer_putc(b, '\0');
57d187bc 11911
d62a17ae 11912 str = buffer_getstr(b);
11913 buffer_free(b);
57d187bc 11914
d62a17ae 11915 lcom = lcommunity_str2com(str);
11916 XFREE(MTYPE_TMP, str);
11917 if (!lcom) {
11918 vty_out(vty, "%% Large-community malformed\n");
11919 return CMD_WARNING;
11920 }
57d187bc 11921
4f28b2b5 11922 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11923 (exact ? bgp_show_type_lcommunity_exact
11924 : bgp_show_type_lcommunity),
11925 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11926
11927 lcommunity_free(&lcom);
11928 return ret;
57d187bc
JS
11929}
11930
d62a17ae 11931static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11932 const char *lcom, bool exact, afi_t afi,
11933 safi_t safi, bool uj)
57d187bc 11934{
d62a17ae 11935 struct community_list *list;
96c81f66 11936 uint16_t show_flags = 0;
96f3485c
MK
11937
11938 if (uj)
11939 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11940
57d187bc 11941
e237b0d2 11942 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11943 LARGE_COMMUNITY_LIST_MASTER);
11944 if (list == NULL) {
11945 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11946 lcom);
11947 return CMD_WARNING;
11948 }
57d187bc 11949
36a206db 11950 return bgp_show(vty, bgp, afi, safi,
11951 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11952 : bgp_show_type_lcommunity_list),
1e2ce4f1 11953 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11954}
11955
52951b63
DS
11956DEFUN (show_ip_bgp_large_community_list,
11957 show_ip_bgp_large_community_list_cmd,
77a3a95e 11958 "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
11959 SHOW_STR
11960 IP_STR
11961 BGP_STR
11962 BGP_INSTANCE_HELP_STR
9bedbb1e 11963 BGP_AFI_HELP_STR
4dd6177e 11964 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11965 "Display routes matching the large-community-list\n"
11966 "large-community-list number\n"
11967 "large-community-list name\n"
36a206db 11968 "Exact match of the large-communities\n"
52951b63
DS
11969 JSON_STR)
11970{
d62a17ae 11971 afi_t afi = AFI_IP6;
11972 safi_t safi = SAFI_UNICAST;
11973 int idx = 0;
36a206db 11974 bool exact_match = 0;
4d678463 11975 struct bgp *bgp = NULL;
9f049418 11976 bool uj = use_json(argc, argv);
d62a17ae 11977
ef3364f0
DA
11978 if (uj)
11979 argc--;
4d678463 11980
ef3364f0
DA
11981 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11982 &bgp, uj);
11983 if (!idx)
11984 return CMD_WARNING;
d62a17ae 11985
11986 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11987
11988 const char *clist_number_or_name = argv[++idx]->arg;
11989
11990 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11991 exact_match = 1;
11992
11993 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11994 exact_match, afi, safi, uj);
52951b63
DS
11995}
11996DEFUN (show_ip_bgp_large_community,
11997 show_ip_bgp_large_community_cmd,
36a206db 11998 "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
11999 SHOW_STR
12000 IP_STR
12001 BGP_STR
12002 BGP_INSTANCE_HELP_STR
9bedbb1e 12003 BGP_AFI_HELP_STR
4dd6177e 12004 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12005 "Display routes matching the large-communities\n"
12006 "List of large-community numbers\n"
36a206db 12007 "Exact match of the large-communities\n"
52951b63
DS
12008 JSON_STR)
12009{
d62a17ae 12010 afi_t afi = AFI_IP6;
12011 safi_t safi = SAFI_UNICAST;
12012 int idx = 0;
36a206db 12013 bool exact_match = 0;
4d678463 12014 struct bgp *bgp = NULL;
9f049418 12015 bool uj = use_json(argc, argv);
96c81f66 12016 uint16_t show_flags = 0;
d62a17ae 12017
96f3485c
MK
12018 if (uj) {
12019 argc--;
12020 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12021 }
4d678463 12022
96f3485c
MK
12023 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12024 &bgp, uj);
12025 if (!idx)
12026 return CMD_WARNING;
d62a17ae 12027
36a206db 12028 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12029 if (argv_find(argv, argc, "exact-match", &idx))
12030 exact_match = 1;
12031 return bgp_show_lcommunity(vty, bgp, argc, argv,
12032 exact_match, afi, safi, uj);
12033 } else
d62a17ae 12034 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12035 bgp_show_type_lcommunity_all, NULL, show_flags,
12036 RPKI_NOT_BEING_USED);
52951b63
DS
12037}
12038
71f1613a
DA
12039static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12040 safi_t safi, struct json_object *json_array);
d62a17ae 12041static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12042 safi_t safi, struct json_object *json);
e01ca200 12043
7b2ff250 12044
9ab0cf58
PG
12045DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12046 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12047 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12048 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12049{
12050 bool uj = use_json(argc, argv);
12051 struct bgp *bgp = NULL;
ec76a1d1
DA
12052 safi_t safi = SAFI_UNICAST;
12053 afi_t afi = AFI_IP6;
4265b261 12054 int idx = 0;
6c9d22e2
PG
12055 struct json_object *json_all = NULL;
12056 struct json_object *json_afi_safi = NULL;
4265b261
PG
12057
12058 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12059 &bgp, false);
71f1613a 12060 if (!idx)
4265b261 12061 return CMD_WARNING;
6c9d22e2 12062
4265b261 12063 if (uj)
6c9d22e2 12064 json_all = json_object_new_object();
4265b261 12065
9ab0cf58
PG
12066 FOREACH_AFI_SAFI (afi, safi) {
12067 /*
12068 * So limit output to those afi/safi pairs that
12069 * actually have something interesting in them
12070 */
12071 if (strmatch(get_afi_safi_str(afi, safi, true),
12072 "Unknown")) {
12073 continue;
12074 }
12075 if (uj) {
12076 json_afi_safi = json_object_new_array();
12077 json_object_object_add(
12078 json_all,
12079 get_afi_safi_str(afi, safi, true),
12080 json_afi_safi);
12081 } else {
12082 json_afi_safi = NULL;
6c9d22e2 12083 }
9ab0cf58
PG
12084
12085 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12086 }
6c9d22e2 12087
3757f964
DA
12088 if (uj)
12089 vty_json(vty, json_all);
6c9d22e2 12090
4265b261
PG
12091 return CMD_SUCCESS;
12092}
12093
7b2ff250 12094/* BGP route print out function without JSON */
14718643
PG
12095DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12096 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12097 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12098 SHOW_STR
12099 IP_STR
12100 BGP_STR
12101 BGP_INSTANCE_HELP_STR
12102 L2VPN_HELP_STR
12103 EVPN_HELP_STR
12104 "BGP RIB advertisement statistics\n"
12105 JSON_STR)
12106{
ec76a1d1
DA
12107 afi_t afi = AFI_IP6;
12108 safi_t safi = SAFI_UNICAST;
14718643
PG
12109 struct bgp *bgp = NULL;
12110 int idx = 0, ret;
12111 bool uj = use_json(argc, argv);
12112 struct json_object *json_afi_safi = NULL, *json = NULL;
12113
12114 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12115 &bgp, false);
12116 if (!idx)
12117 return CMD_WARNING;
12118
12119 if (uj)
12120 json_afi_safi = json_object_new_array();
12121 else
12122 json_afi_safi = NULL;
12123
12124 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12125
12126 if (uj) {
12127 json = json_object_new_object();
12128 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12129 json_afi_safi);
3757f964 12130 vty_json(vty, json);
14718643
PG
12131 }
12132 return ret;
12133}
12134
893cccd0 12135/* BGP route print out function without JSON */
9ab0cf58
PG
12136DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12137 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12138 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12139 "]]\
893cccd0 12140 statistics [json]",
9ab0cf58
PG
12141 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12142 BGP_SAFI_WITH_LABEL_HELP_STR
12143 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12144{
ec76a1d1
DA
12145 afi_t afi = AFI_IP6;
12146 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12147 struct bgp *bgp = NULL;
12148 int idx = 0, ret;
12149 bool uj = use_json(argc, argv);
6c9d22e2 12150 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12151
12152 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12153 &bgp, false);
12154 if (!idx)
12155 return CMD_WARNING;
6c9d22e2 12156
893cccd0 12157 if (uj)
6c9d22e2
PG
12158 json_afi_safi = json_object_new_array();
12159 else
12160 json_afi_safi = NULL;
12161
12162 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12163
12164 if (uj) {
12165 json = json_object_new_object();
12166 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12167 json_afi_safi);
3757f964 12168 vty_json(vty, json);
893cccd0
PG
12169 }
12170 return ret;
893cccd0 12171}
7b2ff250 12172
fe0f234d 12173DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12174 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12175 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12176 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12177 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12178 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12179 "Display the entries for all address families\n"
9ab0cf58
PG
12180 "Display detailed information about dampening\n"
12181 "Display detail of configured dampening parameters\n"
fe0f234d 12182 JSON_STR)
718e3744 12183{
d62a17ae 12184 afi_t afi = AFI_IP6;
12185 safi_t safi = SAFI_UNICAST;
d62a17ae 12186 struct bgp *bgp = NULL;
12187 int idx = 0;
96c81f66 12188 uint16_t show_flags = 0;
fe0f234d
RW
12189 bool uj = use_json(argc, argv);
12190
12191 if (uj) {
12192 argc--;
12193 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12194 }
96f3485c
MK
12195
12196 /* [<ipv4|ipv6> [all]] */
12197 if (all) {
12198 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12199 if (argv_find(argv, argc, "ipv4", &idx))
12200 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12201
12202 if (argv_find(argv, argc, "ipv6", &idx))
12203 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12204 }
d62a17ae 12205
12206 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12207 &bgp, false);
d62a17ae 12208 if (!idx)
12209 return CMD_WARNING;
12210
fe0f234d 12211 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12212}
12213
fe0f234d
RW
12214/* BGP route print out function */
12215DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12216 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12217 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12218 "]]\
96f3485c 12219 [all$all]\
cf4898bc
QY
12220 [cidr-only\
12221 |dampening <flap-statistics|dampened-paths>\
12222 |community [AA:NN|local-AS|no-advertise|no-export\
12223 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12224 |accept-own|accept-own-nexthop|route-filter-v6\
12225 |route-filter-v4|route-filter-translated-v6\
12226 |route-filter-translated-v4] [exact-match]\
70799983 12227 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12228 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12229 |prefix-list WORD\
bf1a944a 12230 |route-map WORD\
1e2ce4f1 12231 |rpki <invalid|valid|notfound>\
7d3cae70 12232 |version (1-4294967295)\
b4ad2fae 12233 |alias ALIAS_NAME\
39c3c736
RW
12234 |A.B.C.D/M longer-prefixes\
12235 |X:X::X:X/M longer-prefixes\
f280c93b 12236 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12237 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12238 BGP_SAFI_WITH_LABEL_HELP_STR
12239 "Display the entries for all address families\n"
12240 "Display only routes with non-natural netmasks\n"
12241 "Display detailed information about dampening\n"
12242 "Display flap statistics of routes\n"
12243 "Display paths suppressed due to dampening\n"
12244 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12245 "Do not send outside local AS (well-known community)\n"
12246 "Do not advertise to any peer (well-known community)\n"
12247 "Do not export to next AS (well-known community)\n"
12248 "Graceful shutdown (well-known community)\n"
12249 "Do not export to any peer (well-known community)\n"
12250 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12251 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12252 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12253 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12254 "Should accept VPN route with local nexthop (well-known community)\n"
12255 "RT VPNv6 route filtering (well-known community)\n"
12256 "RT VPNv4 route filtering (well-known community)\n"
12257 "RT translated VPNv6 route filtering (well-known community)\n"
12258 "RT translated VPNv4 route filtering (well-known community)\n"
12259 "Exact match of the communities\n"
70799983
RW
12260 "Community-list number\n"
12261 "Community-list name\n"
12262 "Display routes matching the community-list\n"
12263 "Exact match of the communities\n"
a7129347
RW
12264 "Display routes conforming to the filter-list\n"
12265 "Regular expression access list name\n"
6deaf579
RW
12266 "Display routes conforming to the prefix-list\n"
12267 "Prefix-list name\n"
bf1a944a
RW
12268 "Display routes matching the route-map\n"
12269 "A route-map to match on\n"
a70a28a5
DA
12270 "RPKI route types\n"
12271 "A valid path as determined by rpki\n"
12272 "A invalid path as determined by rpki\n"
12273 "A path that has no rpki data\n"
12274 "Display prefixes with matching version numbers\n"
12275 "Version number and above\n"
12276 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12277 "BGP community alias\n"
12278 "IPv4 prefix\n"
12279 "Display route and more specific routes\n"
12280 "IPv6 prefix\n"
12281 "Display route and more specific routes\n"
12282 JSON_STR
a70a28a5
DA
12283 "Display detailed version of JSON output\n"
12284 "Increase table width for longer prefixes\n")
7b2ff250
DW
12285{
12286 afi_t afi = AFI_IP6;
12287 safi_t safi = SAFI_UNICAST;
12288 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12289 void *output_arg = NULL;
7b2ff250
DW
12290 struct bgp *bgp = NULL;
12291 int idx = 0;
d0086e8e 12292 int exact_match = 0;
96f3485c
MK
12293 char *community = NULL;
12294 bool first = true;
96c81f66 12295 uint16_t show_flags = 0;
4027d19b 12296 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12297 struct prefix p;
96f3485c
MK
12298
12299 if (uj) {
9f049418 12300 argc--;
96f3485c
MK
12301 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12302 }
12303
f280c93b
DA
12304 if (detail)
12305 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12306
96f3485c
MK
12307 /* [<ipv4|ipv6> [all]] */
12308 if (all) {
12309 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12310
12311 if (argv_find(argv, argc, "ipv4", &idx))
12312 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12313
12314 if (argv_find(argv, argc, "ipv6", &idx))
12315 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12316 }
12317
12318 if (wide)
12319 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12320
12321 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12322 &bgp, uj);
7b2ff250
DW
12323 if (!idx)
12324 return CMD_WARNING;
12325
7b2ff250 12326 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12327 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12328
12329 if (argv_find(argv, argc, "dampening", &idx)) {
12330 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12331 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12332 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12333 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12334 }
12335
12336 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12337 char *maybecomm = NULL;
d0086e8e 12338
79bc257a
RW
12339 if (idx + 1 < argc) {
12340 if (argv[idx + 1]->type == VARIABLE_TKN)
12341 maybecomm = argv[idx + 1]->arg;
12342 else
12343 maybecomm = argv[idx + 1]->text;
12344 }
12345
cf4898bc
QY
12346 if (maybecomm && !strmatch(maybecomm, "json")
12347 && !strmatch(maybecomm, "exact-match"))
12348 community = maybecomm;
d0086e8e 12349
cf4898bc
QY
12350 if (argv_find(argv, argc, "exact-match", &idx))
12351 exact_match = 1;
d0086e8e 12352
96f3485c
MK
12353 if (!community)
12354 sh_type = bgp_show_type_community_all;
12355 }
12356
70799983
RW
12357 if (argv_find(argv, argc, "community-list", &idx)) {
12358 const char *clist_number_or_name = argv[++idx]->arg;
12359 struct community_list *list;
12360
12361 if (argv_find(argv, argc, "exact-match", &idx))
12362 exact_match = 1;
12363
12364 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12365 COMMUNITY_LIST_MASTER);
12366 if (list == NULL) {
12367 vty_out(vty,
12368 "%% %s is not a valid community-list name\n",
12369 clist_number_or_name);
12370 return CMD_WARNING;
12371 }
12372
12373 if (exact_match)
12374 sh_type = bgp_show_type_community_list_exact;
12375 else
12376 sh_type = bgp_show_type_community_list;
12377 output_arg = list;
12378 }
12379
a7129347
RW
12380 if (argv_find(argv, argc, "filter-list", &idx)) {
12381 const char *filter = argv[++idx]->arg;
12382 struct as_list *as_list;
12383
12384 as_list = as_list_lookup(filter);
12385 if (as_list == NULL) {
12386 vty_out(vty,
12387 "%% %s is not a valid AS-path access-list name\n",
12388 filter);
12389 return CMD_WARNING;
12390 }
12391
12392 sh_type = bgp_show_type_filter_list;
12393 output_arg = as_list;
12394 }
12395
6deaf579
RW
12396 if (argv_find(argv, argc, "prefix-list", &idx)) {
12397 const char *prefix_list_str = argv[++idx]->arg;
12398 struct prefix_list *plist;
12399
12400 plist = prefix_list_lookup(afi, prefix_list_str);
12401 if (plist == NULL) {
12402 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12403 prefix_list_str);
12404 return CMD_WARNING;
12405 }
12406
12407 sh_type = bgp_show_type_prefix_list;
12408 output_arg = plist;
12409 }
12410
bf1a944a
RW
12411 if (argv_find(argv, argc, "route-map", &idx)) {
12412 const char *rmap_str = argv[++idx]->arg;
12413 struct route_map *rmap;
12414
12415 rmap = route_map_lookup_by_name(rmap_str);
12416 if (!rmap) {
12417 vty_out(vty, "%% %s is not a valid route-map name\n",
12418 rmap_str);
12419 return CMD_WARNING;
12420 }
12421
12422 sh_type = bgp_show_type_route_map;
12423 output_arg = rmap;
12424 }
12425
1e2ce4f1
DS
12426 if (argv_find(argv, argc, "rpki", &idx)) {
12427 sh_type = bgp_show_type_rpki;
12428 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12429 rpki_target_state = RPKI_VALID;
1e2ce4f1 12430 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12431 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12432 }
12433
7d3cae70
DA
12434 /* Display prefixes with matching version numbers */
12435 if (argv_find(argv, argc, "version", &idx)) {
12436 sh_type = bgp_show_type_prefix_version;
2391833e 12437 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12438 }
12439
a70a28a5
DA
12440 /* Display prefixes with matching BGP community alias */
12441 if (argv_find(argv, argc, "alias", &idx)) {
12442 sh_type = bgp_show_type_community_alias;
2391833e 12443 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12444 }
12445
39c3c736
RW
12446 /* prefix-longer */
12447 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12448 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12449 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12450
12451 if (!str2prefix(prefix_str, &p)) {
12452 vty_out(vty, "%% Malformed Prefix\n");
12453 return CMD_WARNING;
12454 }
12455
12456 sh_type = bgp_show_type_prefix_longer;
12457 output_arg = &p;
a70a28a5
DA
12458 }
12459
96f3485c
MK
12460 if (!all) {
12461 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12462 if (community)
12463 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12464 exact_match, afi, safi,
12465 show_flags);
2391833e 12466 else
a70a28a5 12467 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12468 output_arg, show_flags,
a70a28a5 12469 rpki_target_state);
96f3485c 12470 } else {
fa5ac378
DA
12471 struct listnode *node;
12472 struct bgp *abgp;
96f3485c
MK
12473 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12474 * AFI_IP6 */
12475
12476 if (uj)
12477 vty_out(vty, "{\n");
12478
12479 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12480 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12481 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12482 ? AFI_IP
12483 : AFI_IP6;
fa5ac378
DA
12484 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12485 FOREACH_SAFI (safi) {
12486 if (!bgp_afi_safi_peer_exists(abgp, afi,
12487 safi))
12488 continue;
96f3485c 12489
fa5ac378
DA
12490 if (uj) {
12491 if (first)
12492 first = false;
12493 else
12494 vty_out(vty, ",\n");
12495 vty_out(vty, "\"%s\":{\n",
12496 get_afi_safi_str(afi,
12497 safi,
12498 true));
12499 } else
12500 vty_out(vty,
12501 "\nFor address family: %s\n",
12502 get_afi_safi_str(
12503 afi, safi,
12504 false));
12505
12506 if (community)
12507 bgp_show_community(
12508 vty, abgp, community,
12509 exact_match, afi, safi,
12510 show_flags);
96f3485c 12511 else
fa5ac378
DA
12512 bgp_show(vty, abgp, afi, safi,
12513 sh_type, output_arg,
12514 show_flags,
12515 rpki_target_state);
12516 if (uj)
12517 vty_out(vty, "}\n");
12518 }
96f3485c
MK
12519 }
12520 } else {
12521 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12522 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12523 FOREACH_AFI_SAFI (afi, safi) {
12524 if (!bgp_afi_safi_peer_exists(abgp, afi,
12525 safi))
12526 continue;
96f3485c 12527
fa5ac378
DA
12528 if (uj) {
12529 if (first)
12530 first = false;
12531 else
12532 vty_out(vty, ",\n");
12533
12534 vty_out(vty, "\"%s\":{\n",
12535 get_afi_safi_str(afi,
12536 safi,
12537 true));
12538 } else
12539 vty_out(vty,
12540 "\nFor address family: %s\n",
12541 get_afi_safi_str(
12542 afi, safi,
12543 false));
12544
12545 if (community)
12546 bgp_show_community(
12547 vty, abgp, community,
12548 exact_match, afi, safi,
12549 show_flags);
96f3485c 12550 else
fa5ac378
DA
12551 bgp_show(vty, abgp, afi, safi,
12552 sh_type, output_arg,
12553 show_flags,
12554 rpki_target_state);
12555 if (uj)
12556 vty_out(vty, "}\n");
12557 }
96f3485c
MK
12558 }
12559 }
12560 if (uj)
12561 vty_out(vty, "}\n");
12562 }
12563 return CMD_SUCCESS;
a636c635 12564}
47fc97cc 12565
718e3744 12566DEFUN (show_ip_bgp_route,
12567 show_ip_bgp_route_cmd,
8aa22bbb 12568 "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 12569 SHOW_STR
12570 IP_STR
12571 BGP_STR
a636c635 12572 BGP_INSTANCE_HELP_STR
4f280b15 12573 BGP_AFI_HELP_STR
4dd6177e 12574 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12575 "Network in the BGP routing table to display\n"
0c7b1b01 12576 "IPv4 prefix\n"
8c3deaae 12577 "Network in the BGP routing table to display\n"
0c7b1b01 12578 "IPv6 prefix\n"
4092b06c 12579 "Display only the bestpath\n"
b05a1c8b 12580 "Display only multipaths\n"
8aa22bbb
DS
12581 "Display only paths that match the specified rpki state\n"
12582 "A valid path as determined by rpki\n"
12583 "A invalid path as determined by rpki\n"
12584 "A path that has no rpki data\n"
9973d184 12585 JSON_STR)
4092b06c 12586{
d62a17ae 12587 int prefix_check = 0;
ae19d7dd 12588
d62a17ae 12589 afi_t afi = AFI_IP6;
12590 safi_t safi = SAFI_UNICAST;
12591 char *prefix = NULL;
12592 struct bgp *bgp = NULL;
12593 enum bgp_path_type path_type;
9f049418 12594 bool uj = use_json(argc, argv);
b05a1c8b 12595
d62a17ae 12596 int idx = 0;
ae19d7dd 12597
d62a17ae 12598 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12599 &bgp, uj);
d62a17ae 12600 if (!idx)
12601 return CMD_WARNING;
c41247f5 12602
d62a17ae 12603 if (!bgp) {
12604 vty_out(vty,
12605 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12606 return CMD_WARNING;
12607 }
a636c635 12608
d62a17ae 12609 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12610 if (argv_find(argv, argc, "A.B.C.D", &idx)
12611 || argv_find(argv, argc, "X:X::X:X", &idx))
12612 prefix_check = 0;
12613 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12614 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12615 prefix_check = 1;
12616
12617 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12618 && afi != AFI_IP6) {
12619 vty_out(vty,
12620 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12621 return CMD_WARNING;
12622 }
12623 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12624 && afi != AFI_IP) {
12625 vty_out(vty,
12626 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12627 return CMD_WARNING;
12628 }
12629
12630 prefix = argv[idx]->arg;
12631
12632 /* [<bestpath|multipath>] */
12633 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12634 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12635 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12636 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12637 else
360660c6 12638 path_type = BGP_PATH_SHOW_ALL;
a636c635 12639
d62a17ae 12640 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12641 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12642}
12643
8c3deaae
QY
12644DEFUN (show_ip_bgp_regexp,
12645 show_ip_bgp_regexp_cmd,
3e5b31b3 12646 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12647 SHOW_STR
12648 IP_STR
12649 BGP_STR
b00b230a 12650 BGP_INSTANCE_HELP_STR
4f280b15 12651 BGP_AFI_HELP_STR
4dd6177e 12652 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12653 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12654 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12655 JSON_STR)
8c3deaae 12656{
d62a17ae 12657 afi_t afi = AFI_IP6;
12658 safi_t safi = SAFI_UNICAST;
12659 struct bgp *bgp = NULL;
3e5b31b3
DA
12660 bool uj = use_json(argc, argv);
12661 char *regstr = NULL;
8c3deaae 12662
d62a17ae 12663 int idx = 0;
12664 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12665 &bgp, false);
d62a17ae 12666 if (!idx)
12667 return CMD_WARNING;
8c3deaae 12668
d62a17ae 12669 // get index of regex
3e5b31b3
DA
12670 if (argv_find(argv, argc, "REGEX", &idx))
12671 regstr = argv[idx]->arg;
8c3deaae 12672
5f71d11c 12673 assert(regstr);
3e5b31b3
DA
12674 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12675 bgp_show_type_regexp, uj);
8c3deaae
QY
12676}
12677
ae248832 12678DEFPY (show_ip_bgp_instance_all,
a636c635 12679 show_ip_bgp_instance_all_cmd,
ae248832 12680 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12681 SHOW_STR
a636c635 12682 IP_STR
4092b06c 12683 BGP_STR
a636c635 12684 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12685 BGP_AFI_HELP_STR
4dd6177e 12686 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12687 JSON_STR
12688 "Increase table width for longer prefixes\n")
4092b06c 12689{
54d05dea 12690 afi_t afi = AFI_IP6;
d62a17ae 12691 safi_t safi = SAFI_UNICAST;
12692 struct bgp *bgp = NULL;
d62a17ae 12693 int idx = 0;
96c81f66 12694 uint16_t show_flags = 0;
ae19d7dd 12695
96f3485c 12696 if (uj) {
d62a17ae 12697 argc--;
96f3485c
MK
12698 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12699 }
12700
12701 if (wide)
12702 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12703
9f049418
DS
12704 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12705 &bgp, uj);
12706 if (!idx)
12707 return CMD_WARNING;
12708
96f3485c 12709 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12710 return CMD_SUCCESS;
e3e29b32
LB
12711}
12712
a4d82a8a 12713static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12714 afi_t afi, safi_t safi, enum bgp_show_type type,
12715 bool use_json)
718e3744 12716{
d62a17ae 12717 regex_t *regex;
12718 int rc;
96c81f66 12719 uint16_t show_flags = 0;
96f3485c
MK
12720
12721 if (use_json)
12722 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12723
c3900853 12724 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12725 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12726 regstr);
12727 return CMD_WARNING_CONFIG_FAILED;
12728 }
12729
d62a17ae 12730 regex = bgp_regcomp(regstr);
12731 if (!regex) {
12732 vty_out(vty, "Can't compile regexp %s\n", regstr);
12733 return CMD_WARNING;
12734 }
a636c635 12735
1e2ce4f1
DS
12736 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12737 RPKI_NOT_BEING_USED);
d62a17ae 12738 bgp_regex_free(regex);
12739 return rc;
e3e29b32
LB
12740}
12741
7f323236
DW
12742static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12743 const char *comstr, int exact, afi_t afi,
96c81f66 12744 safi_t safi, uint16_t show_flags)
d62a17ae 12745{
12746 struct community *com;
d62a17ae 12747 int ret = 0;
12748
7f323236 12749 com = community_str2com(comstr);
d62a17ae 12750 if (!com) {
7f323236 12751 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12752 return CMD_WARNING;
12753 }
12754
12755 ret = bgp_show(vty, bgp, afi, safi,
12756 (exact ? bgp_show_type_community_exact
12757 : bgp_show_type_community),
1e2ce4f1 12758 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12759 community_free(&com);
46c3ce83 12760
d62a17ae 12761 return ret;
718e3744 12762}
12763
d62a17ae 12764enum bgp_stats {
12765 BGP_STATS_MAXBITLEN = 0,
12766 BGP_STATS_RIB,
12767 BGP_STATS_PREFIXES,
12768 BGP_STATS_TOTPLEN,
12769 BGP_STATS_UNAGGREGATEABLE,
12770 BGP_STATS_MAX_AGGREGATEABLE,
12771 BGP_STATS_AGGREGATES,
12772 BGP_STATS_SPACE,
12773 BGP_STATS_ASPATH_COUNT,
12774 BGP_STATS_ASPATH_MAXHOPS,
12775 BGP_STATS_ASPATH_TOTHOPS,
12776 BGP_STATS_ASPATH_MAXSIZE,
12777 BGP_STATS_ASPATH_TOTSIZE,
12778 BGP_STATS_ASN_HIGHEST,
12779 BGP_STATS_MAX,
a636c635 12780};
2815e61f 12781
9ab0cf58 12782#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12783#define TABLE_STATS_IDX_JSON 1
12784
12785static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12786 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12787 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12788 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12789 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12790 "unaggregateablePrefixes"},
12791 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12792 "maximumAggregateablePrefixes"},
12793 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12794 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12795 [BGP_STATS_SPACE] = {"Address space advertised",
12796 "addressSpaceAdvertised"},
9ab0cf58
PG
12797 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12798 "advertisementsWithPaths"},
12799 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12800 "longestAsPath"},
12801 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12802 "largestAsPath"},
12803 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12804 "averageAsPathLengthHops"},
12805 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12806 "averageAsPathSizeBytes"},
12807 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12808 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12809};
2815e61f 12810
d62a17ae 12811struct bgp_table_stats {
12812 struct bgp_table *table;
12813 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12814 double total_space;
ff7924f6
PJ
12815};
12816
9bcb3eef 12817static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12818 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12819{
9bcb3eef 12820 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12821 struct bgp_path_info *pi;
b54892e0 12822 const struct prefix *rn_p;
d62a17ae 12823
9bcb3eef 12824 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12825 return;
d62a17ae 12826
9bcb3eef 12827 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12828 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12829 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12830
9c14ec72 12831 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12832 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12833 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12834
9bcb3eef 12835 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12836 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12837 /* announced address space */
12838 if (space)
b54892e0 12839 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12840 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12841 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12842
9c14ec72 12843
9bcb3eef 12844 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12845 ts->counts[BGP_STATS_RIB]++;
12846
05864da7
DS
12847 if (CHECK_FLAG(pi->attr->flag,
12848 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12849 ts->counts[BGP_STATS_AGGREGATES]++;
12850
12851 /* as-path stats */
05864da7 12852 if (pi->attr->aspath) {
9c14ec72
RW
12853 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12854 unsigned int size = aspath_size(pi->attr->aspath);
12855 as_t highest = aspath_highest(pi->attr->aspath);
12856
12857 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12858
12859 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12860 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12861
12862 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12863 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12864
12865 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12866 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12867 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12868 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12869 }
12870 }
12871}
12872
cc9f21da 12873static void bgp_table_stats_walker(struct thread *t)
9c14ec72 12874{
9bcb3eef
DS
12875 struct bgp_dest *dest, *ndest;
12876 struct bgp_dest *top;
9c14ec72
RW
12877 struct bgp_table_stats *ts = THREAD_ARG(t);
12878 unsigned int space = 0;
12879
12880 if (!(top = bgp_table_top(ts->table)))
cc9f21da 12881 return;
9c14ec72
RW
12882
12883 switch (ts->table->afi) {
12884 case AFI_IP:
12885 space = IPV4_MAX_BITLEN;
12886 break;
12887 case AFI_IP6:
12888 space = IPV6_MAX_BITLEN;
12889 break;
3ba7b4af
TA
12890 case AFI_L2VPN:
12891 space = EVPN_ROUTE_PREFIXLEN;
12892 break;
9c14ec72 12893 default:
cc9f21da 12894 return;
9c14ec72
RW
12895 }
12896
12897 ts->counts[BGP_STATS_MAXBITLEN] = space;
12898
9bcb3eef 12899 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12900 if (ts->table->safi == SAFI_MPLS_VPN
12901 || ts->table->safi == SAFI_ENCAP
12902 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12903 struct bgp_table *table;
12904
9bcb3eef 12905 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12906 if (!table)
12907 continue;
12908
12909 top = bgp_table_top(table);
9bcb3eef
DS
12910 for (ndest = bgp_table_top(table); ndest;
12911 ndest = bgp_route_next(ndest))
12912 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12913 } else {
9bcb3eef 12914 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12915 }
12916 }
2815e61f 12917}
ff7924f6 12918
71f1613a
DA
12919static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12920 struct json_object *json_array)
12921{
12922 struct listnode *node, *nnode;
12923 struct bgp *bgp;
12924
12925 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12926 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12927}
12928
12929static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12930 safi_t safi, struct json_object *json_array)
2815e61f 12931{
d62a17ae 12932 struct bgp_table_stats ts;
12933 unsigned int i;
893cccd0
PG
12934 int ret = CMD_SUCCESS;
12935 char temp_buf[20];
6c9d22e2
PG
12936 struct json_object *json = NULL;
12937
12938 if (json_array)
12939 json = json_object_new_object();
019386c2 12940
d62a17ae 12941 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12942 char warning_msg[50];
12943
12944 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12945 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12946 safi);
6c9d22e2
PG
12947
12948 if (!json)
893cccd0
PG
12949 vty_out(vty, "%s\n", warning_msg);
12950 else
9ab0cf58 12951 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12952
893cccd0
PG
12953 ret = CMD_WARNING;
12954 goto end_table_stats;
d62a17ae 12955 }
019386c2 12956
893cccd0 12957 if (!json)
5290ceab
DA
12958 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12959 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12960 else
12961 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12962
d62a17ae 12963 /* labeled-unicast routes live in the unicast table */
12964 if (safi == SAFI_LABELED_UNICAST)
12965 safi = SAFI_UNICAST;
019386c2 12966
d62a17ae 12967 memset(&ts, 0, sizeof(ts));
12968 ts.table = bgp->rib[afi][safi];
12969 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12970
d62a17ae 12971 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12972 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12973 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12974 continue;
12975
12976 switch (i) {
d62a17ae 12977 case BGP_STATS_ASPATH_TOTHOPS:
12978 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12979 if (!json) {
9ab0cf58
PG
12980 snprintf(
12981 temp_buf, sizeof(temp_buf), "%12.2f",
12982 ts.counts[i]
12983 ? (float)ts.counts[i]
12984 / (float)ts.counts
12985 [BGP_STATS_ASPATH_COUNT]
12986 : 0);
893cccd0 12987 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12988 table_stats_strs[i]
12989 [TABLE_STATS_IDX_VTY],
893cccd0 12990 temp_buf);
9ab0cf58
PG
12991 } else {
12992 json_object_double_add(
12993 json,
12994 table_stats_strs[i]
12995 [TABLE_STATS_IDX_JSON],
12996 ts.counts[i]
12997 ? (double)ts.counts[i]
12998 / (double)ts.counts
d62a17ae 12999 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13000 : 0);
13001 }
d62a17ae 13002 break;
13003 case BGP_STATS_TOTPLEN:
6c9d22e2 13004 if (!json) {
9ab0cf58
PG
13005 snprintf(
13006 temp_buf, sizeof(temp_buf), "%12.2f",
13007 ts.counts[i]
13008 ? (float)ts.counts[i]
13009 / (float)ts.counts
13010 [BGP_STATS_PREFIXES]
13011 : 0);
893cccd0 13012 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13013 table_stats_strs[i]
13014 [TABLE_STATS_IDX_VTY],
893cccd0 13015 temp_buf);
9ab0cf58
PG
13016 } else {
13017 json_object_double_add(
13018 json,
13019 table_stats_strs[i]
13020 [TABLE_STATS_IDX_JSON],
13021 ts.counts[i]
13022 ? (double)ts.counts[i]
13023 / (double)ts.counts
d62a17ae 13024 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13025 : 0);
13026 }
d62a17ae 13027 break;
13028 case BGP_STATS_SPACE:
6c9d22e2
PG
13029 if (!json) {
13030 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13031 ts.total_space);
893cccd0 13032 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13033 table_stats_strs[i]
13034 [TABLE_STATS_IDX_VTY],
893cccd0 13035 temp_buf);
9ab0cf58
PG
13036 } else {
13037 json_object_double_add(
13038 json,
13039 table_stats_strs[i]
13040 [TABLE_STATS_IDX_JSON],
13041 (double)ts.total_space);
13042 }
8d0ab76d 13043 if (afi == AFI_IP6) {
6c9d22e2
PG
13044 if (!json) {
13045 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13046 "%12g",
13047 ts.total_space
13048 * pow(2.0, -128 + 32));
6c9d22e2
PG
13049 vty_out(vty, "%30s: %s\n",
13050 "/32 equivalent %s\n",
13051 temp_buf);
9ab0cf58
PG
13052 } else {
13053 json_object_double_add(
13054 json, "/32equivalent",
13055 (double)(ts.total_space
13056 * pow(2.0,
13057 -128 + 32)));
13058 }
6c9d22e2
PG
13059 if (!json) {
13060 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13061 "%12g",
13062 ts.total_space
13063 * pow(2.0, -128 + 48));
6c9d22e2
PG
13064 vty_out(vty, "%30s: %s\n",
13065 "/48 equivalent %s\n",
13066 temp_buf);
9ab0cf58
PG
13067 } else {
13068 json_object_double_add(
13069 json, "/48equivalent",
13070 (double)(ts.total_space
13071 * pow(2.0,
13072 -128 + 48)));
13073 }
8d0ab76d 13074 } else {
6c9d22e2
PG
13075 if (!json) {
13076 snprintf(temp_buf, sizeof(temp_buf),
13077 "%12.2f",
9ab0cf58
PG
13078 ts.total_space * 100.
13079 * pow(2.0, -32));
6c9d22e2 13080 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13081 "% announced ", temp_buf);
13082 } else {
13083 json_object_double_add(
13084 json, "%announced",
13085 (double)(ts.total_space * 100.
13086 * pow(2.0, -32)));
13087 }
6c9d22e2
PG
13088 if (!json) {
13089 snprintf(temp_buf, sizeof(temp_buf),
13090 "%12.2f",
9ab0cf58
PG
13091 ts.total_space
13092 * pow(2.0, -32 + 8));
6c9d22e2
PG
13093 vty_out(vty, "%30s: %s\n",
13094 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13095 } else {
13096 json_object_double_add(
13097 json, "/8equivalent",
13098 (double)(ts.total_space
13099 * pow(2.0, -32 + 8)));
13100 }
6c9d22e2
PG
13101 if (!json) {
13102 snprintf(temp_buf, sizeof(temp_buf),
13103 "%12.2f",
9ab0cf58
PG
13104 ts.total_space
13105 * pow(2.0, -32 + 24));
6c9d22e2 13106 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13107 "/24 equivalent ", temp_buf);
13108 } else {
13109 json_object_double_add(
13110 json, "/24equivalent",
13111 (double)(ts.total_space
13112 * pow(2.0, -32 + 24)));
13113 }
8d0ab76d 13114 }
d62a17ae 13115 break;
13116 default:
6c9d22e2
PG
13117 if (!json) {
13118 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13119 ts.counts[i]);
893cccd0 13120 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13121 table_stats_strs[i]
13122 [TABLE_STATS_IDX_VTY],
13123 temp_buf);
13124 } else {
13125 json_object_int_add(
13126 json,
13127 table_stats_strs[i]
13128 [TABLE_STATS_IDX_JSON],
13129 ts.counts[i]);
13130 }
d62a17ae 13131 }
893cccd0
PG
13132 if (!json)
13133 vty_out(vty, "\n");
d62a17ae 13134 }
9ab0cf58 13135end_table_stats:
6c9d22e2
PG
13136 if (json)
13137 json_object_array_add(json_array, json);
893cccd0 13138 return ret;
d62a17ae 13139}
13140
71f1613a
DA
13141static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13142 safi_t safi, struct json_object *json_array)
13143{
13144 if (!bgp) {
13145 bgp_table_stats_all(vty, afi, safi, json_array);
13146 return CMD_SUCCESS;
13147 }
13148
13149 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13150}
13151
d62a17ae 13152enum bgp_pcounts {
13153 PCOUNT_ADJ_IN = 0,
13154 PCOUNT_DAMPED,
13155 PCOUNT_REMOVED,
13156 PCOUNT_HISTORY,
13157 PCOUNT_STALE,
13158 PCOUNT_VALID,
13159 PCOUNT_ALL,
13160 PCOUNT_COUNTED,
7e3d9632 13161 PCOUNT_BPATH_SELECTED,
d62a17ae 13162 PCOUNT_PFCNT, /* the figure we display to users */
13163 PCOUNT_MAX,
a636c635 13164};
718e3744 13165
2b64873d 13166static const char *const pcount_strs[] = {
9d303b37
DL
13167 [PCOUNT_ADJ_IN] = "Adj-in",
13168 [PCOUNT_DAMPED] = "Damped",
13169 [PCOUNT_REMOVED] = "Removed",
13170 [PCOUNT_HISTORY] = "History",
13171 [PCOUNT_STALE] = "Stale",
13172 [PCOUNT_VALID] = "Valid",
13173 [PCOUNT_ALL] = "All RIB",
13174 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13175 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13176 [PCOUNT_PFCNT] = "Useable",
13177 [PCOUNT_MAX] = NULL,
a636c635 13178};
718e3744 13179
d62a17ae 13180struct peer_pcounts {
13181 unsigned int count[PCOUNT_MAX];
13182 const struct peer *peer;
13183 const struct bgp_table *table;
54317cba 13184 safi_t safi;
a636c635 13185};
47fc97cc 13186
9bcb3eef 13187static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13188{
54317cba
JW
13189 const struct bgp_adj_in *ain;
13190 const struct bgp_path_info *pi;
d62a17ae 13191 const struct peer *peer = pc->peer;
13192
54317cba
JW
13193 for (ain = rn->adj_in; ain; ain = ain->next)
13194 if (ain->peer == peer)
13195 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13196
9bcb3eef 13197 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13198
54317cba
JW
13199 if (pi->peer != peer)
13200 continue;
d62a17ae 13201
54317cba 13202 pc->count[PCOUNT_ALL]++;
d62a17ae 13203
54317cba
JW
13204 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13205 pc->count[PCOUNT_DAMPED]++;
13206 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13207 pc->count[PCOUNT_HISTORY]++;
13208 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13209 pc->count[PCOUNT_REMOVED]++;
13210 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13211 pc->count[PCOUNT_STALE]++;
13212 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13213 pc->count[PCOUNT_VALID]++;
13214 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13215 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13216 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13217 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13218
13219 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13220 pc->count[PCOUNT_COUNTED]++;
13221 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13222 flog_err(
13223 EC_LIB_DEVELOPMENT,
13224 "Attempting to count but flags say it is unusable");
13225 } else {
40381db7 13226 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13227 flog_err(
13228 EC_LIB_DEVELOPMENT,
13229 "Not counted but flags say we should");
d62a17ae 13230 }
13231 }
54317cba
JW
13232}
13233
cc9f21da 13234static void bgp_peer_count_walker(struct thread *t)
54317cba 13235{
9bcb3eef 13236 struct bgp_dest *rn, *rm;
54317cba
JW
13237 const struct bgp_table *table;
13238 struct peer_pcounts *pc = THREAD_ARG(t);
13239
13240 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13241 || pc->safi == SAFI_EVPN) {
13242 /* Special handling for 2-level routing tables. */
13243 for (rn = bgp_table_top(pc->table); rn;
13244 rn = bgp_route_next(rn)) {
9bcb3eef 13245 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13246 if (table != NULL)
13247 for (rm = bgp_table_top(table); rm;
13248 rm = bgp_route_next(rm))
13249 bgp_peer_count_proc(rm, pc);
13250 }
13251 } else
13252 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13253 bgp_peer_count_proc(rn, pc);
718e3744 13254}
13255
d62a17ae 13256static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13257 safi_t safi, bool use_json)
856ca177 13258{
d62a17ae 13259 struct peer_pcounts pcounts = {.peer = peer};
13260 unsigned int i;
13261 json_object *json = NULL;
13262 json_object *json_loop = NULL;
856ca177 13263
d62a17ae 13264 if (use_json) {
13265 json = json_object_new_object();
13266 json_loop = json_object_new_object();
13267 }
718e3744 13268
d62a17ae 13269 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13270 || !peer->bgp->rib[afi][safi]) {
13271 if (use_json) {
13272 json_object_string_add(
13273 json, "warning",
13274 "No such neighbor or address family");
13275 vty_out(vty, "%s\n", json_object_to_json_string(json));
13276 json_object_free(json);
d5f20468 13277 json_object_free(json_loop);
d62a17ae 13278 } else
13279 vty_out(vty, "%% No such neighbor or address family\n");
13280
13281 return CMD_WARNING;
13282 }
2a71e9ce 13283
d62a17ae 13284 memset(&pcounts, 0, sizeof(pcounts));
13285 pcounts.peer = peer;
13286 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13287 pcounts.safi = safi;
d62a17ae 13288
13289 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13290 * stats for the thread-walk (i.e. ensure this can't be blamed on
13291 * on just vty_read()).
13292 */
d62a17ae 13293 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13294
13295 if (use_json) {
13296 json_object_string_add(json, "prefixCountsFor", peer->host);
13297 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13298 get_afi_safi_str(afi, safi, true));
d62a17ae 13299 json_object_int_add(json, "pfxCounter",
13300 peer->pcount[afi][safi]);
13301
13302 for (i = 0; i < PCOUNT_MAX; i++)
13303 json_object_int_add(json_loop, pcount_strs[i],
13304 pcounts.count[i]);
13305
13306 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13307
13308 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13309 json_object_string_add(json, "pfxctDriftFor",
13310 peer->host);
13311 json_object_string_add(
13312 json, "recommended",
13313 "Please report this bug, with the above command output");
13314 }
75eeda93 13315 vty_json(vty, json);
d62a17ae 13316 } else {
13317
13318 if (peer->hostname
892fedb6 13319 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13320 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13321 peer->hostname, peer->host,
5cb5f4d0 13322 get_afi_safi_str(afi, safi, false));
d62a17ae 13323 } else {
13324 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13325 get_afi_safi_str(afi, safi, false));
d62a17ae 13326 }
13327
6cde4b45 13328 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13329 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13330
13331 for (i = 0; i < PCOUNT_MAX; i++)
13332 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13333 pcounts.count[i]);
13334
13335 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13336 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13337 vty_out(vty,
13338 "Please report this bug, with the above command output\n");
13339 }
13340 }
13341
13342 return CMD_SUCCESS;
718e3744 13343}
13344
a636c635
DW
13345DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13346 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13347 "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 13348 SHOW_STR
13349 IP_STR
13350 BGP_STR
8386ac43 13351 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13352 BGP_AFI_HELP_STR
13353 BGP_SAFI_HELP_STR
0b16f239
DS
13354 "Detailed information on TCP and BGP neighbor connections\n"
13355 "Neighbor to display information about\n"
13356 "Neighbor to display information about\n"
91d37724 13357 "Neighbor on BGP configured interface\n"
a636c635 13358 "Display detailed prefix count information\n"
9973d184 13359 JSON_STR)
0b16f239 13360{
d62a17ae 13361 afi_t afi = AFI_IP6;
13362 safi_t safi = SAFI_UNICAST;
13363 struct peer *peer;
13364 int idx = 0;
13365 struct bgp *bgp = NULL;
9f049418
DS
13366 bool uj = use_json(argc, argv);
13367
13368 if (uj)
13369 argc--;
856ca177 13370
d62a17ae 13371 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13372 &bgp, uj);
d62a17ae 13373 if (!idx)
13374 return CMD_WARNING;
0b16f239 13375
d62a17ae 13376 argv_find(argv, argc, "neighbors", &idx);
13377 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13378 if (!peer)
13379 return CMD_WARNING;
bb46e94f 13380
29c8d9da 13381 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13382}
0b16f239 13383
d6902373
PG
13384#ifdef KEEP_OLD_VPN_COMMANDS
13385DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13386 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13387 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13388 SHOW_STR
13389 IP_STR
13390 BGP_STR
d6902373 13391 BGP_VPNVX_HELP_STR
91d37724 13392 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13393 "Detailed information on TCP and BGP neighbor connections\n"
13394 "Neighbor to display information about\n"
13395 "Neighbor to display information about\n"
91d37724 13396 "Neighbor on BGP configured interface\n"
a636c635 13397 "Display detailed prefix count information\n"
9973d184 13398 JSON_STR)
a636c635 13399{
d62a17ae 13400 int idx_peer = 6;
13401 struct peer *peer;
9f049418 13402 bool uj = use_json(argc, argv);
a636c635 13403
d62a17ae 13404 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13405 if (!peer)
13406 return CMD_WARNING;
13407
13408 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13409}
13410
d6902373
PG
13411DEFUN (show_ip_bgp_vpn_all_route_prefix,
13412 show_ip_bgp_vpn_all_route_prefix_cmd,
13413 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13414 SHOW_STR
13415 IP_STR
13416 BGP_STR
d6902373 13417 BGP_VPNVX_HELP_STR
91d37724
QY
13418 "Display information about all VPNv4 NLRIs\n"
13419 "Network in the BGP routing table to display\n"
3a2d747c 13420 "Network in the BGP routing table to display\n"
9973d184 13421 JSON_STR)
91d37724 13422{
d62a17ae 13423 int idx = 0;
13424 char *network = NULL;
13425 struct bgp *bgp = bgp_get_default();
13426 if (!bgp) {
13427 vty_out(vty, "Can't find default instance\n");
13428 return CMD_WARNING;
13429 }
87e34b58 13430
d62a17ae 13431 if (argv_find(argv, argc, "A.B.C.D", &idx))
13432 network = argv[idx]->arg;
13433 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13434 network = argv[idx]->arg;
13435 else {
13436 vty_out(vty, "Unable to figure out Network\n");
13437 return CMD_WARNING;
13438 }
87e34b58 13439
d62a17ae 13440 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13441 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13442 use_json(argc, argv));
91d37724 13443}
d6902373 13444#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13445
44c69747
LK
13446DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13447 show_bgp_l2vpn_evpn_route_prefix_cmd,
13448 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13449 SHOW_STR
4c63a661
PG
13450 BGP_STR
13451 L2VPN_HELP_STR
13452 EVPN_HELP_STR
44c69747
LK
13453 "Network in the BGP routing table to display\n"
13454 "Network in the BGP routing table to display\n"
4c63a661
PG
13455 "Network in the BGP routing table to display\n"
13456 "Network in the BGP routing table to display\n"
13457 JSON_STR)
13458{
d62a17ae 13459 int idx = 0;
13460 char *network = NULL;
44c69747 13461 int prefix_check = 0;
a636c635 13462
44c69747
LK
13463 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13464 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13465 network = argv[idx]->arg;
44c69747 13466 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13467 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13468 network = argv[idx]->arg;
44c69747
LK
13469 prefix_check = 1;
13470 } else {
d62a17ae 13471 vty_out(vty, "Unable to figure out Network\n");
13472 return CMD_WARNING;
13473 }
44c69747
LK
13474 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13475 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13476 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13477}
13478
114fc229 13479static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13480 struct bgp_table *table, int *header1,
13481 int *header2, json_object *json,
13482 json_object *json_scode,
13483 json_object *json_ocode, bool wide)
13484{
13485 uint64_t version = table ? table->version : 0;
13486
13487 if (*header1) {
13488 if (json) {
13489 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13490 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13491 "%pI4", &peer->bgp->router_id);
2f9bc755 13492 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13493 peer->bgp->default_local_pref);
13494 json_object_int_add(json, "localAS",
13495 peer->change_local_as
13496 ? peer->change_local_as
13497 : peer->local_as);
2f9bc755
DS
13498 json_object_object_add(json, "bgpStatusCodes",
13499 json_scode);
13500 json_object_object_add(json, "bgpOriginCodes",
13501 json_ocode);
13502 } else {
13503 vty_out(vty,
23d0a753
DA
13504 "BGP table version is %" PRIu64
13505 ", local router ID is %pI4, vrf id ",
114fc229
DA
13506 version, &peer->bgp->router_id);
13507 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13508 vty_out(vty, "%s", VRFID_NONE_STR);
13509 else
114fc229 13510 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13511 vty_out(vty, "\n");
13512 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13513 peer->bgp->default_local_pref);
13514 vty_out(vty, "local AS %u\n",
13515 peer->change_local_as ? peer->change_local_as
13516 : peer->local_as);
2f9bc755
DS
13517 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13518 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13519 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13520 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13521 }
13522 *header1 = 0;
13523 }
13524 if (*header2) {
13525 if (!json)
13526 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13527 : BGP_SHOW_HEADER));
13528 *header2 = 0;
13529 }
13530}
13531
d9478df0
TA
13532static void
13533show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13534 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13535 const char *rmap_name, json_object *json, json_object *json_ar,
13536 json_object *json_scode, json_object *json_ocode,
96c81f66 13537 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13538 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13539{
d62a17ae 13540 struct bgp_adj_in *ain;
13541 struct bgp_adj_out *adj;
9bcb3eef 13542 struct bgp_dest *dest;
d62a17ae 13543 struct bgp *bgp;
d62a17ae 13544 struct attr attr;
13545 int ret;
13546 struct update_subgroup *subgrp;
d62a17ae 13547 struct peer_af *paf;
f99def61 13548 bool route_filtered;
96f3485c
MK
13549 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13550 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13551 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13552 || (safi == SAFI_EVPN))
13553 ? true
13554 : false;
a636c635 13555
d62a17ae 13556 bgp = peer->bgp;
a636c635 13557
d62a17ae 13558 subgrp = peer_subgroup(peer, afi, safi);
13559
6392aaa6 13560 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13561 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13562 if (use_json) {
13563 json_object_int_add(json, "bgpTableVersion",
13564 table->version);
c949c771
DA
13565 json_object_string_addf(json, "bgpLocalRouterId",
13566 "%pI4", &bgp->router_id);
01eced22
AD
13567 json_object_int_add(json, "defaultLocPrf",
13568 bgp->default_local_pref);
114fc229
DA
13569 json_object_int_add(json, "localAS",
13570 peer->change_local_as
13571 ? peer->change_local_as
13572 : peer->local_as);
d62a17ae 13573 json_object_object_add(json, "bgpStatusCodes",
13574 json_scode);
13575 json_object_object_add(json, "bgpOriginCodes",
13576 json_ocode);
07d0c4ed
DA
13577 json_object_string_add(
13578 json, "bgpOriginatingDefaultNetwork",
13579 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13580 } else {
23d0a753
DA
13581 vty_out(vty,
13582 "BGP table version is %" PRIu64
13583 ", local router ID is %pI4, vrf id ",
13584 table->version, &bgp->router_id);
9df8b37c
PZ
13585 if (bgp->vrf_id == VRF_UNKNOWN)
13586 vty_out(vty, "%s", VRFID_NONE_STR);
13587 else
13588 vty_out(vty, "%u", bgp->vrf_id);
13589 vty_out(vty, "\n");
01eced22
AD
13590 vty_out(vty, "Default local pref %u, ",
13591 bgp->default_local_pref);
114fc229
DA
13592 vty_out(vty, "local AS %u\n",
13593 peer->change_local_as ? peer->change_local_as
13594 : peer->local_as);
d62a17ae 13595 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13596 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13597 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13598 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13599
07d0c4ed
DA
13600 vty_out(vty, "Originating default network %s\n\n",
13601 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13602 }
d9478df0 13603 *header1 = 0;
d62a17ae 13604 }
a636c635 13605
9bcb3eef 13606 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13607 if (type == bgp_show_adj_route_received
13608 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13609 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13610 if (ain->peer != peer)
ea47320b 13611 continue;
6392aaa6 13612
114fc229 13613 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13614 header2, json, json_scode,
13615 json_ocode, wide);
13616
13617 if ((safi == SAFI_MPLS_VPN)
13618 || (safi == SAFI_ENCAP)
13619 || (safi == SAFI_EVPN)) {
13620 if (use_json)
13621 json_object_string_add(
13622 json_ar, "rd", rd_str);
13623 else if (show_rd && rd_str) {
13624 vty_out(vty,
13625 "Route Distinguisher: %s\n",
13626 rd_str);
13627 show_rd = false;
13628 }
13629 }
6392aaa6 13630
6f4f49b2 13631 attr = *ain->attr;
f99def61
AD
13632 route_filtered = false;
13633
13634 /* Filter prefix using distribute list,
13635 * filter list or prefix list
13636 */
b54892e0 13637 const struct prefix *rn_p =
9bcb3eef 13638 bgp_dest_get_prefix(dest);
b54892e0
DS
13639 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13640 safi))
13641 == FILTER_DENY)
f99def61
AD
13642 route_filtered = true;
13643
13644 /* Filter prefix using route-map */
b54892e0
DS
13645 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13646 safi, rmap_name, NULL,
13647 0, NULL);
6392aaa6 13648
13c8e163
AD
13649 if (type == bgp_show_adj_route_filtered &&
13650 !route_filtered && ret != RMAP_DENY) {
d498917e 13651 bgp_attr_flush(&attr);
6392aaa6 13652 continue;
d62a17ae 13653 }
6392aaa6 13654
d9478df0
TA
13655 if (type == bgp_show_adj_route_received
13656 && (route_filtered || ret == RMAP_DENY))
13657 (*filtered_count)++;
6392aaa6 13658
7d3cae70 13659 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13660 use_json, json_ar, wide);
d498917e 13661 bgp_attr_flush(&attr);
d9478df0 13662 (*output_count)++;
d62a17ae 13663 }
6392aaa6 13664 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13665 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13666 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13667 if (paf->peer != peer || !adj->attr)
924c3f6a 13668 continue;
d62a17ae 13669
114fc229 13670 show_adj_route_header(vty, peer, table,
d9478df0
TA
13671 header1, header2,
13672 json, json_scode,
13673 json_ocode, wide);
d62a17ae 13674
b54892e0 13675 const struct prefix *rn_p =
9bcb3eef 13676 bgp_dest_get_prefix(dest);
b54892e0 13677
6f4f49b2 13678 attr = *adj->attr;
b755861b 13679 ret = bgp_output_modifier(
b54892e0 13680 peer, rn_p, &attr, afi, safi,
b755861b 13681 rmap_name);
f46d8e1e 13682
b755861b 13683 if (ret != RMAP_DENY) {
d9478df0
TA
13684 if ((safi == SAFI_MPLS_VPN)
13685 || (safi == SAFI_ENCAP)
13686 || (safi == SAFI_EVPN)) {
13687 if (use_json)
13688 json_object_string_add(
13689 json_ar,
13690 "rd",
13691 rd_str);
13692 else if (show_rd
13693 && rd_str) {
13694 vty_out(vty,
13695 "Route Distinguisher: %s\n",
13696 rd_str);
13697 show_rd = false;
13698 }
13699 }
b54892e0 13700 route_vty_out_tmp(
7d3cae70
DA
13701 vty, dest, rn_p, &attr,
13702 safi, use_json, json_ar,
ae248832 13703 wide);
d9478df0 13704 (*output_count)++;
b755861b 13705 } else {
d9478df0 13706 (*filtered_count)++;
a2addae8 13707 }
b755861b 13708
d498917e 13709 bgp_attr_flush(&attr);
924c3f6a 13710 }
f20ce998
DS
13711 } else if (type == bgp_show_adj_route_bestpath) {
13712 struct bgp_path_info *pi;
13713
114fc229
DA
13714 show_adj_route_header(vty, peer, table, header1,
13715 header2, json, json_scode,
13716 json_ocode, wide);
f20ce998
DS
13717
13718 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13719 pi = pi->next) {
13720 if (pi->peer != peer)
13721 continue;
13722
13723 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13724 continue;
13725
7d3cae70 13726 route_vty_out_tmp(vty, dest,
f20ce998
DS
13727 bgp_dest_get_prefix(dest),
13728 pi->attr, safi, use_json,
13729 json_ar, wide);
d9478df0 13730 (*output_count)++;
f20ce998 13731 }
d62a17ae 13732 }
13733 }
a636c635 13734}
2a71e9ce 13735
d62a17ae 13736static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13737 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13738 const char *rmap_name, uint16_t show_flags)
0b16f239 13739{
d9478df0
TA
13740 struct bgp *bgp;
13741 struct bgp_table *table;
d62a17ae 13742 json_object *json = NULL;
d9478df0
TA
13743 json_object *json_scode = NULL;
13744 json_object *json_ocode = NULL;
13745 json_object *json_ar = NULL;
96f3485c 13746 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13747
d9478df0
TA
13748 /* Init BGP headers here so they're only displayed once
13749 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13750 */
13751 int header1 = 1;
13752 int header2 = 1;
13753
13754 /*
13755 * Initialize variables for each RD
13756 * All prefixes under an RD is aggregated within "json_routes"
13757 */
13758 char rd_str[BUFSIZ] = {0};
13759 json_object *json_routes = NULL;
13760
13761
13762 /* For 2-tier tables, prefix counts need to be
13763 * maintained across multiple runs of show_adj_route()
13764 */
13765 unsigned long output_count_per_rd;
13766 unsigned long filtered_count_per_rd;
13767 unsigned long output_count = 0;
13768 unsigned long filtered_count = 0;
13769
13770 if (use_json) {
d62a17ae 13771 json = json_object_new_object();
d9478df0
TA
13772 json_ar = json_object_new_object();
13773 json_scode = json_object_new_object();
13774 json_ocode = json_object_new_object();
13775
13776 json_object_string_add(json_scode, "suppressed", "s");
13777 json_object_string_add(json_scode, "damped", "d");
13778 json_object_string_add(json_scode, "history", "h");
13779 json_object_string_add(json_scode, "valid", "*");
13780 json_object_string_add(json_scode, "best", ">");
13781 json_object_string_add(json_scode, "multipath", "=");
13782 json_object_string_add(json_scode, "internal", "i");
13783 json_object_string_add(json_scode, "ribFailure", "r");
13784 json_object_string_add(json_scode, "stale", "S");
13785 json_object_string_add(json_scode, "removed", "R");
13786
13787 json_object_string_add(json_ocode, "igp", "i");
13788 json_object_string_add(json_ocode, "egp", "e");
13789 json_object_string_add(json_ocode, "incomplete", "?");
13790 }
0b16f239 13791
d62a17ae 13792 if (!peer || !peer->afc[afi][safi]) {
13793 if (use_json) {
13794 json_object_string_add(
13795 json, "warning",
13796 "No such neighbor or address family");
13797 vty_out(vty, "%s\n", json_object_to_json_string(json));
13798 json_object_free(json);
690c3134
MW
13799 json_object_free(json_ar);
13800 json_object_free(json_scode);
13801 json_object_free(json_ocode);
d62a17ae 13802 } else
13803 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13804
d62a17ae 13805 return CMD_WARNING;
13806 }
13807
6392aaa6
PM
13808 if ((type == bgp_show_adj_route_received
13809 || type == bgp_show_adj_route_filtered)
d62a17ae 13810 && !CHECK_FLAG(peer->af_flags[afi][safi],
13811 PEER_FLAG_SOFT_RECONFIG)) {
13812 if (use_json) {
13813 json_object_string_add(
13814 json, "warning",
13815 "Inbound soft reconfiguration not enabled");
13816 vty_out(vty, "%s\n", json_object_to_json_string(json));
13817 json_object_free(json);
690c3134
MW
13818 json_object_free(json_ar);
13819 json_object_free(json_scode);
13820 json_object_free(json_ocode);
d62a17ae 13821 } else
13822 vty_out(vty,
13823 "%% Inbound soft reconfiguration not enabled\n");
13824
13825 return CMD_WARNING;
13826 }
0b16f239 13827
d9478df0
TA
13828 bgp = peer->bgp;
13829
13830 /* labeled-unicast routes live in the unicast table */
13831 if (safi == SAFI_LABELED_UNICAST)
13832 table = bgp->rib[afi][SAFI_UNICAST];
13833 else
13834 table = bgp->rib[afi][safi];
13835
13836 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13837 || (safi == SAFI_EVPN)) {
13838
13839 struct bgp_dest *dest;
13840
13841 for (dest = bgp_table_top(table); dest;
13842 dest = bgp_route_next(dest)) {
13843 table = bgp_dest_get_bgp_table_info(dest);
13844 if (!table)
13845 continue;
13846
13847 output_count_per_rd = 0;
13848 filtered_count_per_rd = 0;
13849
13850 if (use_json)
13851 json_routes = json_object_new_object();
13852
13853 const struct prefix_rd *prd;
13854 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13855 dest);
13856
13857 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13858
13859 show_adj_route(vty, peer, table, afi, safi, type,
13860 rmap_name, json, json_routes, json_scode,
13861 json_ocode, show_flags, &header1,
13862 &header2, rd_str, &output_count_per_rd,
13863 &filtered_count_per_rd);
13864
13865 /* Don't include an empty RD in the output! */
13866 if (json_routes && (output_count_per_rd > 0))
13867 json_object_object_add(json_ar, rd_str,
13868 json_routes);
13869
13870 output_count += output_count_per_rd;
13871 filtered_count += filtered_count_per_rd;
13872 }
13873 } else
13874 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13875 json, json_ar, json_scode, json_ocode,
13876 show_flags, &header1, &header2, rd_str,
13877 &output_count, &filtered_count);
13878
13879 if (use_json) {
c1984955
TA
13880 if (type == bgp_show_adj_route_advertised)
13881 json_object_object_add(json, "advertisedRoutes",
13882 json_ar);
13883 else
13884 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
13885 json_object_int_add(json, "totalPrefixCounter", output_count);
13886 json_object_int_add(json, "filteredPrefixCounter",
13887 filtered_count);
13888
690c3134
MW
13889 /*
13890 * These fields only give up ownership to `json` when `header1`
13891 * is used (set to zero). See code in `show_adj_route` and
13892 * `show_adj_route_header`.
13893 */
13894 if (header1 == 1) {
d9478df0
TA
13895 json_object_free(json_scode);
13896 json_object_free(json_ocode);
13897 }
13898
75eeda93 13899 vty_json(vty, json);
d9478df0
TA
13900 } else if (output_count > 0) {
13901 if (filtered_count > 0)
13902 vty_out(vty,
13903 "\nTotal number of prefixes %ld (%ld filtered)\n",
13904 output_count, filtered_count);
13905 else
13906 vty_out(vty, "\nTotal number of prefixes %ld\n",
13907 output_count);
13908 }
0b16f239 13909
d62a17ae 13910 return CMD_SUCCESS;
a636c635 13911}
50ef26d4 13912
f20ce998
DS
13913DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13914 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13915 "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]",
13916 SHOW_STR
13917 IP_STR
13918 BGP_STR
13919 BGP_INSTANCE_HELP_STR
13920 BGP_AFI_HELP_STR
13921 BGP_SAFI_WITH_LABEL_HELP_STR
13922 "Detailed information on TCP and BGP neighbor connections\n"
13923 "Neighbor to display information about\n"
13924 "Neighbor to display information about\n"
13925 "Neighbor on BGP configured interface\n"
13926 "Display the routes selected by best path\n"
13927 JSON_STR
13928 "Increase table width for longer prefixes\n")
13929{
13930 afi_t afi = AFI_IP6;
13931 safi_t safi = SAFI_UNICAST;
13932 char *rmap_name = NULL;
13933 char *peerstr = NULL;
13934 struct bgp *bgp = NULL;
13935 struct peer *peer;
13936 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13937 int idx = 0;
96c81f66 13938 uint16_t show_flags = 0;
96f3485c
MK
13939
13940 if (uj)
13941 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13942
13943 if (wide)
13944 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13945
13946 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13947 &bgp, uj);
13948
13949 if (!idx)
13950 return CMD_WARNING;
13951
13952 argv_find(argv, argc, "neighbors", &idx);
13953 peerstr = argv[++idx]->arg;
13954
13955 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13956 if (!peer)
13957 return CMD_WARNING;
13958
96f3485c
MK
13959 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13960 show_flags);
f20ce998
DS
13961}
13962
ae248832 13963DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13964 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13965 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
718e3744 13966 SHOW_STR
13967 IP_STR
13968 BGP_STR
a636c635 13969 BGP_INSTANCE_HELP_STR
7395a2c9 13970 BGP_AFI_HELP_STR
4dd6177e 13971 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13972 "Display the entries for all address families\n"
718e3744 13973 "Detailed information on TCP and BGP neighbor connections\n"
13974 "Neighbor to display information about\n"
13975 "Neighbor to display information about\n"
91d37724 13976 "Neighbor on BGP configured interface\n"
a636c635 13977 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13978 "Display the received routes from neighbor\n"
13979 "Display the filtered routes received from neighbor\n"
a636c635
DW
13980 "Route-map to modify the attributes\n"
13981 "Name of the route map\n"
ae248832
MK
13982 JSON_STR
13983 "Increase table width for longer prefixes\n")
718e3744 13984{
d62a17ae 13985 afi_t afi = AFI_IP6;
13986 safi_t safi = SAFI_UNICAST;
13987 char *rmap_name = NULL;
13988 char *peerstr = NULL;
d62a17ae 13989 struct bgp *bgp = NULL;
13990 struct peer *peer;
6392aaa6 13991 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13992 int idx = 0;
96f3485c 13993 bool first = true;
96c81f66 13994 uint16_t show_flags = 0;
75ce3b14
DA
13995 struct listnode *node;
13996 struct bgp *abgp;
6392aaa6 13997
96f3485c 13998 if (uj) {
d62a17ae 13999 argc--;
96f3485c
MK
14000 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14001 }
14002
14003 if (all) {
14004 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14005 if (argv_find(argv, argc, "ipv4", &idx))
14006 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14007
14008 if (argv_find(argv, argc, "ipv6", &idx))
14009 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14010 }
14011
14012 if (wide)
14013 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14014
9f049418
DS
14015 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14016 &bgp, uj);
14017 if (!idx)
14018 return CMD_WARNING;
14019
d62a17ae 14020 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14021 argv_find(argv, argc, "neighbors", &idx);
14022 peerstr = argv[++idx]->arg;
8c3deaae 14023
d62a17ae 14024 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14025 if (!peer)
14026 return CMD_WARNING;
856ca177 14027
d62a17ae 14028 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14029 type = bgp_show_adj_route_advertised;
14030 else if (argv_find(argv, argc, "received-routes", &idx))
14031 type = bgp_show_adj_route_received;
14032 else if (argv_find(argv, argc, "filtered-routes", &idx))
14033 type = bgp_show_adj_route_filtered;
14034
d62a17ae 14035 if (argv_find(argv, argc, "route-map", &idx))
14036 rmap_name = argv[++idx]->arg;
95cbbd2a 14037
96f3485c
MK
14038 if (!all)
14039 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14040 show_flags);
14041 if (uj)
14042 vty_out(vty, "{\n");
14043
14044 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14045 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14046 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14047 : AFI_IP6;
75ce3b14
DA
14048 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14049 FOREACH_SAFI (safi) {
14050 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14051 continue;
96f3485c 14052
75ce3b14
DA
14053 if (uj) {
14054 if (first)
14055 first = false;
14056 else
14057 vty_out(vty, ",\n");
14058 vty_out(vty, "\"%s\":",
14059 get_afi_safi_str(afi, safi,
14060 true));
14061 } else
14062 vty_out(vty,
14063 "\nFor address family: %s\n",
14064 get_afi_safi_str(afi, safi,
14065 false));
96f3485c 14066
75ce3b14
DA
14067 peer_adj_routes(vty, peer, afi, safi, type,
14068 rmap_name, show_flags);
14069 }
96f3485c
MK
14070 }
14071 } else {
75ce3b14
DA
14072 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14073 FOREACH_AFI_SAFI (afi, safi) {
14074 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14075 continue;
96f3485c 14076
75ce3b14
DA
14077 if (uj) {
14078 if (first)
14079 first = false;
14080 else
14081 vty_out(vty, ",\n");
14082 vty_out(vty, "\"%s\":",
14083 get_afi_safi_str(afi, safi,
14084 true));
14085 } else
14086 vty_out(vty,
14087 "\nFor address family: %s\n",
14088 get_afi_safi_str(afi, safi,
14089 false));
96f3485c 14090
75ce3b14
DA
14091 peer_adj_routes(vty, peer, afi, safi, type,
14092 rmap_name, show_flags);
14093 }
96f3485c
MK
14094 }
14095 }
14096 if (uj)
14097 vty_out(vty, "}\n");
14098
14099 return CMD_SUCCESS;
95cbbd2a
ML
14100}
14101
718e3744 14102DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14103 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14104 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14105 SHOW_STR
14106 IP_STR
14107 BGP_STR
d3120452 14108 BGP_INSTANCE_HELP_STR
8c3deaae
QY
14109 "Address Family\n"
14110 "Address Family\n"
718e3744 14111 "Address Family modifier\n"
14112 "Detailed information on TCP and BGP neighbor connections\n"
14113 "Neighbor to display information about\n"
14114 "Neighbor to display information about\n"
91d37724 14115 "Neighbor on BGP configured interface\n"
718e3744 14116 "Display information received from a BGP neighbor\n"
856ca177 14117 "Display the prefixlist filter\n"
9973d184 14118 JSON_STR)
718e3744 14119{
d62a17ae 14120 afi_t afi = AFI_IP6;
14121 safi_t safi = SAFI_UNICAST;
14122 char *peerstr = NULL;
d62a17ae 14123 char name[BUFSIZ];
d62a17ae 14124 struct peer *peer;
d3120452 14125 int count;
d62a17ae 14126 int idx = 0;
d3120452
IR
14127 struct bgp *bgp = NULL;
14128 bool uj = use_json(argc, argv);
14129
14130 if (uj)
14131 argc--;
14132
14133 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14134 &bgp, uj);
14135 if (!idx)
14136 return CMD_WARNING;
d62a17ae 14137
d62a17ae 14138 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14139 argv_find(argv, argc, "neighbors", &idx);
14140 peerstr = argv[++idx]->arg;
14141
d3120452
IR
14142 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14143 if (!peer)
14144 return CMD_WARNING;
718e3744 14145
4ced1a2c 14146 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14147 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14148 if (count) {
14149 if (!uj)
14150 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14151 get_afi_safi_str(afi, safi, false));
d62a17ae 14152 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14153 } else {
14154 if (uj)
14155 vty_out(vty, "{}\n");
14156 else
14157 vty_out(vty, "No functional output\n");
14158 }
718e3744 14159
d62a17ae 14160 return CMD_SUCCESS;
14161}
14162
14163static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14164 afi_t afi, safi_t safi,
9f049418 14165 enum bgp_show_type type, bool use_json)
d62a17ae 14166{
96c81f66 14167 uint16_t show_flags = 0;
96f3485c
MK
14168
14169 if (use_json)
14170 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14171
d62a17ae 14172 if (!peer || !peer->afc[afi][safi]) {
14173 if (use_json) {
14174 json_object *json_no = NULL;
14175 json_no = json_object_new_object();
14176 json_object_string_add(
14177 json_no, "warning",
14178 "No such neighbor or address family");
14179 vty_out(vty, "%s\n",
14180 json_object_to_json_string(json_no));
14181 json_object_free(json_no);
14182 } else
14183 vty_out(vty, "%% No such neighbor or address family\n");
14184 return CMD_WARNING;
14185 }
47fc97cc 14186
7daf25a3
TA
14187 /* labeled-unicast routes live in the unicast table */
14188 if (safi == SAFI_LABELED_UNICAST)
14189 safi = SAFI_UNICAST;
14190
1e2ce4f1
DS
14191 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14192 RPKI_NOT_BEING_USED);
718e3744 14193}
14194
dba3c1d3
PG
14195DEFUN (show_ip_bgp_flowspec_routes_detailed,
14196 show_ip_bgp_flowspec_routes_detailed_cmd,
14197 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14198 SHOW_STR
14199 IP_STR
14200 BGP_STR
14201 BGP_INSTANCE_HELP_STR
14202 BGP_AFI_HELP_STR
14203 "SAFI Flowspec\n"
14204 "Detailed information on flowspec entries\n"
14205 JSON_STR)
14206{
458c1475 14207 afi_t afi = AFI_IP6;
dba3c1d3
PG
14208 safi_t safi = SAFI_UNICAST;
14209 struct bgp *bgp = NULL;
14210 int idx = 0;
9f049418 14211 bool uj = use_json(argc, argv);
5be6fa9b 14212 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14213
96f3485c 14214 if (uj) {
9f049418 14215 argc--;
96f3485c
MK
14216 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14217 }
dba3c1d3
PG
14218
14219 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14220 &bgp, uj);
dba3c1d3
PG
14221 if (!idx)
14222 return CMD_WARNING;
14223
96f3485c 14224 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14225 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14226}
14227
718e3744 14228DEFUN (show_ip_bgp_neighbor_routes,
14229 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14230 "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 14231 SHOW_STR
14232 IP_STR
14233 BGP_STR
8386ac43 14234 BGP_INSTANCE_HELP_STR
4f280b15 14235 BGP_AFI_HELP_STR
4dd6177e 14236 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14237 "Detailed information on TCP and BGP neighbor connections\n"
14238 "Neighbor to display information about\n"
14239 "Neighbor to display information about\n"
91d37724 14240 "Neighbor on BGP configured interface\n"
2525cf39 14241 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14242 "Display the dampened routes received from neighbor\n"
14243 "Display routes learned from neighbor\n"
9973d184 14244 JSON_STR)
718e3744 14245{
d62a17ae 14246 char *peerstr = NULL;
14247 struct bgp *bgp = NULL;
14248 afi_t afi = AFI_IP6;
14249 safi_t safi = SAFI_UNICAST;
14250 struct peer *peer;
14251 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14252 int idx = 0;
9f049418
DS
14253 bool uj = use_json(argc, argv);
14254
14255 if (uj)
14256 argc--;
bb46e94f 14257
d62a17ae 14258 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14259 &bgp, uj);
d62a17ae 14260 if (!idx)
14261 return CMD_WARNING;
c493f2d8 14262
d62a17ae 14263 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14264 argv_find(argv, argc, "neighbors", &idx);
14265 peerstr = argv[++idx]->arg;
8c3deaae 14266
d62a17ae 14267 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14268 if (!peer)
d62a17ae 14269 return CMD_WARNING;
bb46e94f 14270
d62a17ae 14271 if (argv_find(argv, argc, "flap-statistics", &idx))
14272 sh_type = bgp_show_type_flap_neighbor;
14273 else if (argv_find(argv, argc, "dampened-routes", &idx))
14274 sh_type = bgp_show_type_damp_neighbor;
14275 else if (argv_find(argv, argc, "routes", &idx))
14276 sh_type = bgp_show_type_neighbor;
2525cf39 14277
d62a17ae 14278 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14279}
6b0655a2 14280
734b349e 14281struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14282
d62a17ae 14283struct bgp_distance {
14284 /* Distance value for the IP source prefix. */
d7c0a89a 14285 uint8_t distance;
718e3744 14286
d62a17ae 14287 /* Name of the access-list to be matched. */
14288 char *access_list;
718e3744 14289};
14290
4f280b15
LB
14291DEFUN (show_bgp_afi_vpn_rd_route,
14292 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14293 "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
14294 SHOW_STR
14295 BGP_STR
14296 BGP_AFI_HELP_STR
14297 "Address Family modifier\n"
14298 "Display information for a route distinguisher\n"
14299 "Route Distinguisher\n"
a111dd97 14300 "All Route Distinguishers\n"
7395a2c9
DS
14301 "Network in the BGP routing table to display\n"
14302 "Network in the BGP routing table to display\n"
14303 JSON_STR)
4f280b15 14304{
d62a17ae 14305 int ret;
14306 struct prefix_rd prd;
14307 afi_t afi = AFI_MAX;
14308 int idx = 0;
4f280b15 14309
ff6566f3
DS
14310 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14311 vty_out(vty, "%% Malformed Address Family\n");
14312 return CMD_WARNING;
14313 }
14314
a111dd97
TA
14315 if (!strcmp(argv[5]->arg, "all"))
14316 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14317 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14318 RPKI_NOT_BEING_USED,
14319 use_json(argc, argv));
14320
d62a17ae 14321 ret = str2prefix_rd(argv[5]->arg, &prd);
14322 if (!ret) {
14323 vty_out(vty, "%% Malformed Route Distinguisher\n");
14324 return CMD_WARNING;
14325 }
ff6566f3 14326
d62a17ae 14327 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14328 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14329 use_json(argc, argv));
4f280b15
LB
14330}
14331
d62a17ae 14332static struct bgp_distance *bgp_distance_new(void)
718e3744 14333{
d62a17ae 14334 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14335}
14336
d62a17ae 14337static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14338{
d62a17ae 14339 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14340}
14341
585f1adc
IR
14342static int bgp_distance_set(struct vty *vty, const char *distance_str,
14343 const char *ip_str, const char *access_list_str)
718e3744 14344{
d62a17ae 14345 int ret;
585f1adc
IR
14346 afi_t afi;
14347 safi_t safi;
d62a17ae 14348 struct prefix p;
585f1adc 14349 uint8_t distance;
9bcb3eef 14350 struct bgp_dest *dest;
d62a17ae 14351 struct bgp_distance *bdistance;
718e3744 14352
585f1adc
IR
14353 afi = bgp_node_afi(vty);
14354 safi = bgp_node_safi(vty);
14355
d62a17ae 14356 ret = str2prefix(ip_str, &p);
14357 if (ret == 0) {
585f1adc 14358 vty_out(vty, "Malformed prefix\n");
d62a17ae 14359 return CMD_WARNING_CONFIG_FAILED;
14360 }
718e3744 14361
585f1adc
IR
14362 distance = atoi(distance_str);
14363
d62a17ae 14364 /* Get BGP distance node. */
9bcb3eef
DS
14365 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14366 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14367 if (bdistance)
9bcb3eef 14368 bgp_dest_unlock_node(dest);
ca2e160d 14369 else {
d62a17ae 14370 bdistance = bgp_distance_new();
9bcb3eef 14371 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14372 }
718e3744 14373
d62a17ae 14374 /* Set distance value. */
14375 bdistance->distance = distance;
718e3744 14376
d62a17ae 14377 /* Reset access-list configuration. */
e1b36e13 14378 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14379 if (access_list_str)
14380 bdistance->access_list =
14381 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14382
d62a17ae 14383 return CMD_SUCCESS;
718e3744 14384}
14385
585f1adc
IR
14386static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14387 const char *ip_str, const char *access_list_str)
718e3744 14388{
d62a17ae 14389 int ret;
585f1adc
IR
14390 afi_t afi;
14391 safi_t safi;
d62a17ae 14392 struct prefix p;
585f1adc 14393 int distance;
9bcb3eef 14394 struct bgp_dest *dest;
d62a17ae 14395 struct bgp_distance *bdistance;
718e3744 14396
585f1adc
IR
14397 afi = bgp_node_afi(vty);
14398 safi = bgp_node_safi(vty);
14399
d62a17ae 14400 ret = str2prefix(ip_str, &p);
14401 if (ret == 0) {
585f1adc 14402 vty_out(vty, "Malformed prefix\n");
d62a17ae 14403 return CMD_WARNING_CONFIG_FAILED;
14404 }
718e3744 14405
9bcb3eef
DS
14406 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14407 if (!dest) {
585f1adc 14408 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14409 return CMD_WARNING_CONFIG_FAILED;
14410 }
718e3744 14411
9bcb3eef 14412 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14413 distance = atoi(distance_str);
1f9a9fff 14414
d62a17ae 14415 if (bdistance->distance != distance) {
585f1adc 14416 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14417 bgp_dest_unlock_node(dest);
d62a17ae 14418 return CMD_WARNING_CONFIG_FAILED;
14419 }
718e3744 14420
0a22ddfb 14421 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14422 bgp_distance_free(bdistance);
718e3744 14423
9bcb3eef
DS
14424 bgp_dest_set_bgp_path_info(dest, NULL);
14425 bgp_dest_unlock_node(dest);
14426 bgp_dest_unlock_node(dest);
718e3744 14427
d62a17ae 14428 return CMD_SUCCESS;
718e3744 14429}
14430
718e3744 14431/* Apply BGP information to distance method. */
b8685f9b 14432uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14433 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14434{
9bcb3eef 14435 struct bgp_dest *dest;
801bb996 14436 struct prefix q = {0};
d62a17ae 14437 struct peer *peer;
14438 struct bgp_distance *bdistance;
14439 struct access_list *alist;
14440 struct bgp_static *bgp_static;
14441
14442 if (!bgp)
14443 return 0;
14444
40381db7 14445 peer = pinfo->peer;
d62a17ae 14446
7b7d48e5
DS
14447 if (pinfo->attr->distance)
14448 return pinfo->attr->distance;
14449
801bb996
CS
14450 /* Check source address.
14451 * Note: for aggregate route, peer can have unspec af type.
14452 */
14453 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14454 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14455 return 0;
14456
9bcb3eef
DS
14457 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14458 if (dest) {
14459 bdistance = bgp_dest_get_bgp_distance_info(dest);
14460 bgp_dest_unlock_node(dest);
d62a17ae 14461
14462 if (bdistance->access_list) {
14463 alist = access_list_lookup(afi, bdistance->access_list);
14464 if (alist
14465 && access_list_apply(alist, p) == FILTER_PERMIT)
14466 return bdistance->distance;
14467 } else
14468 return bdistance->distance;
718e3744 14469 }
718e3744 14470
d62a17ae 14471 /* Backdoor check. */
9bcb3eef
DS
14472 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14473 if (dest) {
14474 bgp_static = bgp_dest_get_bgp_static_info(dest);
14475 bgp_dest_unlock_node(dest);
718e3744 14476
d62a17ae 14477 if (bgp_static->backdoor) {
14478 if (bgp->distance_local[afi][safi])
14479 return bgp->distance_local[afi][safi];
14480 else
14481 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14482 }
718e3744 14483 }
718e3744 14484
d62a17ae 14485 if (peer->sort == BGP_PEER_EBGP) {
14486 if (bgp->distance_ebgp[afi][safi])
14487 return bgp->distance_ebgp[afi][safi];
14488 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14489 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14490 if (bgp->distance_ibgp[afi][safi])
14491 return bgp->distance_ibgp[afi][safi];
14492 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14493 } else {
14494 if (bgp->distance_local[afi][safi])
14495 return bgp->distance_local[afi][safi];
14496 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14497 }
718e3744 14498}
14499
a612fb77
DA
14500/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14501 * we should tell ZEBRA update the routes for a specific
14502 * AFI/SAFI to reflect changes in RIB.
14503 */
585f1adc
IR
14504static void bgp_announce_routes_distance_update(struct bgp *bgp,
14505 afi_t update_afi,
14506 safi_t update_safi)
a612fb77
DA
14507{
14508 afi_t afi;
14509 safi_t safi;
14510
14511 FOREACH_AFI_SAFI (afi, safi) {
14512 if (!bgp_fibupd_safi(safi))
14513 continue;
14514
8b54bc30
DA
14515 if (afi != update_afi && safi != update_safi)
14516 continue;
14517
14518 if (BGP_DEBUG(zebra, ZEBRA))
14519 zlog_debug(
14520 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14521 __func__, afi, safi);
14522 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14523 }
14524}
14525
585f1adc
IR
14526DEFUN (bgp_distance,
14527 bgp_distance_cmd,
14528 "distance bgp (1-255) (1-255) (1-255)",
14529 "Define an administrative distance\n"
14530 "BGP distance\n"
14531 "Distance for routes external to the AS\n"
14532 "Distance for routes internal to the AS\n"
14533 "Distance for local routes\n")
718e3744 14534{
585f1adc 14535 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14536 int idx_number = 2;
14537 int idx_number_2 = 3;
14538 int idx_number_3 = 4;
585f1adc
IR
14539 int distance_ebgp = atoi(argv[idx_number]->arg);
14540 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14541 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14542 afi_t afi;
14543 safi_t safi;
718e3744 14544
d62a17ae 14545 afi = bgp_node_afi(vty);
14546 safi = bgp_node_safi(vty);
718e3744 14547
585f1adc
IR
14548 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14549 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14550 || bgp->distance_local[afi][safi] != distance_local) {
14551 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14552 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14553 bgp->distance_local[afi][safi] = distance_local;
14554 bgp_announce_routes_distance_update(bgp, afi, safi);
14555 }
14556 return CMD_SUCCESS;
14557}
37a87b8f 14558
585f1adc
IR
14559DEFUN (no_bgp_distance,
14560 no_bgp_distance_cmd,
14561 "no distance bgp [(1-255) (1-255) (1-255)]",
14562 NO_STR
14563 "Define an administrative distance\n"
14564 "BGP distance\n"
14565 "Distance for routes external to the AS\n"
14566 "Distance for routes internal to the AS\n"
14567 "Distance for local routes\n")
718e3744 14568{
585f1adc 14569 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14570 afi_t afi;
14571 safi_t safi;
37a87b8f
CS
14572
14573 afi = bgp_node_afi(vty);
14574 safi = bgp_node_safi(vty);
14575
585f1adc
IR
14576 if (bgp->distance_ebgp[afi][safi] != 0
14577 || bgp->distance_ibgp[afi][safi] != 0
14578 || bgp->distance_local[afi][safi] != 0) {
14579 bgp->distance_ebgp[afi][safi] = 0;
14580 bgp->distance_ibgp[afi][safi] = 0;
14581 bgp->distance_local[afi][safi] = 0;
14582 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14583 }
585f1adc
IR
14584 return CMD_SUCCESS;
14585}
37a87b8f 14586
37a87b8f 14587
585f1adc
IR
14588DEFUN (bgp_distance_source,
14589 bgp_distance_source_cmd,
14590 "distance (1-255) A.B.C.D/M",
14591 "Define an administrative distance\n"
14592 "Administrative distance\n"
14593 "IP source prefix\n")
14594{
14595 int idx_number = 1;
14596 int idx_ipv4_prefixlen = 2;
14597 bgp_distance_set(vty, argv[idx_number]->arg,
14598 argv[idx_ipv4_prefixlen]->arg, NULL);
14599 return CMD_SUCCESS;
734b349e
MZ
14600}
14601
585f1adc
IR
14602DEFUN (no_bgp_distance_source,
14603 no_bgp_distance_source_cmd,
14604 "no distance (1-255) A.B.C.D/M",
14605 NO_STR
14606 "Define an administrative distance\n"
14607 "Administrative distance\n"
14608 "IP source prefix\n")
37a87b8f 14609{
585f1adc
IR
14610 int idx_number = 2;
14611 int idx_ipv4_prefixlen = 3;
14612 bgp_distance_unset(vty, argv[idx_number]->arg,
14613 argv[idx_ipv4_prefixlen]->arg, NULL);
14614 return CMD_SUCCESS;
37a87b8f
CS
14615}
14616
585f1adc
IR
14617DEFUN (bgp_distance_source_access_list,
14618 bgp_distance_source_access_list_cmd,
14619 "distance (1-255) A.B.C.D/M WORD",
14620 "Define an administrative distance\n"
14621 "Administrative distance\n"
14622 "IP source prefix\n"
14623 "Access list name\n")
37a87b8f 14624{
585f1adc
IR
14625 int idx_number = 1;
14626 int idx_ipv4_prefixlen = 2;
14627 int idx_word = 3;
14628 bgp_distance_set(vty, argv[idx_number]->arg,
14629 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14630 return CMD_SUCCESS;
14631}
718e3744 14632
585f1adc
IR
14633DEFUN (no_bgp_distance_source_access_list,
14634 no_bgp_distance_source_access_list_cmd,
14635 "no distance (1-255) A.B.C.D/M WORD",
14636 NO_STR
14637 "Define an administrative distance\n"
14638 "Administrative distance\n"
14639 "IP source prefix\n"
14640 "Access list name\n")
14641{
14642 int idx_number = 2;
14643 int idx_ipv4_prefixlen = 3;
14644 int idx_word = 4;
14645 bgp_distance_unset(vty, argv[idx_number]->arg,
14646 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14647 return CMD_SUCCESS;
14648}
37a87b8f 14649
585f1adc
IR
14650DEFUN (ipv6_bgp_distance_source,
14651 ipv6_bgp_distance_source_cmd,
14652 "distance (1-255) X:X::X:X/M",
14653 "Define an administrative distance\n"
14654 "Administrative distance\n"
14655 "IP source prefix\n")
14656{
14657 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14658 return CMD_SUCCESS;
14659}
7ebe9748 14660
585f1adc
IR
14661DEFUN (no_ipv6_bgp_distance_source,
14662 no_ipv6_bgp_distance_source_cmd,
14663 "no distance (1-255) X:X::X:X/M",
14664 NO_STR
14665 "Define an administrative distance\n"
14666 "Administrative distance\n"
14667 "IP source prefix\n")
14668{
14669 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14670 return CMD_SUCCESS;
14671}
37a87b8f 14672
585f1adc
IR
14673DEFUN (ipv6_bgp_distance_source_access_list,
14674 ipv6_bgp_distance_source_access_list_cmd,
14675 "distance (1-255) X:X::X:X/M WORD",
14676 "Define an administrative distance\n"
14677 "Administrative distance\n"
14678 "IP source prefix\n"
14679 "Access list name\n")
14680{
14681 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14682 return CMD_SUCCESS;
718e3744 14683}
14684
585f1adc
IR
14685DEFUN (no_ipv6_bgp_distance_source_access_list,
14686 no_ipv6_bgp_distance_source_access_list_cmd,
14687 "no distance (1-255) X:X::X:X/M WORD",
14688 NO_STR
14689 "Define an administrative distance\n"
14690 "Administrative distance\n"
14691 "IP source prefix\n"
14692 "Access list name\n")
718e3744 14693{
585f1adc
IR
14694 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14695 return CMD_SUCCESS;
14696}
37a87b8f 14697
585f1adc
IR
14698DEFUN (bgp_damp_set,
14699 bgp_damp_set_cmd,
a30fec23 14700 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14701 "BGP Specific commands\n"
14702 "Enable route-flap dampening\n"
14703 "Half-life time for the penalty\n"
14704 "Value to start reusing a route\n"
14705 "Value to start suppressing a route\n"
14706 "Maximum duration to suppress a stable route\n")
14707{
14708 VTY_DECLVAR_CONTEXT(bgp, bgp);
14709 int idx_half_life = 2;
14710 int idx_reuse = 3;
14711 int idx_suppress = 4;
14712 int idx_max_suppress = 5;
37a87b8f
CS
14713 int half = DEFAULT_HALF_LIFE * 60;
14714 int reuse = DEFAULT_REUSE;
14715 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14716 int max = 4 * half;
14717
14718 if (argc == 6) {
14719 half = atoi(argv[idx_half_life]->arg) * 60;
14720 reuse = atoi(argv[idx_reuse]->arg);
14721 suppress = atoi(argv[idx_suppress]->arg);
14722 max = atoi(argv[idx_max_suppress]->arg) * 60;
14723 } else if (argc == 3) {
14724 half = atoi(argv[idx_half_life]->arg) * 60;
14725 max = 4 * half;
14726 }
14727
14728 /*
14729 * These can't be 0 but our SA doesn't understand the
14730 * way our cli is constructed
14731 */
14732 assert(reuse);
14733 assert(half);
14734 if (suppress < reuse) {
14735 vty_out(vty,
14736 "Suppress value cannot be less than reuse value \n");
14737 return 0;
14738 }
14739
14740 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14741 reuse, suppress, max);
14742}
14743
14744DEFUN (bgp_damp_unset,
14745 bgp_damp_unset_cmd,
a30fec23 14746 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14747 NO_STR
14748 "BGP Specific commands\n"
14749 "Enable route-flap dampening\n"
14750 "Half-life time for the penalty\n"
14751 "Value to start reusing a route\n"
14752 "Value to start suppressing a route\n"
14753 "Maximum duration to suppress a stable route\n")
14754{
14755 VTY_DECLVAR_CONTEXT(bgp, bgp);
14756 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14757}
14758
718e3744 14759/* Display specified route of BGP table. */
d62a17ae 14760static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14761 const char *ip_str, afi_t afi, safi_t safi,
14762 struct prefix_rd *prd, int prefix_check)
14763{
14764 int ret;
14765 struct prefix match;
9bcb3eef
DS
14766 struct bgp_dest *dest;
14767 struct bgp_dest *rm;
40381db7
DS
14768 struct bgp_path_info *pi;
14769 struct bgp_path_info *pi_temp;
d62a17ae 14770 struct bgp *bgp;
14771 struct bgp_table *table;
14772
14773 /* BGP structure lookup. */
14774 if (view_name) {
14775 bgp = bgp_lookup_by_name(view_name);
14776 if (bgp == NULL) {
14777 vty_out(vty, "%% Can't find BGP instance %s\n",
14778 view_name);
14779 return CMD_WARNING;
14780 }
14781 } else {
14782 bgp = bgp_get_default();
14783 if (bgp == NULL) {
14784 vty_out(vty, "%% No BGP process is configured\n");
14785 return CMD_WARNING;
14786 }
718e3744 14787 }
718e3744 14788
d62a17ae 14789 /* Check IP address argument. */
14790 ret = str2prefix(ip_str, &match);
14791 if (!ret) {
14792 vty_out(vty, "%% address is malformed\n");
14793 return CMD_WARNING;
14794 }
718e3744 14795
d62a17ae 14796 match.family = afi2family(afi);
14797
14798 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14799 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14800 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14801 dest = bgp_route_next(dest)) {
14802 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14803
9bcb3eef 14804 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14805 continue;
9bcb3eef 14806 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14807 if (!table)
ea47320b 14808 continue;
4953391b
DA
14809 rm = bgp_node_match(table, &match);
14810 if (rm == NULL)
ea47320b 14811 continue;
d62a17ae 14812
9bcb3eef 14813 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14814
ea47320b 14815 if (!prefix_check
b54892e0 14816 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14817 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14818 while (pi) {
14819 if (pi->extra && pi->extra->damp_info) {
14820 pi_temp = pi->next;
ea47320b 14821 bgp_damp_info_free(
19971c9a 14822 pi->extra->damp_info,
5c8846f6 14823 1, afi, safi);
40381db7 14824 pi = pi_temp;
ea47320b 14825 } else
40381db7 14826 pi = pi->next;
d62a17ae 14827 }
ea47320b
DL
14828 }
14829
9bcb3eef 14830 bgp_dest_unlock_node(rm);
d62a17ae 14831 }
14832 } else {
4953391b
DA
14833 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14834 if (dest != NULL) {
9bcb3eef 14835 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14836
d62a17ae 14837 if (!prefix_check
9bcb3eef
DS
14838 || dest_p->prefixlen == match.prefixlen) {
14839 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14840 while (pi) {
14841 if (pi->extra && pi->extra->damp_info) {
14842 pi_temp = pi->next;
d62a17ae 14843 bgp_damp_info_free(
19971c9a 14844 pi->extra->damp_info,
5c8846f6 14845 1, afi, safi);
40381db7 14846 pi = pi_temp;
d62a17ae 14847 } else
40381db7 14848 pi = pi->next;
d62a17ae 14849 }
14850 }
14851
9bcb3eef 14852 bgp_dest_unlock_node(dest);
d62a17ae 14853 }
14854 }
718e3744 14855
d62a17ae 14856 return CMD_SUCCESS;
718e3744 14857}
14858
14859DEFUN (clear_ip_bgp_dampening,
14860 clear_ip_bgp_dampening_cmd,
14861 "clear ip bgp dampening",
14862 CLEAR_STR
14863 IP_STR
14864 BGP_STR
14865 "Clear route flap dampening information\n")
14866{
b4f7f45b 14867 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14868 return CMD_SUCCESS;
718e3744 14869}
14870
14871DEFUN (clear_ip_bgp_dampening_prefix,
14872 clear_ip_bgp_dampening_prefix_cmd,
14873 "clear ip bgp dampening A.B.C.D/M",
14874 CLEAR_STR
14875 IP_STR
14876 BGP_STR
14877 "Clear route flap dampening information\n"
0c7b1b01 14878 "IPv4 prefix\n")
718e3744 14879{
d62a17ae 14880 int idx_ipv4_prefixlen = 4;
14881 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14882 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14883}
14884
14885DEFUN (clear_ip_bgp_dampening_address,
14886 clear_ip_bgp_dampening_address_cmd,
14887 "clear ip bgp dampening A.B.C.D",
14888 CLEAR_STR
14889 IP_STR
14890 BGP_STR
14891 "Clear route flap dampening information\n"
14892 "Network to clear damping information\n")
14893{
d62a17ae 14894 int idx_ipv4 = 4;
14895 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14896 SAFI_UNICAST, NULL, 0);
718e3744 14897}
14898
14899DEFUN (clear_ip_bgp_dampening_address_mask,
14900 clear_ip_bgp_dampening_address_mask_cmd,
14901 "clear ip bgp dampening A.B.C.D A.B.C.D",
14902 CLEAR_STR
14903 IP_STR
14904 BGP_STR
14905 "Clear route flap dampening information\n"
14906 "Network to clear damping information\n"
14907 "Network mask\n")
14908{
d62a17ae 14909 int idx_ipv4 = 4;
14910 int idx_ipv4_2 = 5;
14911 int ret;
14912 char prefix_str[BUFSIZ];
718e3744 14913
d62a17ae 14914 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14915 prefix_str, sizeof(prefix_str));
d62a17ae 14916 if (!ret) {
14917 vty_out(vty, "%% Inconsistent address and mask\n");
14918 return CMD_WARNING;
14919 }
718e3744 14920
d62a17ae 14921 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14922 NULL, 0);
718e3744 14923}
6b0655a2 14924
e3b78da8 14925static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14926{
14927 struct vty *vty = arg;
e3b78da8 14928 struct peer *peer = bucket->data;
825d9834
DS
14929 char buf[SU_ADDRSTRLEN];
14930
14931 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14932 sockunion2str(&peer->su, buf, sizeof(buf)));
14933}
14934
2a0e69ae
DS
14935DEFUN (show_bgp_listeners,
14936 show_bgp_listeners_cmd,
14937 "show bgp listeners",
14938 SHOW_STR
14939 BGP_STR
14940 "Display Listen Sockets and who created them\n")
14941{
14942 bgp_dump_listener_info(vty);
14943
14944 return CMD_SUCCESS;
14945}
14946
825d9834
DS
14947DEFUN (show_bgp_peerhash,
14948 show_bgp_peerhash_cmd,
14949 "show bgp peerhash",
14950 SHOW_STR
14951 BGP_STR
14952 "Display information about the BGP peerhash\n")
14953{
14954 struct list *instances = bm->bgp;
14955 struct listnode *node;
14956 struct bgp *bgp;
14957
14958 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14959 vty_out(vty, "BGP: %s\n", bgp->name);
14960 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14961 vty);
14962 }
14963
14964 return CMD_SUCCESS;
14965}
14966
587ff0fd 14967/* also used for encap safi */
2b791107
DL
14968static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14969 afi_t afi, safi_t safi)
d62a17ae 14970{
9bcb3eef
DS
14971 struct bgp_dest *pdest;
14972 struct bgp_dest *dest;
d62a17ae 14973 struct bgp_table *table;
b54892e0
DS
14974 const struct prefix *p;
14975 const struct prefix_rd *prd;
d62a17ae 14976 struct bgp_static *bgp_static;
14977 mpls_label_t label;
d62a17ae 14978 char rdbuf[RD_ADDRSTRLEN];
14979
14980 /* Network configuration. */
9bcb3eef
DS
14981 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14982 pdest = bgp_route_next(pdest)) {
14983 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14984 if (!table)
ea47320b 14985 continue;
d62a17ae 14986
9bcb3eef
DS
14987 for (dest = bgp_table_top(table); dest;
14988 dest = bgp_route_next(dest)) {
14989 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14990 if (bgp_static == NULL)
ea47320b 14991 continue;
d62a17ae 14992
9bcb3eef
DS
14993 p = bgp_dest_get_prefix(dest);
14994 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14995 pdest);
d62a17ae 14996
ea47320b 14997 /* "network" configuration display. */
06b9f471 14998 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14999 label = decode_label(&bgp_static->label);
15000
8228a9a7 15001 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
15002 if (safi == SAFI_MPLS_VPN)
15003 vty_out(vty, " label %u", label);
15004
15005 if (bgp_static->rmap.name)
15006 vty_out(vty, " route-map %s",
15007 bgp_static->rmap.name);
e2a86ad9
DS
15008
15009 if (bgp_static->backdoor)
15010 vty_out(vty, " backdoor");
15011
ea47320b
DL
15012 vty_out(vty, "\n");
15013 }
15014 }
d62a17ae 15015}
15016
2b791107
DL
15017static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15018 afi_t afi, safi_t safi)
d62a17ae 15019{
9bcb3eef
DS
15020 struct bgp_dest *pdest;
15021 struct bgp_dest *dest;
d62a17ae 15022 struct bgp_table *table;
b54892e0
DS
15023 const struct prefix *p;
15024 const struct prefix_rd *prd;
d62a17ae 15025 struct bgp_static *bgp_static;
ff44f570 15026 char buf[PREFIX_STRLEN * 2];
d62a17ae 15027 char buf2[SU_ADDRSTRLEN];
15028 char rdbuf[RD_ADDRSTRLEN];
5f933e1e 15029 char esi_buf[ESI_STR_LEN];
d62a17ae 15030
15031 /* Network configuration. */
9bcb3eef
DS
15032 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15033 pdest = bgp_route_next(pdest)) {
15034 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15035 if (!table)
ea47320b 15036 continue;
d62a17ae 15037
9bcb3eef
DS
15038 for (dest = bgp_table_top(table); dest;
15039 dest = bgp_route_next(dest)) {
15040 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15041 if (bgp_static == NULL)
ea47320b 15042 continue;
d62a17ae 15043
ea47320b 15044 char *macrouter = NULL;
d62a17ae 15045
ea47320b
DL
15046 if (bgp_static->router_mac)
15047 macrouter = prefix_mac2str(
15048 bgp_static->router_mac, NULL, 0);
15049 if (bgp_static->eth_s_id)
0a50c248
AK
15050 esi_to_str(bgp_static->eth_s_id,
15051 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15052 p = bgp_dest_get_prefix(dest);
15053 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15054
ea47320b 15055 /* "network" configuration display. */
06b9f471 15056 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15057 if (p->u.prefix_evpn.route_type == 5) {
15058 char local_buf[PREFIX_STRLEN];
3714a385 15059 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15060 struct prefix_evpn *)p)
15061 ? AF_INET
15062 : AF_INET6;
3714a385 15063 inet_ntop(family,
15064 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15065 local_buf, PREFIX_STRLEN);
772270f3
QY
15066 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15067 p->u.prefix_evpn.prefix_addr
15068 .ip_prefix_length);
197cb530
PG
15069 } else {
15070 prefix2str(p, buf, sizeof(buf));
15071 }
ea47320b 15072
a4d82a8a
PZ
15073 if (bgp_static->gatewayIp.family == AF_INET
15074 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15075 inet_ntop(bgp_static->gatewayIp.family,
15076 &bgp_static->gatewayIp.u.prefix, buf2,
15077 sizeof(buf2));
ea47320b 15078 vty_out(vty,
7bcc8dac 15079 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15080 buf, rdbuf,
15081 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15082 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15083 macrouter);
15084
0a22ddfb 15085 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15086 }
15087 }
3da6fcd5
PG
15088}
15089
718e3744 15090/* Configuration of static route announcement and aggregate
15091 information. */
2b791107
DL
15092void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15093 safi_t safi)
d62a17ae 15094{
9bcb3eef 15095 struct bgp_dest *dest;
b54892e0 15096 const struct prefix *p;
d62a17ae 15097 struct bgp_static *bgp_static;
15098 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15099
2b791107
DL
15100 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15101 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15102 return;
15103 }
d62a17ae 15104
2b791107
DL
15105 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15106 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15107 return;
15108 }
d62a17ae 15109
15110 /* Network configuration. */
9bcb3eef
DS
15111 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15112 dest = bgp_route_next(dest)) {
15113 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15114 if (bgp_static == NULL)
ea47320b 15115 continue;
d62a17ae 15116
9bcb3eef 15117 p = bgp_dest_get_prefix(dest);
d62a17ae 15118
8228a9a7 15119 vty_out(vty, " network %pFX", p);
d62a17ae 15120
ea47320b
DL
15121 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15122 vty_out(vty, " label-index %u",
15123 bgp_static->label_index);
d62a17ae 15124
ea47320b
DL
15125 if (bgp_static->rmap.name)
15126 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15127
15128 if (bgp_static->backdoor)
15129 vty_out(vty, " backdoor");
718e3744 15130
ea47320b
DL
15131 vty_out(vty, "\n");
15132 }
15133
d62a17ae 15134 /* Aggregate-address configuration. */
9bcb3eef
DS
15135 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15136 dest = bgp_route_next(dest)) {
15137 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15138 if (bgp_aggregate == NULL)
ea47320b 15139 continue;
d62a17ae 15140
9bcb3eef 15141 p = bgp_dest_get_prefix(dest);
d62a17ae 15142
8228a9a7 15143 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15144
ea47320b
DL
15145 if (bgp_aggregate->as_set)
15146 vty_out(vty, " as-set");
d62a17ae 15147
ea47320b
DL
15148 if (bgp_aggregate->summary_only)
15149 vty_out(vty, " summary-only");
718e3744 15150
20894f50
DA
15151 if (bgp_aggregate->rmap.name)
15152 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15153
229757f1
DA
15154 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15155 vty_out(vty, " origin %s",
15156 bgp_origin2str(bgp_aggregate->origin));
15157
6aabb15d
RZ
15158 if (bgp_aggregate->match_med)
15159 vty_out(vty, " matching-MED-only");
15160
365ab2e7
RZ
15161 if (bgp_aggregate->suppress_map_name)
15162 vty_out(vty, " suppress-map %s",
15163 bgp_aggregate->suppress_map_name);
15164
ea47320b
DL
15165 vty_out(vty, "\n");
15166 }
d62a17ae 15167}
734b349e 15168
2b791107 15169void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15170 safi_t safi)
d62a17ae 15171{
9bcb3eef 15172 struct bgp_dest *dest;
d62a17ae 15173 struct bgp_distance *bdistance;
15174
15175 /* Distance configuration. */
15176 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15177 && bgp->distance_local[afi][safi]
15178 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15179 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15180 || bgp->distance_local[afi][safi]
15181 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15182 vty_out(vty, " distance bgp %d %d %d\n",
15183 bgp->distance_ebgp[afi][safi],
15184 bgp->distance_ibgp[afi][safi],
15185 bgp->distance_local[afi][safi]);
15186 }
734b349e 15187
9bcb3eef
DS
15188 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15189 dest = bgp_route_next(dest)) {
15190 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15191 if (bdistance != NULL)
56ca3b5b 15192 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15193 bdistance->distance, dest,
d62a17ae 15194 bdistance->access_list ? bdistance->access_list
15195 : "");
ca2e160d 15196 }
718e3744 15197}
15198
15199/* Allocate routing table structure and install commands. */
d62a17ae 15200void bgp_route_init(void)
15201{
15202 afi_t afi;
15203 safi_t safi;
15204
15205 /* Init BGP distance table. */
05c7a1cc 15206 FOREACH_AFI_SAFI (afi, safi)
960035b2 15207 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15208
15209 /* IPv4 BGP commands. */
15210 install_element(BGP_NODE, &bgp_table_map_cmd);
15211 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15212 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15213
554b3b10 15214 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15215
15216 /* IPv4 unicast configuration. */
15217 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15218 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15219 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15220
554b3b10 15221 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15222
15223 /* IPv4 multicast configuration. */
15224 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15225 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15226 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15227 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15228
15229 /* IPv4 labeled-unicast configuration. */
fb985e0c 15230 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15231 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15232
d62a17ae 15233 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15234 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15235 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15236 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15237 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15238 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15239 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15240 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15241
15242 install_element(VIEW_NODE,
15243 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15244 install_element(VIEW_NODE,
15245 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15246 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15247 install_element(VIEW_NODE,
15248 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15249#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15250 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15251#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15252 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15253 install_element(VIEW_NODE,
44c69747 15254 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15255
d62a17ae 15256 /* BGP dampening clear commands */
15257 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15258 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15259
d62a17ae 15260 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15261 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15262
15263 /* prefix count */
15264 install_element(ENABLE_NODE,
15265 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15266#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15267 install_element(ENABLE_NODE,
15268 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15269#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15270
d62a17ae 15271 /* New config IPv6 BGP commands. */
15272 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15273 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15274 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15275
554b3b10 15276 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15277
15278 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15279
fb985e0c
DA
15280 /* IPv6 labeled unicast address family. */
15281 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15282 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15283
d62a17ae 15284 install_element(BGP_NODE, &bgp_distance_cmd);
15285 install_element(BGP_NODE, &no_bgp_distance_cmd);
15286 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15287 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15288 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15289 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15290 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15291 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15292 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15293 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15294 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15295 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15296 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15297 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15298 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15299 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15300 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15301 install_element(BGP_IPV4M_NODE,
15302 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15303 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15304 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15305 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15306 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15307 install_element(BGP_IPV6_NODE,
15308 &ipv6_bgp_distance_source_access_list_cmd);
15309 install_element(BGP_IPV6_NODE,
15310 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15311 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15312 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15313 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15314 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15315 install_element(BGP_IPV6M_NODE,
15316 &ipv6_bgp_distance_source_access_list_cmd);
15317 install_element(BGP_IPV6M_NODE,
15318 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15319
ef5f4b23 15320 /* BGP dampening */
585f1adc
IR
15321 install_element(BGP_NODE, &bgp_damp_set_cmd);
15322 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15323 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15324 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15325 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15326 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15327 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15328 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15329 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15330 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15331 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15332 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15333 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15334 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15335
15336 /* Large Communities */
15337 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15338 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15339
15340 /* show bgp ipv4 flowspec detailed */
15341 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15342
2a0e69ae 15343 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15344 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15345}
15346
15347void bgp_route_finish(void)
15348{
15349 afi_t afi;
15350 safi_t safi;
15351
05c7a1cc
QY
15352 FOREACH_AFI_SAFI (afi, safi) {
15353 bgp_table_unlock(bgp_distance_table[afi][safi]);
15354 bgp_distance_table[afi][safi] = NULL;
15355 }
228da428 15356}