]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: fix missing bgp_attr_flush on errors in bgp_update
[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;
568 bgp_peer_sort_t new_sort;
569 bgp_peer_sort_t 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 */
644 if (newattr->community &&
645 community_include(newattr->community, COMMUNITY_LLGR_STALE)) {
646 if (debug)
647 zlog_debug(
648 "%s: %s wins over %s due to LLGR_STALE community",
649 pfx_buf, new_buf, exist_buf);
650 return 0;
651 }
652
653 if (existattr->community &&
654 community_include(existattr->community, COMMUNITY_LLGR_STALE)) {
655 if (debug)
656 zlog_debug(
657 "%s: %s loses to %s due to LLGR_STALE community",
658 pfx_buf, new_buf, exist_buf);
659 return 1;
660 }
661
5df26422
NS
662 new_p = bgp_dest_get_prefix(new->net);
663
d62a17ae 664 /* For EVPN routes, we cannot just go by local vs remote, we have to
665 * look at the MAC mobility sequence number, if present.
666 */
5df26422
NS
667 if ((safi == SAFI_EVPN)
668 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 669 /* This is an error condition described in RFC 7432 Section
670 * 15.2. The RFC
671 * states that in this scenario "the PE MUST alert the operator"
672 * but it
673 * does not state what other action to take. In order to provide
674 * some
675 * consistency in this scenario we are going to prefer the path
676 * with the
677 * sticky flag.
678 */
679 if (newattr->sticky != existattr->sticky) {
680 if (!debug) {
5df26422
NS
681 prefix2str(new_p, pfx_buf,
682 sizeof(*pfx_buf)
683 * PREFIX2STR_BUFFER);
18ee8310 684 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
685 new, new_buf, sizeof(new_buf));
686 bgp_path_info_path_with_addpath_rx_str(
687 exist, exist_buf, sizeof(exist_buf));
d62a17ae 688 }
689
690 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 691 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
692 if (debug)
693 zlog_debug(
694 "%s: %s wins over %s due to sticky MAC flag",
695 pfx_buf, new_buf, exist_buf);
d62a17ae 696 return 1;
697 }
698
699 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 700 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
701 if (debug)
702 zlog_debug(
703 "%s: %s loses to %s due to sticky MAC flag",
704 pfx_buf, new_buf, exist_buf);
d62a17ae 705 return 0;
706 }
707 }
128ea8ab 708
d071f237
AK
709 new_esi = bgp_evpn_attr_get_esi(newattr);
710 exist_esi = bgp_evpn_attr_get_esi(existattr);
711 if (bgp_evpn_is_esi_valid(new_esi) &&
712 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
713 same_esi = true;
714 } else {
715 same_esi = false;
716 }
717
718 /* If both paths have the same non-zero ES and
719 * one path is local it wins.
720 * PS: Note the local path wins even if the remote
721 * has the higher MM seq. The local path's
722 * MM seq will be fixed up to match the highest
723 * rem seq, subsequently.
724 */
725 if (same_esi) {
726 char esi_buf[ESI_STR_LEN];
727
728 if (bgp_evpn_is_path_local(bgp, new)) {
729 *reason = bgp_path_selection_evpn_local_path;
730 if (debug)
731 zlog_debug(
732 "%s: %s wins over %s as ES %s is same and local",
733 pfx_buf, new_buf, exist_buf,
734 esi_to_str(new_esi, esi_buf,
735 sizeof(esi_buf)));
736 return 1;
737 }
738 if (bgp_evpn_is_path_local(bgp, exist)) {
739 *reason = bgp_path_selection_evpn_local_path;
740 if (debug)
741 zlog_debug(
742 "%s: %s loses to %s as ES %s is same and local",
743 pfx_buf, new_buf, exist_buf,
744 esi_to_str(new_esi, esi_buf,
745 sizeof(esi_buf)));
746 return 0;
747 }
748 }
749
d62a17ae 750 new_mm_seq = mac_mobility_seqnum(newattr);
751 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 752
d62a17ae 753 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 754 *reason = bgp_path_selection_evpn_seq;
d62a17ae 755 if (debug)
756 zlog_debug(
757 "%s: %s wins over %s due to MM seq %u > %u",
758 pfx_buf, new_buf, exist_buf, new_mm_seq,
759 exist_mm_seq);
760 return 1;
761 }
8ff56318 762
d62a17ae 763 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 764 *reason = bgp_path_selection_evpn_seq;
d62a17ae 765 if (debug)
766 zlog_debug(
767 "%s: %s loses to %s due to MM seq %u < %u",
768 pfx_buf, new_buf, exist_buf, new_mm_seq,
769 exist_mm_seq);
770 return 0;
771 }
6d8c603a 772
d071f237
AK
773 /* if the sequence numbers and ESI are the same and one path
774 * is non-proxy it wins (over proxy)
775 */
776 new_proxy = bgp_evpn_attr_is_proxy(newattr);
777 old_proxy = bgp_evpn_attr_is_proxy(existattr);
778 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
779 old_proxy != new_proxy) {
780 if (!new_proxy) {
781 *reason = bgp_path_selection_evpn_non_proxy;
782 if (debug)
783 zlog_debug(
784 "%s: %s wins over %s, same seq/es and non-proxy",
785 pfx_buf, new_buf, exist_buf);
786 return 1;
787 }
788
789 *reason = bgp_path_selection_evpn_non_proxy;
790 if (debug)
791 zlog_debug(
792 "%s: %s loses to %s, same seq/es and non-proxy",
793 pfx_buf, new_buf, exist_buf);
794 return 0;
795 }
796
6d8c603a
AK
797 /*
798 * if sequence numbers are the same path with the lowest IP
799 * wins
800 */
801 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
802 if (nh_cmp < 0) {
fdf81fa0 803 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
804 if (debug)
805 zlog_debug(
23d0a753 806 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 807 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 808 &new->attr->nexthop);
6d8c603a
AK
809 return 1;
810 }
811 if (nh_cmp > 0) {
fdf81fa0 812 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
813 if (debug)
814 zlog_debug(
23d0a753 815 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 816 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 817 &new->attr->nexthop);
6d8c603a
AK
818 return 0;
819 }
d62a17ae 820 }
9fbdd100 821
d62a17ae 822 /* 1. Weight check. */
d62a17ae 823 new_weight = newattr->weight;
824 exist_weight = existattr->weight;
8ff56318 825
d62a17ae 826 if (new_weight > exist_weight) {
fdf81fa0 827 *reason = bgp_path_selection_weight;
d62a17ae 828 if (debug)
829 zlog_debug("%s: %s wins over %s due to weight %d > %d",
830 pfx_buf, new_buf, exist_buf, new_weight,
831 exist_weight);
832 return 1;
833 }
718e3744 834
d62a17ae 835 if (new_weight < exist_weight) {
fdf81fa0 836 *reason = bgp_path_selection_weight;
d62a17ae 837 if (debug)
838 zlog_debug("%s: %s loses to %s due to weight %d < %d",
839 pfx_buf, new_buf, exist_buf, new_weight,
840 exist_weight);
841 return 0;
842 }
9fbdd100 843
d62a17ae 844 /* 2. Local preference check. */
845 new_pref = exist_pref = bgp->default_local_pref;
846
847 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
848 new_pref = newattr->local_pref;
849 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 exist_pref = existattr->local_pref;
851
852 if (new_pref > exist_pref) {
fdf81fa0 853 *reason = bgp_path_selection_local_pref;
d62a17ae 854 if (debug)
855 zlog_debug(
856 "%s: %s wins over %s due to localpref %d > %d",
857 pfx_buf, new_buf, exist_buf, new_pref,
858 exist_pref);
859 return 1;
860 }
718e3744 861
d62a17ae 862 if (new_pref < exist_pref) {
fdf81fa0 863 *reason = bgp_path_selection_local_pref;
d62a17ae 864 if (debug)
865 zlog_debug(
866 "%s: %s loses to %s due to localpref %d < %d",
867 pfx_buf, new_buf, exist_buf, new_pref,
868 exist_pref);
869 return 0;
870 }
9fbdd100 871
d62a17ae 872 /* 3. Local route check. We prefer:
873 * - BGP_ROUTE_STATIC
874 * - BGP_ROUTE_AGGREGATE
875 * - BGP_ROUTE_REDISTRIBUTE
876 */
33c6e933
DS
877 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
878 new->sub_type == BGP_ROUTE_IMPORTED);
879 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
880 exist->sub_type == BGP_ROUTE_IMPORTED);
881
882 if (new_origin && !exist_origin) {
fdf81fa0 883 *reason = bgp_path_selection_local_route;
d62a17ae 884 if (debug)
885 zlog_debug(
886 "%s: %s wins over %s due to preferred BGP_ROUTE type",
887 pfx_buf, new_buf, exist_buf);
888 return 1;
889 }
718e3744 890
33c6e933 891 if (!new_origin && exist_origin) {
fdf81fa0 892 *reason = bgp_path_selection_local_route;
d62a17ae 893 if (debug)
894 zlog_debug(
895 "%s: %s loses to %s due to preferred BGP_ROUTE type",
896 pfx_buf, new_buf, exist_buf);
897 return 0;
6811845b 898 }
718e3744 899
da0c0ef7
KM
900 /* Here if these are imported routes then get ultimate pi for
901 * path compare.
902 */
903 new = bgp_get_imported_bpi_ultimate(new);
904 exist = bgp_get_imported_bpi_ultimate(exist);
905 newattr = new->attr;
906 existattr = exist->attr;
907
d62a17ae 908 /* 4. AS path length check. */
892fedb6 909 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 910 int exist_hops = aspath_count_hops(existattr->aspath);
911 int exist_confeds = aspath_count_confeds(existattr->aspath);
912
892fedb6 913 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 914 int aspath_hops;
915
916 aspath_hops = aspath_count_hops(newattr->aspath);
917 aspath_hops += aspath_count_confeds(newattr->aspath);
918
919 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 920 *reason = bgp_path_selection_confed_as_path;
d62a17ae 921 if (debug)
922 zlog_debug(
923 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
924 pfx_buf, new_buf, exist_buf,
925 aspath_hops,
926 (exist_hops + exist_confeds));
927 return 1;
928 }
929
930 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 931 *reason = bgp_path_selection_confed_as_path;
d62a17ae 932 if (debug)
933 zlog_debug(
934 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
935 pfx_buf, new_buf, exist_buf,
936 aspath_hops,
937 (exist_hops + exist_confeds));
938 return 0;
939 }
940 } else {
941 int newhops = aspath_count_hops(newattr->aspath);
942
943 if (newhops < exist_hops) {
fdf81fa0 944 *reason = bgp_path_selection_as_path;
d62a17ae 945 if (debug)
946 zlog_debug(
947 "%s: %s wins over %s due to aspath hopcount %d < %d",
948 pfx_buf, new_buf, exist_buf,
949 newhops, exist_hops);
950 return 1;
951 }
952
953 if (newhops > exist_hops) {
fdf81fa0 954 *reason = bgp_path_selection_as_path;
d62a17ae 955 if (debug)
956 zlog_debug(
957 "%s: %s loses to %s due to aspath hopcount %d > %d",
958 pfx_buf, new_buf, exist_buf,
959 newhops, exist_hops);
960 return 0;
961 }
962 }
963 }
9fbdd100 964
d62a17ae 965 /* 5. Origin check. */
966 if (newattr->origin < existattr->origin) {
fdf81fa0 967 *reason = bgp_path_selection_origin;
d62a17ae 968 if (debug)
969 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
970 pfx_buf, new_buf, exist_buf,
971 bgp_origin_long_str[newattr->origin],
972 bgp_origin_long_str[existattr->origin]);
973 return 1;
974 }
718e3744 975
d62a17ae 976 if (newattr->origin > existattr->origin) {
fdf81fa0 977 *reason = bgp_path_selection_origin;
d62a17ae 978 if (debug)
979 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
980 pfx_buf, new_buf, exist_buf,
981 bgp_origin_long_str[newattr->origin],
982 bgp_origin_long_str[existattr->origin]);
983 return 0;
984 }
718e3744 985
d62a17ae 986 /* 6. MED check. */
987 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
988 && aspath_count_hops(existattr->aspath) == 0);
989 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
990 && aspath_count_confeds(existattr->aspath) > 0
991 && aspath_count_hops(newattr->aspath) == 0
992 && aspath_count_hops(existattr->aspath) == 0);
993
892fedb6
DA
994 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
995 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 996 || aspath_cmp_left(newattr->aspath, existattr->aspath)
997 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
998 || internal_as_route) {
999 new_med = bgp_med_value(new->attr, bgp);
1000 exist_med = bgp_med_value(exist->attr, bgp);
1001
1002 if (new_med < exist_med) {
fdf81fa0 1003 *reason = bgp_path_selection_med;
d62a17ae 1004 if (debug)
1005 zlog_debug(
1006 "%s: %s wins over %s due to MED %d < %d",
1007 pfx_buf, new_buf, exist_buf, new_med,
1008 exist_med);
1009 return 1;
1010 }
8ff56318 1011
d62a17ae 1012 if (new_med > exist_med) {
fdf81fa0 1013 *reason = bgp_path_selection_med;
d62a17ae 1014 if (debug)
1015 zlog_debug(
1016 "%s: %s loses to %s due to MED %d > %d",
1017 pfx_buf, new_buf, exist_buf, new_med,
1018 exist_med);
1019 return 0;
1020 }
1021 }
9fbdd100 1022
d62a17ae 1023 /* 7. Peer type check. */
1024 new_sort = new->peer->sort;
1025 exist_sort = exist->peer->sort;
1026
1027 if (new_sort == BGP_PEER_EBGP
1028 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1029 *reason = bgp_path_selection_peer;
d62a17ae 1030 if (debug)
1031 zlog_debug(
1032 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1033 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1034 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1035 return 1;
1036 peer_sort_ret = 1;
d62a17ae 1037 }
718e3744 1038
d62a17ae 1039 if (exist_sort == BGP_PEER_EBGP
1040 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1041 *reason = bgp_path_selection_peer;
d62a17ae 1042 if (debug)
1043 zlog_debug(
1044 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1045 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1046 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1047 return 0;
1048 peer_sort_ret = 0;
d62a17ae 1049 }
8ff56318 1050
d62a17ae 1051 /* 8. IGP metric check. */
1052 newm = existm = 0;
8ff56318 1053
d62a17ae 1054 if (new->extra)
1055 newm = new->extra->igpmetric;
1056 if (exist->extra)
1057 existm = exist->extra->igpmetric;
9fbdd100 1058
d62a17ae 1059 if (newm < existm) {
ee88563a 1060 if (debug && peer_sort_ret < 0)
d62a17ae 1061 zlog_debug(
d588b995 1062 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1063 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1064 igp_metric_ret = 1;
d62a17ae 1065 }
718e3744 1066
d62a17ae 1067 if (newm > existm) {
ee88563a 1068 if (debug && peer_sort_ret < 0)
d62a17ae 1069 zlog_debug(
d588b995 1070 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1071 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1072 igp_metric_ret = 0;
5e242b0d 1073 }
5e242b0d 1074
d62a17ae 1075 /* 9. Same IGP metric. Compare the cluster list length as
1076 representative of IGP hops metric. Rewrite the metric value
1077 pair (newm, existm) with the cluster list length. Prefer the
1078 path with smaller cluster list length. */
1079 if (newm == existm) {
bf0d28dc
DS
1080 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1081 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1082 && (mpath_cfg == NULL
1083 || CHECK_FLAG(
1084 mpath_cfg->ibgp_flags,
1085 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1086 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1087 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1088
1089 if (newm < existm) {
ee88563a 1090 if (debug && peer_sort_ret < 0)
d62a17ae 1091 zlog_debug(
d588b995 1092 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1093 pfx_buf, new_buf, exist_buf,
1094 newm, existm);
ee88563a 1095 igp_metric_ret = 1;
d62a17ae 1096 }
1097
1098 if (newm > existm) {
ee88563a 1099 if (debug && peer_sort_ret < 0)
d62a17ae 1100 zlog_debug(
d588b995 1101 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1102 pfx_buf, new_buf, exist_buf,
1103 newm, existm);
ee88563a 1104 igp_metric_ret = 0;
d62a17ae 1105 }
1106 }
1107 }
31a4638f 1108
d62a17ae 1109 /* 10. confed-external vs. confed-internal */
1110 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1111 if (new_sort == BGP_PEER_CONFED
1112 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1113 *reason = bgp_path_selection_confed;
d62a17ae 1114 if (debug)
1115 zlog_debug(
1116 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1117 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1118 if (!CHECK_FLAG(bgp->flags,
1119 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1120 return 1;
1121 peer_sort_ret = 1;
d62a17ae 1122 }
718e3744 1123
d62a17ae 1124 if (exist_sort == BGP_PEER_CONFED
1125 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1126 *reason = bgp_path_selection_confed;
d62a17ae 1127 if (debug)
1128 zlog_debug(
1129 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1130 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1131 if (!CHECK_FLAG(bgp->flags,
1132 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1133 return 0;
1134 peer_sort_ret = 0;
d62a17ae 1135 }
1136 }
718e3744 1137
d62a17ae 1138 /* 11. Maximum path check. */
1139 if (newm == existm) {
1140 /* If one path has a label but the other does not, do not treat
1141 * them as equals for multipath
1142 */
a4d82a8a 1143 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1144 != (exist->extra
b57ba6d2 1145 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1146 if (debug)
1147 zlog_debug(
1148 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1149 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1150 } else if (CHECK_FLAG(bgp->flags,
1151 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1152
1153 /*
1154 * For the two paths, all comparison steps till IGP
1155 * metric
1156 * have succeeded - including AS_PATH hop count. Since
1157 * 'bgp
1158 * bestpath as-path multipath-relax' knob is on, we
1159 * don't need
1160 * an exact match of AS_PATH. Thus, mark the paths are
1161 * equal.
1162 * That will trigger both these paths to get into the
1163 * multipath
1164 * array.
1165 */
1166 *paths_eq = 1;
1167
1168 if (debug)
1169 zlog_debug(
1170 "%s: %s and %s are equal via multipath-relax",
1171 pfx_buf, new_buf, exist_buf);
1172 } else if (new->peer->sort == BGP_PEER_IBGP) {
1173 if (aspath_cmp(new->attr->aspath,
1174 exist->attr->aspath)) {
1175 *paths_eq = 1;
1176
1177 if (debug)
1178 zlog_debug(
1179 "%s: %s and %s are equal via matching aspaths",
1180 pfx_buf, new_buf, exist_buf);
1181 }
1182 } else if (new->peer->as == exist->peer->as) {
1183 *paths_eq = 1;
1184
1185 if (debug)
1186 zlog_debug(
1187 "%s: %s and %s are equal via same remote-as",
1188 pfx_buf, new_buf, exist_buf);
1189 }
1190 } else {
1191 /*
1192 * TODO: If unequal cost ibgp multipath is enabled we can
1193 * mark the paths as equal here instead of returning
1194 */
ee88563a
JM
1195
1196 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1197 * if either step 7 or 10 (peer type checks) yielded a winner,
1198 * that result was returned immediately. Returning from step 10
1199 * ignored the return value computed in steps 8 and 9 (IGP
1200 * metric checks). In order to preserve that behavior, if
1201 * peer_sort_ret is set, return that rather than igp_metric_ret.
1202 */
1203 ret = peer_sort_ret;
1204 if (peer_sort_ret < 0) {
1205 ret = igp_metric_ret;
1206 if (debug) {
1207 if (ret == 1)
1208 zlog_debug(
1209 "%s: %s wins over %s after IGP metric comparison",
1210 pfx_buf, new_buf, exist_buf);
1211 else
1212 zlog_debug(
1213 "%s: %s loses to %s after IGP metric comparison",
1214 pfx_buf, new_buf, exist_buf);
1215 }
1216 *reason = bgp_path_selection_igp_metric;
d62a17ae 1217 }
1218 return ret;
1219 }
718e3744 1220
ee88563a
JM
1221 /*
1222 * At this point, the decision whether to set *paths_eq = 1 has been
1223 * completed. If we deferred returning because of bestpath peer-type
1224 * relax configuration, return now.
1225 */
1226 if (peer_sort_ret >= 0)
1227 return peer_sort_ret;
1228
d62a17ae 1229 /* 12. If both paths are external, prefer the path that was received
1230 first (the oldest one). This step minimizes route-flap, since a
1231 newer path won't displace an older one, even if it was the
1232 preferred route based on the additional decision criteria below. */
892fedb6 1233 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1234 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1235 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1236 *reason = bgp_path_selection_older;
d62a17ae 1237 if (debug)
1238 zlog_debug(
1239 "%s: %s wins over %s due to oldest external",
1240 pfx_buf, new_buf, exist_buf);
1241 return 1;
1242 }
9fbdd100 1243
1defdda8 1244 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1245 *reason = bgp_path_selection_older;
d62a17ae 1246 if (debug)
1247 zlog_debug(
1248 "%s: %s loses to %s due to oldest external",
1249 pfx_buf, new_buf, exist_buf);
1250 return 0;
1251 }
1252 }
718e3744 1253
d62a17ae 1254 /* 13. Router-ID comparision. */
1255 /* If one of the paths is "stale", the corresponding peer router-id will
1256 * be 0 and would always win over the other path. If originator id is
1257 * used for the comparision, it will decide which path is better.
1258 */
1259 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1260 new_id.s_addr = newattr->originator_id.s_addr;
1261 else
1262 new_id.s_addr = new->peer->remote_id.s_addr;
1263 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1264 exist_id.s_addr = existattr->originator_id.s_addr;
1265 else
1266 exist_id.s_addr = exist->peer->remote_id.s_addr;
1267
1268 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1269 *reason = bgp_path_selection_router_id;
d62a17ae 1270 if (debug)
1271 zlog_debug(
1272 "%s: %s wins over %s due to Router-ID comparison",
1273 pfx_buf, new_buf, exist_buf);
1274 return 1;
1275 }
718e3744 1276
d62a17ae 1277 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1278 *reason = bgp_path_selection_router_id;
d62a17ae 1279 if (debug)
1280 zlog_debug(
1281 "%s: %s loses to %s due to Router-ID comparison",
1282 pfx_buf, new_buf, exist_buf);
1283 return 0;
1284 }
9fbdd100 1285
d62a17ae 1286 /* 14. Cluster length comparision. */
1287 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1288 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1289
1290 if (new_cluster < exist_cluster) {
fdf81fa0 1291 *reason = bgp_path_selection_cluster_length;
d62a17ae 1292 if (debug)
1293 zlog_debug(
1294 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1295 pfx_buf, new_buf, exist_buf, new_cluster,
1296 exist_cluster);
1297 return 1;
1298 }
718e3744 1299
d62a17ae 1300 if (new_cluster > exist_cluster) {
fdf81fa0 1301 *reason = bgp_path_selection_cluster_length;
d62a17ae 1302 if (debug)
1303 zlog_debug(
1304 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1305 pfx_buf, new_buf, exist_buf, new_cluster,
1306 exist_cluster);
1307 return 0;
1308 }
9fbdd100 1309
d62a17ae 1310 /* 15. Neighbor address comparision. */
1311 /* Do this only if neither path is "stale" as stale paths do not have
1312 * valid peer information (as the connection may or may not be up).
1313 */
1defdda8 1314 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1315 *reason = bgp_path_selection_stale;
d62a17ae 1316 if (debug)
1317 zlog_debug(
1318 "%s: %s wins over %s due to latter path being STALE",
1319 pfx_buf, new_buf, exist_buf);
1320 return 1;
1321 }
0de5153c 1322
1defdda8 1323 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1324 *reason = bgp_path_selection_stale;
d62a17ae 1325 if (debug)
1326 zlog_debug(
1327 "%s: %s loses to %s due to former path being STALE",
1328 pfx_buf, new_buf, exist_buf);
1329 return 0;
1330 }
718e3744 1331
d62a17ae 1332 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1333 if (new->peer->su_remote == NULL) {
1334 *reason = bgp_path_selection_local_configured;
d62a17ae 1335 return 0;
fdf81fa0
DS
1336 }
1337 if (exist->peer->su_remote == NULL) {
1338 *reason = bgp_path_selection_local_configured;
d62a17ae 1339 return 1;
fdf81fa0 1340 }
9fbdd100 1341
d62a17ae 1342 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1343
1344 if (ret == 1) {
fdf81fa0 1345 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1346 if (debug)
1347 zlog_debug(
1348 "%s: %s loses to %s due to Neighor IP comparison",
1349 pfx_buf, new_buf, exist_buf);
1350 return 0;
1351 }
1352
1353 if (ret == -1) {
fdf81fa0 1354 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1355 if (debug)
1356 zlog_debug(
1357 "%s: %s wins over %s due to Neighor IP comparison",
1358 pfx_buf, new_buf, exist_buf);
1359 return 1;
1360 }
9fbdd100 1361
fdf81fa0 1362 *reason = bgp_path_selection_default;
d62a17ae 1363 if (debug)
1364 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1365 pfx_buf, new_buf, exist_buf);
718e3744 1366
d62a17ae 1367 return 1;
718e3744 1368}
1369
d071f237
AK
1370
1371int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1372 struct bgp_path_info *exist, int *paths_eq)
1373{
1374 enum bgp_path_selection_reason reason;
1375 char pfx_buf[PREFIX2STR_BUFFER];
1376
1377 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1378 AFI_L2VPN, SAFI_EVPN, &reason);
1379}
1380
65efcfce
LB
1381/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1382 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1383 * multipath is enabled
65efcfce 1384 * This version is compatible with */
18ee8310
DS
1385int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1386 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1387 afi_t afi, safi_t safi,
1388 enum bgp_path_selection_reason *reason)
d62a17ae 1389{
1390 int paths_eq;
1391 int ret;
18ee8310 1392 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1393 afi, safi, reason);
d62a17ae 1394
1395 if (paths_eq)
1396 ret = 0;
1397 else {
1398 if (ret == 1)
1399 ret = -1;
1400 else
1401 ret = 1;
1402 }
1403 return ret;
65efcfce
LB
1404}
1405
5a1ae2c2
DS
1406static enum filter_type bgp_input_filter(struct peer *peer,
1407 const struct prefix *p,
d62a17ae 1408 struct attr *attr, afi_t afi,
1409 safi_t safi)
718e3744 1410{
d62a17ae 1411 struct bgp_filter *filter;
6401252f 1412 enum filter_type ret = FILTER_PERMIT;
718e3744 1413
d62a17ae 1414 filter = &peer->filter[afi][safi];
718e3744 1415
d62a17ae 1416#define FILTER_EXIST_WARN(F, f, filter) \
1417 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1418 zlog_debug("%s: Could not find configured input %s-list %s!", \
1419 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1420
1421 if (DISTRIBUTE_IN_NAME(filter)) {
1422 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1423
6401252f
QY
1424 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1425 == FILTER_DENY) {
1426 ret = FILTER_DENY;
1427 goto done;
1428 }
d62a17ae 1429 }
1430
1431 if (PREFIX_LIST_IN_NAME(filter)) {
1432 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1433
6401252f
QY
1434 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1435 == PREFIX_DENY) {
1436 ret = FILTER_DENY;
1437 goto done;
1438 }
d62a17ae 1439 }
1440
1441 if (FILTER_LIST_IN_NAME(filter)) {
1442 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1443
1444 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1445 == AS_FILTER_DENY) {
1446 ret = FILTER_DENY;
1447 goto done;
1448 }
d62a17ae 1449 }
1450
6401252f 1451done:
c7bb4f00 1452 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1453 char pfxprint[PREFIX2STR_BUFFER];
1454
1455 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1456 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1457 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1458 }
1459
1460 return ret;
650f76c2 1461#undef FILTER_EXIST_WARN
718e3744 1462}
1463
b8685f9b
DS
1464static enum filter_type bgp_output_filter(struct peer *peer,
1465 const struct prefix *p,
d62a17ae 1466 struct attr *attr, afi_t afi,
1467 safi_t safi)
718e3744 1468{
d62a17ae 1469 struct bgp_filter *filter;
6401252f 1470 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1471
1472 filter = &peer->filter[afi][safi];
1473
1474#define FILTER_EXIST_WARN(F, f, filter) \
1475 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1476 zlog_debug("%s: Could not find configured output %s-list %s!", \
1477 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1478
d62a17ae 1479 if (DISTRIBUTE_OUT_NAME(filter)) {
1480 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1481
6401252f
QY
1482 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1483 == FILTER_DENY) {
1484 ret = FILTER_DENY;
1485 goto done;
1486 }
d62a17ae 1487 }
1488
1489 if (PREFIX_LIST_OUT_NAME(filter)) {
1490 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1491
d62a17ae 1492 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1493 == PREFIX_DENY) {
1494 ret = FILTER_DENY;
1495 goto done;
1496 }
d62a17ae 1497 }
718e3744 1498
d62a17ae 1499 if (FILTER_LIST_OUT_NAME(filter)) {
1500 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1501
d62a17ae 1502 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1503 == AS_FILTER_DENY) {
1504 ret = FILTER_DENY;
1505 goto done;
1506 }
1507 }
1508
c7bb4f00 1509 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1510 char pfxprint[PREFIX2STR_BUFFER];
1511
1512 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1513 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1514 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1515 }
718e3744 1516
6401252f
QY
1517done:
1518 return ret;
650f76c2 1519#undef FILTER_EXIST_WARN
718e3744 1520}
1521
1522/* If community attribute includes no_export then return 1. */
3dc339cd 1523static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1524{
1525 if (attr->community) {
1526 /* NO_ADVERTISE check. */
1527 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1528 return true;
d62a17ae 1529
1530 /* NO_EXPORT check. */
1531 if (peer->sort == BGP_PEER_EBGP
1532 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1533 return true;
d62a17ae 1534
1535 /* NO_EXPORT_SUBCONFED check. */
1536 if (peer->sort == BGP_PEER_EBGP
1537 || peer->sort == BGP_PEER_CONFED)
1538 if (community_include(attr->community,
1539 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1540 return true;
d62a17ae 1541 }
3dc339cd 1542 return false;
718e3744 1543}
1544
1545/* Route reflection loop check. */
3dc339cd 1546static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1547{
d62a17ae 1548 struct in_addr cluster_id;
779fee93 1549 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1550
779fee93 1551 if (cluster) {
d62a17ae 1552 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1553 cluster_id = peer->bgp->cluster_id;
1554 else
1555 cluster_id = peer->bgp->router_id;
1556
779fee93 1557 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1558 return true;
d62a17ae 1559 }
3dc339cd 1560 return false;
718e3744 1561}
6b0655a2 1562
5a1ae2c2 1563static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1564 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1565 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1566 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1567{
d62a17ae 1568 struct bgp_filter *filter;
82b692c0
LK
1569 struct bgp_path_info rmap_path = { 0 };
1570 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1571 route_map_result_t ret;
1572 struct route_map *rmap = NULL;
718e3744 1573
d62a17ae 1574 filter = &peer->filter[afi][safi];
718e3744 1575
d62a17ae 1576 /* Apply default weight value. */
1577 if (peer->weight[afi][safi])
1578 attr->weight = peer->weight[afi][safi];
718e3744 1579
d62a17ae 1580 if (rmap_name) {
1581 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1582
d62a17ae 1583 if (rmap == NULL)
1584 return RMAP_DENY;
1585 } else {
1586 if (ROUTE_MAP_IN_NAME(filter)) {
1587 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1588
d62a17ae 1589 if (rmap == NULL)
1590 return RMAP_DENY;
1591 }
1592 }
0b16f239 1593
d62a17ae 1594 /* Route map apply. */
1595 if (rmap) {
40381db7 1596 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1597 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1598 rmap_path.peer = peer;
1599 rmap_path.attr = attr;
82b692c0 1600 rmap_path.extra = &extra;
9bcb3eef 1601 rmap_path.net = dest;
196c6b09 1602
82b692c0
LK
1603 extra.num_labels = num_labels;
1604 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1605 memcpy(extra.label, label,
1606 num_labels * sizeof(mpls_label_t));
718e3744 1607
d62a17ae 1608 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1609
d62a17ae 1610 /* Apply BGP route map to the attribute. */
1782514f 1611 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1612
d62a17ae 1613 peer->rmap_type = 0;
0b16f239 1614
1f2263be 1615 if (ret == RMAP_DENYMATCH)
d62a17ae 1616 return RMAP_DENY;
0b16f239 1617 }
d62a17ae 1618 return RMAP_PERMIT;
0b16f239
DS
1619}
1620
5f040085 1621static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1622 struct attr *attr, afi_t afi, safi_t safi,
1623 const char *rmap_name)
0b16f239 1624{
40381db7 1625 struct bgp_path_info rmap_path;
d62a17ae 1626 route_map_result_t ret;
1627 struct route_map *rmap = NULL;
d7c0a89a 1628 uint8_t rmap_type;
0b16f239 1629
b787157a
DS
1630 /*
1631 * So if we get to this point and have no rmap_name
1632 * we want to just show the output as it currently
1633 * exists.
1634 */
1635 if (!rmap_name)
1636 return RMAP_PERMIT;
0b16f239 1637
d62a17ae 1638 /* Apply default weight value. */
1639 if (peer->weight[afi][safi])
1640 attr->weight = peer->weight[afi][safi];
0b16f239 1641
b787157a 1642 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1643
b787157a
DS
1644 /*
1645 * If we have a route map name and we do not find
1646 * the routemap that means we have an implicit
1647 * deny.
1648 */
1649 if (rmap == NULL)
1650 return RMAP_DENY;
0b16f239 1651
40381db7 1652 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1653 /* Route map apply. */
b787157a 1654 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1655 rmap_path.peer = peer;
1656 rmap_path.attr = attr;
0b16f239 1657
0f672529 1658 rmap_type = peer->rmap_type;
b787157a 1659 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1660
b787157a 1661 /* Apply BGP route map to the attribute. */
1782514f 1662 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1663
0f672529 1664 peer->rmap_type = rmap_type;
b787157a
DS
1665
1666 if (ret == RMAP_DENYMATCH)
1667 /*
1668 * caller has multiple error paths with bgp_attr_flush()
1669 */
1670 return RMAP_DENY;
ac41b2a2 1671
d62a17ae 1672 return RMAP_PERMIT;
718e3744 1673}
6b0655a2 1674
5000f21c 1675/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1676static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1677 struct peer *peer, struct attr *attr)
1678{
1679 if (peer->sort == BGP_PEER_EBGP
1680 && (peer_af_flag_check(peer, afi, safi,
1681 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1682 || peer_af_flag_check(peer, afi, safi,
1683 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1684 || peer_af_flag_check(peer, afi, safi,
1685 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1686 || peer_af_flag_check(peer, afi, safi,
1687 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1688 // Take action on the entire aspath
1689 if (peer_af_flag_check(peer, afi, safi,
1690 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1691 || peer_af_flag_check(peer, afi, safi,
1692 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1693 if (peer_af_flag_check(
1694 peer, afi, safi,
1695 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1696 attr->aspath = aspath_replace_private_asns(
bf26b80e 1697 attr->aspath, bgp->as, peer->as);
d62a17ae 1698
179d5a0e
TA
1699 /*
1700 * Even if the aspath consists of just private ASNs we
1701 * need to walk the AS-Path to maintain all instances
1702 * of the peer's ASN to break possible loops.
1703 */
d62a17ae 1704 else
1705 attr->aspath = aspath_remove_private_asns(
bf26b80e 1706 attr->aspath, peer->as);
d62a17ae 1707 }
1708
1709 // 'all' was not specified so the entire aspath must be private
1710 // ASNs
1711 // for us to do anything
1712 else if (aspath_private_as_check(attr->aspath)) {
1713 if (peer_af_flag_check(
1714 peer, afi, safi,
1715 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1716 attr->aspath = aspath_replace_private_asns(
bf26b80e 1717 attr->aspath, bgp->as, peer->as);
d62a17ae 1718 else
179d5a0e
TA
1719 /*
1720 * Walk the aspath to retain any instances of
1721 * the peer_asn
1722 */
1723 attr->aspath = aspath_remove_private_asns(
1724 attr->aspath, peer->as);
d62a17ae 1725 }
1726 }
5000f21c
DS
1727}
1728
c7122e14 1729/* If this is an EBGP peer with as-override */
d62a17ae 1730static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1731 struct peer *peer, struct attr *attr)
1732{
1733 if (peer->sort == BGP_PEER_EBGP
1734 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1735 if (aspath_single_asn_check(attr->aspath, peer->as))
1736 attr->aspath = aspath_replace_specific_asn(
1737 attr->aspath, peer->as, bgp->as);
1738 }
1739}
1740
1479ed2f
DA
1741void bgp_attr_add_llgr_community(struct attr *attr)
1742{
1743 struct community *old;
1744 struct community *new;
1745 struct community *merge;
1746 struct community *llgr;
1747
1748 old = attr->community;
1749 llgr = community_str2com("llgr-stale");
1750
1751 assert(llgr);
1752
1753 if (old) {
1754 merge = community_merge(community_dup(old), llgr);
1755
1756 if (old->refcnt == 0)
1757 community_free(&old);
1758
1759 new = community_uniq_sort(merge);
1760 community_free(&merge);
1761 } else {
1762 new = community_dup(llgr);
1763 }
1764
1765 community_free(&llgr);
1766
1767 attr->community = new;
1768 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
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
1778 old = attr->community;
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);
7f323236
DW
1796 attr->community = new;
1797 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1798
1799 /* When we add the graceful-shutdown community we must also
1800 * lower the local-preference */
1801 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1802 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1803}
1804
1805
e73c112e
MK
1806/* Notify BGP Conditional advertisement scanner process. */
1807void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1808{
e73c112e 1809 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1810 afi_t afi = SUBGRP_AFI(subgrp);
1811 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1812 struct bgp_filter *filter = &peer->filter[afi][safi];
1813
1814 if (!ADVERTISE_MAP_NAME(filter))
1815 return;
1816
52979c3b
DS
1817 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1818 return;
e73c112e 1819
52979c3b 1820 peer->advmap_table_change = true;
e73c112e
MK
1821}
1822
1823
f2ee6d5c 1824void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1825{
960035b2 1826 if (family == AF_INET) {
975a328e
DA
1827 attr->nexthop.s_addr = INADDR_ANY;
1828 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1829 }
d62a17ae 1830 if (family == AF_INET6)
1831 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1832 if (family == AF_EVPN)
1833 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1834}
1835
9bcb3eef 1836bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1837 struct update_subgroup *subgrp,
7f7940e6
MK
1838 const struct prefix *p, struct attr *attr,
1839 bool skip_rmap_check)
d62a17ae 1840{
1841 struct bgp_filter *filter;
1842 struct peer *from;
1843 struct peer *peer;
1844 struct peer *onlypeer;
1845 struct bgp *bgp;
40381db7 1846 struct attr *piattr;
b68885f9 1847 route_map_result_t ret;
d62a17ae 1848 int transparent;
1849 int reflect;
1850 afi_t afi;
1851 safi_t safi;
1852 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1853 bool nh_reset = false;
1854 uint64_t cum_bw;
d62a17ae 1855
1856 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1857 return false;
d62a17ae 1858
1859 afi = SUBGRP_AFI(subgrp);
1860 safi = SUBGRP_SAFI(subgrp);
1861 peer = SUBGRP_PEER(subgrp);
1862 onlypeer = NULL;
1863 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1864 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1865
40381db7 1866 from = pi->peer;
d62a17ae 1867 filter = &peer->filter[afi][safi];
1868 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1869 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1870 : pi->attr;
3f9c7369 1871
d0bf49ec
LS
1872 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1873 peer->pmax_out[afi][safi] != 0 &&
1874 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1875 if (BGP_DEBUG(update, UPDATE_OUT) ||
1876 BGP_DEBUG(update, UPDATE_PREFIX)) {
1877 zlog_debug("%s reached maximum prefix to be send (%u)",
1878 peer->host, peer->pmax_out[afi][safi]);
1879 }
1880 return false;
1881 }
1882
49e5a4a0 1883#ifdef ENABLE_BGP_VNC
d62a17ae 1884 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1885 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1886 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1887
1888 /*
1889 * direct and direct_ext type routes originate internally even
1890 * though they can have peer pointers that reference other
1891 * systems
1892 */
8228a9a7
DS
1893 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1894 __func__, p);
d62a17ae 1895 samepeer_safe = 1;
1896 }
65efcfce
LB
1897#endif
1898
ddb5b488
PZ
1899 if (((afi == AFI_IP) || (afi == AFI_IP6))
1900 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1901 && (pi->type == ZEBRA_ROUTE_BGP)
1902 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1903
1904 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1905
1906 samepeer_safe = 1;
1907 }
1908
d62a17ae 1909 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1910 * pi is valid */
1911 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1912 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1913 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1914 return false;
d62a17ae 1915 }
adbac85e 1916
d62a17ae 1917 /* If this is not the bestpath then check to see if there is an enabled
1918 * addpath
1919 * feature that requires us to advertise it */
40381db7 1920 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1921 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1922 return false;
d62a17ae 1923 }
1924 }
06370dac 1925
d62a17ae 1926 /* Aggregate-address suppress check. */
4056a5f6
RZ
1927 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1928 return false;
3f9c7369 1929
13b7e7f0
DS
1930 /*
1931 * If we are doing VRF 2 VRF leaking via the import
1932 * statement, we want to prevent the route going
1933 * off box as that the RT and RD created are localy
1934 * significant and globaly useless.
1935 */
40381db7
DS
1936 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1937 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1938 return false;
13b7e7f0 1939
d62a17ae 1940 /* If it's labeled safi, make sure the route has a valid label. */
1941 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1942 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1943 if (!bgp_is_valid_label(&label)) {
1944 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1945 zlog_debug("u%" PRIu64 ":s%" PRIu64
1946 " %pFX is filtered - no label (%p)",
d62a17ae 1947 subgrp->update_group->id, subgrp->id,
8228a9a7 1948 p, &label);
3dc339cd 1949 return false;
d62a17ae 1950 }
1951 }
cd1964ff 1952
d62a17ae 1953 /* Do not send back route to sender. */
1954 if (onlypeer && from == onlypeer) {
3dc339cd 1955 return false;
d62a17ae 1956 }
3f9c7369 1957
d62a17ae 1958 /* Do not send the default route in the BGP table if the neighbor is
1959 * configured for default-originate */
1960 if (CHECK_FLAG(peer->af_flags[afi][safi],
1961 PEER_FLAG_DEFAULT_ORIGINATE)) {
1962 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1963 return false;
d62a17ae 1964 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1965 return false;
d62a17ae 1966 }
4125bb67 1967
d62a17ae 1968 /* Transparency check. */
1969 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1970 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1971 transparent = 1;
1972 else
1973 transparent = 0;
1974
1975 /* If community is not disabled check the no-export and local. */
40381db7 1976 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1977 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1978 zlog_debug("%s: community filter check fail for %pFX",
1979 __func__, p);
3dc339cd 1980 return false;
d62a17ae 1981 }
3f9c7369 1982
d62a17ae 1983 /* If the attribute has originator-id and it is same as remote
1984 peer's id. */
40381db7
DS
1985 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1986 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1987 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1988 zlog_debug(
8228a9a7
DS
1989 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1990 onlypeer->host, p);
3dc339cd 1991 return false;
d62a17ae 1992 }
3f9c7369 1993
d62a17ae 1994 /* ORF prefix-list filter check */
1995 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1996 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1997 || CHECK_FLAG(peer->af_cap[afi][safi],
1998 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1999 if (peer->orf_plist[afi][safi]) {
2000 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2001 == PREFIX_DENY) {
2002 if (bgp_debug_update(NULL, p,
2003 subgrp->update_group, 0))
2004 zlog_debug(
8228a9a7
DS
2005 "%s [Update:SEND] %pFX is filtered via ORF",
2006 peer->host, p);
3dc339cd 2007 return false;
d62a17ae 2008 }
2009 }
2010
2011 /* Output filter check. */
40381db7 2012 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2013 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2014 zlog_debug("%s [Update:SEND] %pFX is filtered",
2015 peer->host, p);
3dc339cd 2016 return false;
d62a17ae 2017 }
3f9c7369 2018
d62a17ae 2019 /* AS path loop check. */
2b31007c
RZ
2020 if (onlypeer && onlypeer->as_path_loop_detection
2021 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2022 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2023 zlog_debug(
3efd0893 2024 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 2025 onlypeer->host, onlypeer->as);
3dc339cd 2026 return false;
d62a17ae 2027 }
3f9c7369 2028
d62a17ae 2029 /* If we're a CONFED we need to loop check the CONFED ID too */
2030 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2031 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2032 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2033 zlog_debug(
3efd0893 2034 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 2035 peer->host, bgp->confed_id);
3dc339cd 2036 return false;
d62a17ae 2037 }
3f9c7369 2038 }
3f9c7369 2039
d62a17ae 2040 /* Route-Reflect check. */
2041 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2042 reflect = 1;
2043 else
2044 reflect = 0;
2045
2046 /* IBGP reflection check. */
2047 if (reflect && !samepeer_safe) {
2048 /* A route from a Client peer. */
2049 if (CHECK_FLAG(from->af_flags[afi][safi],
2050 PEER_FLAG_REFLECTOR_CLIENT)) {
2051 /* Reflect to all the Non-Client peers and also to the
2052 Client peers other than the originator. Originator
2053 check
2054 is already done. So there is noting to do. */
2055 /* no bgp client-to-client reflection check. */
892fedb6
DA
2056 if (CHECK_FLAG(bgp->flags,
2057 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2058 if (CHECK_FLAG(peer->af_flags[afi][safi],
2059 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2060 return false;
d62a17ae 2061 } else {
2062 /* A route from a Non-client peer. Reflect to all other
2063 clients. */
2064 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2065 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2066 return false;
d62a17ae 2067 }
2068 }
3f9c7369 2069
d62a17ae 2070 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 2071 *attr = *piattr;
d62a17ae 2072
2073 /* If local-preference is not set. */
2074 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2075 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2076 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2077 attr->local_pref = bgp->default_local_pref;
3f9c7369 2078 }
3f9c7369 2079
d62a17ae 2080 /* If originator-id is not set and the route is to be reflected,
2081 set the originator id */
2082 if (reflect
2083 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2084 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2085 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2086 }
3f9c7369 2087
d62a17ae 2088 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2089 */
2090 if (peer->sort == BGP_PEER_EBGP
2091 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2092 if (from != bgp->peer_self && !transparent
2093 && !CHECK_FLAG(peer->af_flags[afi][safi],
2094 PEER_FLAG_MED_UNCHANGED))
2095 attr->flag &=
2096 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2097 }
3f9c7369 2098
d62a17ae 2099 /* Since the nexthop attribute can vary per peer, it is not explicitly
2100 * set
2101 * in announce check, only certain flags and length (or number of
2102 * nexthops
2103 * -- for IPv6/MP_REACH) are set here in order to guide the update
2104 * formation
2105 * code in setting the nexthop(s) on a per peer basis in
2106 * reformat_peer().
2107 * Typically, the source nexthop in the attribute is preserved but in
2108 * the
2109 * scenarios where we know it will always be overwritten, we reset the
2110 * nexthop to "0" in an attempt to achieve better Update packing. An
2111 * example of this is when a prefix from each of 2 IBGP peers needs to
2112 * be
2113 * announced to an EBGP peer (and they have the same attributes barring
2114 * their nexthop).
2115 */
2116 if (reflect)
2117 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2118
2119#define NEXTHOP_IS_V6 \
2120 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2121 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2122 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2123 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2124
2125 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2126 * if
2127 * the peer (group) is configured to receive link-local nexthop
2128 * unchanged
c728d027
DA
2129 * and it is available in the prefix OR we're not reflecting the route,
2130 * link-local nexthop address is valid and
d62a17ae 2131 * the peer (group) to whom we're going to announce is on a shared
2132 * network
2133 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2134 * By checking if nexthop LL address is valid we are sure that
2135 * we do not announce LL address as `::`.
d62a17ae 2136 */
2137 if (NEXTHOP_IS_V6) {
2138 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2139 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2140 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2141 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2142 || (!reflect && !transparent
c728d027
DA
2143 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2144 && peer->shared_network
d62a17ae 2145 && (from == bgp->peer_self
2146 || peer->sort == BGP_PEER_EBGP))) {
2147 attr->mp_nexthop_len =
2148 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2149 }
3f9c7369 2150
d62a17ae 2151 /* Clear off link-local nexthop in source, whenever it is not
2152 * needed to
2153 * ensure more prefixes share the same attribute for
2154 * announcement.
2155 */
2156 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2157 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2158 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2159 }
3f9c7369 2160
d62a17ae 2161 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2162 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2163
2164 /* Route map & unsuppress-map apply. */
7f7940e6 2165 if (!skip_rmap_check
e73c112e 2166 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2167 struct bgp_path_info rmap_path = {0};
2168 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2169 struct attr dummy_attr = {0};
d62a17ae 2170
e34291b8 2171 /* Fill temp path_info */
9bcb3eef
DS
2172 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2173 pi, peer, attr);
16f7ce2b 2174
d62a17ae 2175 /* don't confuse inbound and outbound setting */
2176 RESET_FLAG(attr->rmap_change_flags);
2177
2178 /*
2179 * The route reflector is not allowed to modify the attributes
2180 * of the reflected IBGP routes unless explicitly allowed.
2181 */
2182 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2183 && !CHECK_FLAG(bgp->flags,
2184 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2185 dummy_attr = *attr;
40381db7 2186 rmap_path.attr = &dummy_attr;
d62a17ae 2187 }
3f9c7369 2188
d62a17ae 2189 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2190
4056a5f6 2191 if (bgp_path_suppressed(pi))
d62a17ae 2192 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2193 &rmap_path);
d62a17ae 2194 else
2195 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2196 &rmap_path);
d62a17ae 2197
2198 peer->rmap_type = 0;
2199
2200 if (ret == RMAP_DENYMATCH) {
778048bf 2201 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2202 zlog_debug(
02494580
DA
2203 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2204 peer->host, p,
2205 ROUTE_MAP_OUT_NAME(filter));
778048bf 2206
686826e9 2207 bgp_attr_flush(&dummy_attr);
3dc339cd 2208 return false;
d62a17ae 2209 }
3f9c7369 2210 }
3f9c7369 2211
9dac9fc8
DA
2212 /* RFC 8212 to prevent route leaks.
2213 * This specification intends to improve this situation by requiring the
2214 * explicit configuration of both BGP Import and Export Policies for any
2215 * External BGP (EBGP) session such as customers, peers, or
2216 * confederation boundaries for all enabled address families. Through
2217 * codification of the aforementioned requirement, operators will
2218 * benefit from consistent behavior across different BGP
2219 * implementations.
2220 */
1d3fdccf 2221 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2222 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2223 return false;
9dac9fc8 2224
fb29348a
DA
2225 /* draft-ietf-idr-deprecate-as-set-confed-set
2226 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2227 * Eventually, This document (if approved) updates RFC 4271
2228 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2229 * and obsoletes RFC 6472.
2230 */
7f972cd8 2231 if (peer->bgp->reject_as_sets)
fb29348a 2232 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2233 return false;
fb29348a 2234
33d022bc
DA
2235 /* Codification of AS 0 Processing */
2236 if (aspath_check_as_zero(attr->aspath))
e2369003 2237 return false;
33d022bc 2238
637e5ba4 2239 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2240 if (peer->sort == BGP_PEER_IBGP
2241 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2242 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2243 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2244 } else {
2245 bgp_attr_add_gshut_community(attr);
2246 }
2247 }
2248
1479ed2f
DA
2249 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2250 * Capability" to a neighbor MUST perform the following upon receiving
2251 * a route from that neighbor with the "LLGR_STALE" community, or upon
2252 * attaching the "LLGR_STALE" community itself per Section 4.2:
2253 *
2254 * The route SHOULD NOT be advertised to any neighbor from which the
2255 * Long-lived Graceful Restart Capability has not been received.
2256 */
2257 if (attr->community &&
2258 community_include(attr->community, COMMUNITY_LLGR_STALE) &&
2259 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2260 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2261 return false;
2262
d62a17ae 2263 /* After route-map has been applied, we check to see if the nexthop to
2264 * be carried in the attribute (that is used for the announcement) can
2265 * be cleared off or not. We do this in all cases where we would be
2266 * setting the nexthop to "ourselves". For IPv6, we only need to
2267 * consider
2268 * the global nexthop here; the link-local nexthop would have been
2269 * cleared
2270 * already, and if not, it is required by the update formation code.
2271 * Also see earlier comments in this function.
2272 */
2273 /*
2274 * If route-map has performed some operation on the nexthop or the peer
2275 * configuration says to pass it unchanged, we cannot reset the nexthop
2276 * here, so only attempt to do it if these aren't true. Note that the
2277 * route-map handler itself might have cleared the nexthop, if for
2278 * example,
2279 * it is configured as 'peer-address'.
2280 */
2281 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2282 piattr->rmap_change_flags)
d62a17ae 2283 && !transparent
2284 && !CHECK_FLAG(peer->af_flags[afi][safi],
2285 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2286 /* We can reset the nexthop, if setting (or forcing) it to
2287 * 'self' */
2288 if (CHECK_FLAG(peer->af_flags[afi][safi],
2289 PEER_FLAG_NEXTHOP_SELF)
2290 || CHECK_FLAG(peer->af_flags[afi][safi],
2291 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2292 if (!reflect
2293 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2294 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2295 subgroup_announce_reset_nhop(
2296 (peer_cap_enhe(peer, afi, safi)
2297 ? AF_INET6
2298 : p->family),
2299 attr);
7b651a32 2300 nh_reset = true;
2301 }
d62a17ae 2302 } else if (peer->sort == BGP_PEER_EBGP) {
2303 /* Can also reset the nexthop if announcing to EBGP, but
2304 * only if
2305 * no peer in the subgroup is on a shared subnet.
2306 * Note: 3rd party nexthop currently implemented for
2307 * IPv4 only.
2308 */
737af885
BS
2309 if ((p->family == AF_INET) &&
2310 (!bgp_subgrp_multiaccess_check_v4(
2311 piattr->nexthop,
7b651a32 2312 subgrp, from))) {
d62a17ae 2313 subgroup_announce_reset_nhop(
2314 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2315 ? AF_INET6
2316 : p->family),
737af885 2317 attr);
7b651a32 2318 nh_reset = true;
2319 }
737af885
BS
2320
2321 if ((p->family == AF_INET6) &&
2322 (!bgp_subgrp_multiaccess_check_v6(
2323 piattr->mp_nexthop_global,
7b651a32 2324 subgrp, from))) {
737af885
BS
2325 subgroup_announce_reset_nhop(
2326 (peer_cap_enhe(peer, afi, safi)
2327 ? AF_INET6
2328 : p->family),
2329 attr);
7b651a32 2330 nh_reset = true;
2331 }
737af885
BS
2332
2333
2334
40381db7 2335 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2336 /*
2337 * This flag is used for leaked vpn-vrf routes
2338 */
2339 int family = p->family;
2340
2341 if (peer_cap_enhe(peer, afi, safi))
2342 family = AF_INET6;
2343
2344 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2345 zlog_debug(
1defdda8 2346 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2347 __func__, family2str(family));
2348 subgroup_announce_reset_nhop(family, attr);
7b651a32 2349 nh_reset = true;
d62a17ae 2350 }
63696f1d 2351 }
960035b2 2352
63696f1d 2353 /* If IPv6/MP and nexthop does not have any override and happens
2354 * to
2355 * be a link-local address, reset it so that we don't pass along
2356 * the
2357 * source's link-local IPv6 address to recipients who may not be
2358 * on
2359 * the same interface.
2360 */
2361 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2362 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2363 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2364 nh_reset = true;
2365 }
d62a17ae 2366 }
3f9c7369 2367
7b651a32 2368 /*
2369 * When the next hop is set to ourselves, if all multipaths have
2370 * link-bandwidth announce the cumulative bandwidth as that makes
2371 * the most sense. However, don't modify if the link-bandwidth has
2372 * been explicitly set by user policy.
2373 */
2374 if (nh_reset &&
f7e1c681 2375 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2376 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2377 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2378 bgp_attr_set_ecommunity(
2379 attr,
2380 ecommunity_replace_linkbw(
2381 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2382 CHECK_FLAG(
2383 peer->flags,
2384 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2385
3dc339cd 2386 return true;
3f9c7369
DS
2387}
2388
f009ff26 2389static int bgp_route_select_timer_expire(struct thread *thread)
2390{
2391 struct afi_safi_info *info;
2392 afi_t afi;
2393 safi_t safi;
2394 struct bgp *bgp;
2395
2396 info = THREAD_ARG(thread);
2397 afi = info->afi;
2398 safi = info->safi;
2399 bgp = info->bgp;
2400
2401 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2402 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2403 safi);
f009ff26 2404
2405 bgp->gr_info[afi][safi].t_route_select = NULL;
2406
2407 XFREE(MTYPE_TMP, info);
2408
2409 /* Best path selection */
2410 return bgp_best_path_select_defer(bgp, afi, safi);
2411}
2412
9bcb3eef 2413void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2414 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2415 struct bgp_path_info_pair *result, afi_t afi,
2416 safi_t safi)
2417{
2418 struct bgp_path_info *new_select;
2419 struct bgp_path_info *old_select;
40381db7
DS
2420 struct bgp_path_info *pi;
2421 struct bgp_path_info *pi1;
2422 struct bgp_path_info *pi2;
2423 struct bgp_path_info *nextpi = NULL;
d62a17ae 2424 int paths_eq, do_mpath, debug;
2425 struct list mp_list;
2426 char pfx_buf[PREFIX2STR_BUFFER];
2427 char path_buf[PATH_ADDPATH_STR_BUFFER];
2428
2429 bgp_mp_list_init(&mp_list);
2430 do_mpath =
2431 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2432
9bcb3eef 2433 debug = bgp_debug_bestpath(dest);
d62a17ae 2434
2435 if (debug)
9bcb3eef 2436 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2437
9bcb3eef 2438 dest->reason = bgp_path_selection_none;
d62a17ae 2439 /* bgp deterministic-med */
2440 new_select = NULL;
892fedb6 2441 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2442
1defdda8 2443 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2444 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2445 pi1 = pi1->next)
9bcb3eef 2446 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2447 BGP_PATH_DMED_SELECTED);
d62a17ae 2448
9bcb3eef 2449 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2450 pi1 = pi1->next) {
40381db7 2451 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2452 continue;
40381db7 2453 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2454 continue;
ea8b2282 2455 if (pi1->peer != bgp->peer_self)
feb17238 2456 if (!peer_established(pi1->peer))
d62a17ae 2457 continue;
2458
40381db7
DS
2459 new_select = pi1;
2460 if (pi1->next) {
2461 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2462 if (CHECK_FLAG(pi2->flags,
1defdda8 2463 BGP_PATH_DMED_CHECK))
d62a17ae 2464 continue;
40381db7 2465 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2466 continue;
ea8b2282 2467 if (pi2->peer != bgp->peer_self
d62a17ae 2468 && !CHECK_FLAG(
ea8b2282
DS
2469 pi2->peer->sflags,
2470 PEER_STATUS_NSF_WAIT))
40381db7 2471 if (pi2->peer->status
d62a17ae 2472 != Established)
2473 continue;
2474
121e245d
DS
2475 if (!aspath_cmp_left(pi1->attr->aspath,
2476 pi2->attr->aspath)
2477 && !aspath_cmp_left_confed(
40381db7 2478 pi1->attr->aspath,
121e245d
DS
2479 pi2->attr->aspath))
2480 continue;
d62a17ae 2481
121e245d
DS
2482 if (bgp_path_info_cmp(
2483 bgp, pi2, new_select,
2484 &paths_eq, mpath_cfg, debug,
fdf81fa0 2485 pfx_buf, afi, safi,
9bcb3eef 2486 &dest->reason)) {
121e245d 2487 bgp_path_info_unset_flag(
9bcb3eef 2488 dest, new_select,
121e245d
DS
2489 BGP_PATH_DMED_SELECTED);
2490 new_select = pi2;
d62a17ae 2491 }
121e245d
DS
2492
2493 bgp_path_info_set_flag(
9bcb3eef 2494 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2495 }
2496 }
9bcb3eef 2497 bgp_path_info_set_flag(dest, new_select,
18ee8310 2498 BGP_PATH_DMED_CHECK);
9bcb3eef 2499 bgp_path_info_set_flag(dest, new_select,
18ee8310 2500 BGP_PATH_DMED_SELECTED);
d62a17ae 2501
2502 if (debug) {
18ee8310 2503 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2504 new_select, path_buf, sizeof(path_buf));
8228a9a7 2505 zlog_debug(
4378495a
DS
2506 "%pBD(%s): %s is the bestpath from AS %u",
2507 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2508 aspath_get_first_as(
2509 new_select->attr->aspath));
d62a17ae 2510 }
2511 }
2512 }
96450faf 2513
d62a17ae 2514 /* Check old selected route and new selected route. */
2515 old_select = NULL;
2516 new_select = NULL;
9bcb3eef 2517 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2518 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2519 enum bgp_path_selection_reason reason;
2520
40381db7
DS
2521 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2522 old_select = pi;
d62a17ae 2523
40381db7 2524 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2525 /* reap REMOVED routes, if needs be
2526 * selected route must stay for a while longer though
2527 */
40381db7
DS
2528 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2529 && (pi != old_select))
9bcb3eef 2530 bgp_path_info_reap(dest, pi);
d62a17ae 2531
ddb5b488 2532 if (debug)
40381db7
DS
2533 zlog_debug("%s: pi %p in holddown", __func__,
2534 pi);
ddb5b488 2535
d62a17ae 2536 continue;
2537 }
96450faf 2538
40381db7
DS
2539 if (pi->peer && pi->peer != bgp->peer_self
2540 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2541 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2542
2543 if (debug)
2544 zlog_debug(
40381db7
DS
2545 "%s: pi %p non self peer %s not estab state",
2546 __func__, pi, pi->peer->host);
ddb5b488 2547
d62a17ae 2548 continue;
ddb5b488 2549 }
9fbdd100 2550
892fedb6 2551 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2552 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2553 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2554 if (debug)
40381db7 2555 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2556 continue;
2557 }
9fbdd100 2558
9bcb3eef 2559 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2560
9bcb3eef 2561 reason = dest->reason;
40381db7 2562 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2563 debug, pfx_buf, afi, safi,
2564 &dest->reason)) {
19ea4cec
DS
2565 if (new_select == NULL &&
2566 reason != bgp_path_selection_none)
9bcb3eef 2567 dest->reason = reason;
40381db7 2568 new_select = pi;
d62a17ae 2569 }
2570 }
718e3744 2571
d62a17ae 2572 /* Now that we know which path is the bestpath see if any of the other
2573 * paths
2574 * qualify as multipaths
2575 */
2576 if (debug) {
2577 if (new_select)
7533cad7
QY
2578 bgp_path_info_path_with_addpath_rx_str(
2579 new_select, path_buf, sizeof(path_buf));
d62a17ae 2580 else
772270f3 2581 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2582 zlog_debug(
4378495a
DS
2583 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2584 dest, bgp->name_pretty, path_buf,
d62a17ae 2585 old_select ? old_select->peer->host : "NONE");
96450faf 2586 }
9fbdd100 2587
d62a17ae 2588 if (do_mpath && new_select) {
9bcb3eef 2589 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2590 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2591
2592 if (debug)
18ee8310 2593 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2594 pi, path_buf, sizeof(path_buf));
d62a17ae 2595
40381db7 2596 if (pi == new_select) {
d62a17ae 2597 if (debug)
2598 zlog_debug(
4378495a
DS
2599 "%pBD(%s): %s is the bestpath, add to the multipath list",
2600 dest, bgp->name_pretty,
2601 path_buf);
40381db7 2602 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2603 continue;
2604 }
2605
40381db7 2606 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2607 continue;
2608
40381db7
DS
2609 if (pi->peer && pi->peer != bgp->peer_self
2610 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2611 PEER_STATUS_NSF_WAIT))
feb17238 2612 if (!peer_established(pi->peer))
d62a17ae 2613 continue;
2614
40381db7 2615 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2616 if (debug)
2617 zlog_debug(
8228a9a7
DS
2618 "%pBD: %s has the same nexthop as the bestpath, skip it",
2619 dest, path_buf);
d62a17ae 2620 continue;
2621 }
2622
40381db7 2623 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2624 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2625 &dest->reason);
d62a17ae 2626
2627 if (paths_eq) {
2628 if (debug)
2629 zlog_debug(
8228a9a7
DS
2630 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2631 dest, path_buf);
40381db7 2632 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2633 }
2634 }
2635 }
fee0f4c6 2636
4378495a 2637 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2638 mpath_cfg);
2639 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2640 bgp_mp_list_clear(&mp_list);
96450faf 2641
9bcb3eef 2642 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2643
d62a17ae 2644 result->old = old_select;
2645 result->new = new_select;
96450faf 2646
d62a17ae 2647 return;
fee0f4c6 2648}
2649
3f9c7369
DS
2650/*
2651 * A new route/change in bestpath of an existing route. Evaluate the path
2652 * for advertisement to the subgroup.
2653 */
3dc339cd
DA
2654void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2655 struct bgp_path_info *selected,
9bcb3eef 2656 struct bgp_dest *dest,
3dc339cd 2657 uint32_t addpath_tx_id)
d62a17ae 2658{
b54892e0 2659 const struct prefix *p;
d62a17ae 2660 struct peer *onlypeer;
2661 struct attr attr;
2662 afi_t afi;
2663 safi_t safi;
a77e2f4b
S
2664 struct bgp *bgp;
2665 bool advertise;
adbac85e 2666
9bcb3eef 2667 p = bgp_dest_get_prefix(dest);
d62a17ae 2668 afi = SUBGRP_AFI(subgrp);
2669 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2670 bgp = SUBGRP_INST(subgrp);
d62a17ae 2671 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2672 : NULL);
2673
2dbe669b
DA
2674 if (BGP_DEBUG(update, UPDATE_OUT))
2675 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2676
d62a17ae 2677 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2678 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2679 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2680 return;
d62a17ae 2681
2682 memset(&attr, 0, sizeof(struct attr));
2683 /* It's initialized in bgp_announce_check() */
2684
a77e2f4b
S
2685 /* Announcement to the subgroup. If the route is filtered withdraw it.
2686 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2687 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2688 * route
d62a17ae 2689 */
a77e2f4b
S
2690 advertise = bgp_check_advertise(bgp, dest);
2691
d62a17ae 2692 if (selected) {
7f7940e6 2693 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2694 false)) {
2695 /* Route is selected, if the route is already installed
2696 * in FIB, then it is advertised
2697 */
be785e35
DS
2698 if (advertise) {
2699 if (!bgp_check_withdrawal(bgp, dest))
2700 bgp_adj_out_set_subgroup(
2701 dest, subgrp, &attr, selected);
2702 else
2703 bgp_adj_out_unset_subgroup(
2704 dest, subgrp, 1, addpath_tx_id);
2705 }
a77e2f4b 2706 } else
9bcb3eef 2707 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2708 addpath_tx_id);
d62a17ae 2709 }
2710
2711 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2712 else {
9bcb3eef 2713 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2714 }
200df115 2715}
fee0f4c6 2716
3064bf43 2717/*
e1072051 2718 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2719 * This is called at the end of route processing.
3064bf43 2720 */
9bcb3eef 2721void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2722{
40381db7 2723 struct bgp_path_info *pi;
3064bf43 2724
9bcb3eef 2725 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2726 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2727 continue;
40381db7
DS
2728 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2729 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2730 }
3064bf43 2731}
2732
2733/*
2734 * Has the route changed from the RIB's perspective? This is invoked only
2735 * if the route selection returns the same best route as earlier - to
2736 * determine if we need to update zebra or not.
2737 */
9bcb3eef 2738bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2739{
4b7e6066 2740 struct bgp_path_info *mpinfo;
d62a17ae 2741
2bb9eff4
DS
2742 /* If this is multipath, check all selected paths for any nexthop
2743 * change or attribute change. Some attribute changes (e.g., community)
2744 * aren't of relevance to the RIB, but we'll update zebra to ensure
2745 * we handle the case of BGP nexthop change. This is the behavior
2746 * when the best path has an attribute change anyway.
d62a17ae 2747 */
1defdda8 2748 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2749 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2750 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2751 return true;
d62a17ae 2752
2bb9eff4
DS
2753 /*
2754 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2755 */
18ee8310
DS
2756 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2757 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2758 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2759 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2760 return true;
d62a17ae 2761 }
3064bf43 2762
d62a17ae 2763 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2764 return false;
3064bf43 2765}
2766
d62a17ae 2767struct bgp_process_queue {
2768 struct bgp *bgp;
9bcb3eef 2769 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2770#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2771 unsigned int flags;
2772 unsigned int queued;
200df115 2773};
2774
3b0c17e1 2775static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2776 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2777 struct bgp_path_info *new_select,
2778 struct bgp_path_info *old_select)
2779{
9bcb3eef 2780 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2781
2782 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2783 return;
2784
2785 if (advertise_type5_routes(bgp, afi) && new_select
2786 && is_route_injectable_into_evpn(new_select)) {
2787
2788 /* apply the route-map */
2789 if (bgp->adv_cmd_rmap[afi][safi].map) {
2790 route_map_result_t ret;
2791 struct bgp_path_info rmap_path;
2792 struct bgp_path_info_extra rmap_path_extra;
2793 struct attr dummy_attr;
2794
2795 dummy_attr = *new_select->attr;
2796
2797 /* Fill temp path_info */
9bcb3eef 2798 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2799 new_select, new_select->peer,
2800 &dummy_attr);
2801
2802 RESET_FLAG(dummy_attr.rmap_change_flags);
2803
2804 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2805 p, &rmap_path);
3b0c17e1 2806
2807 if (ret == RMAP_DENYMATCH) {
2808 bgp_attr_flush(&dummy_attr);
2809 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2810 safi);
2811 } else
2812 bgp_evpn_advertise_type5_route(
2813 bgp, p, &dummy_attr, afi, safi);
2814 } else {
2815 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2816 afi, safi);
2817 }
2818 } else if (advertise_type5_routes(bgp, afi) && old_select
2819 && is_route_injectable_into_evpn(old_select))
2820 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2821}
2822
bb2ca692
MS
2823/*
2824 * Utility to determine whether a particular path_info should use
2825 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2826 * in a path where we basically _know_ this is a BGP-LU route.
2827 */
2828static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2829{
2830 /* Certain types get imp null; so do paths where the nexthop is
2831 * not labeled.
2832 */
2833 if (new_select->sub_type == BGP_ROUTE_STATIC
2834 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2835 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2836 return true;
2837 else if (new_select->extra == NULL ||
2838 !bgp_is_valid_label(&new_select->extra->label[0]))
2839 /* TODO -- should be configurable? */
2840 return true;
2841 else
2842 return false;
2843}
2844
3103e8d2
DS
2845/*
2846 * old_select = The old best path
2847 * new_select = the new best path
2848 *
2849 * if (!old_select && new_select)
2850 * We are sending new information on.
2851 *
2852 * if (old_select && new_select) {
2853 * if (new_select != old_select)
2854 * We have a new best path send a change
2855 * else
2856 * We've received a update with new attributes that needs
2857 * to be passed on.
2858 * }
2859 *
2860 * if (old_select && !new_select)
2861 * We have no eligible route that we can announce or the rn
2862 * is being removed.
2863 */
9bcb3eef 2864static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2865 afi_t afi, safi_t safi)
d62a17ae 2866{
4b7e6066
DS
2867 struct bgp_path_info *new_select;
2868 struct bgp_path_info *old_select;
2869 struct bgp_path_info_pair old_and_new;
ddb5b488 2870 int debug = 0;
d62a17ae 2871
892fedb6 2872 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2873 if (dest)
2874 debug = bgp_debug_bestpath(dest);
b54892e0 2875 if (debug)
f4c713ae 2876 zlog_debug(
56ca3b5b 2877 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2878 __func__, dest);
f4c713ae
LB
2879 return;
2880 }
d62a17ae 2881 /* Is it end of initial update? (after startup) */
9bcb3eef 2882 if (!dest) {
e36f61b5
DS
2883 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2884 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2885
2886 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2887 FOREACH_AFI_SAFI (afi, safi) {
2888 if (bgp_fibupd_safi(safi))
2889 bgp_zebra_announce_table(bgp, afi, safi);
2890 }
d62a17ae 2891 bgp->main_peers_update_hold = 0;
2892
2893 bgp_start_routeadv(bgp);
aac24838 2894 return;
d62a17ae 2895 }
cb1faec9 2896
9bcb3eef 2897 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2898
9bcb3eef 2899 debug = bgp_debug_bestpath(dest);
b54892e0 2900 if (debug)
4378495a
DS
2901 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2902 dest, bgp->name_pretty, afi2str(afi),
2903 safi2str(safi));
ddb5b488 2904
f009ff26 2905 /* The best path calculation for the route is deferred if
2906 * BGP_NODE_SELECT_DEFER is set
2907 */
9bcb3eef 2908 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2909 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2910 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2911 return;
2912 }
2913
d62a17ae 2914 /* Best path selection. */
9bcb3eef 2915 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2916 afi, safi);
2917 old_select = old_and_new.old;
2918 new_select = old_and_new.new;
2919
2920 /* Do we need to allocate or free labels?
2921 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2922 * necessary to do this upon changes to best path. Exceptions:
2923 * - label index has changed -> recalculate resulting label
2924 * - path_info sub_type changed -> switch to/from implicit-null
2925 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2926 */
318cac96 2927 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2928 if (new_select) {
2929 if (!old_select
2930 || bgp_label_index_differs(new_select, old_select)
57592a53 2931 || new_select->sub_type != old_select->sub_type
9bcb3eef 2932 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2933 /* Enforced penultimate hop popping:
2934 * implicit-null for local routes, aggregate
2935 * and redistributed routes
2936 */
bb2ca692 2937 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 2938 if (CHECK_FLAG(
9bcb3eef 2939 dest->flags,
992dd67e
PR
2940 BGP_NODE_REGISTERED_FOR_LABEL)
2941 || CHECK_FLAG(
2942 dest->flags,
2943 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2944 bgp_unregister_for_label(dest);
70e98a7f 2945 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2946 &dest->local_label);
2947 bgp_set_valid_label(&dest->local_label);
d62a17ae 2948 } else
9bcb3eef
DS
2949 bgp_register_for_label(dest,
2950 new_select);
d62a17ae 2951 }
9bcb3eef 2952 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2953 BGP_NODE_REGISTERED_FOR_LABEL)
2954 || CHECK_FLAG(dest->flags,
2955 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2956 bgp_unregister_for_label(dest);
318cac96 2957 }
992dd67e
PR
2958 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2959 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2960 bgp_unregister_for_label(dest);
d62a17ae 2961 }
cd1964ff 2962
b54892e0 2963 if (debug)
ddb5b488 2964 zlog_debug(
4378495a
DS
2965 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2966 __func__, dest, bgp->name_pretty, afi2str(afi),
2967 safi2str(safi), old_select, new_select);
ddb5b488 2968
d62a17ae 2969 /* If best route remains the same and this is not due to user-initiated
2970 * clear, see exactly what needs to be done.
2971 */
d62a17ae 2972 if (old_select && old_select == new_select
9bcb3eef 2973 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2974 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2975 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2976 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2977#ifdef ENABLE_BGP_VNC
d62a17ae 2978 vnc_import_bgp_add_route(bgp, p, old_select);
2979 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2980#endif
bb744275 2981 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2982 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2983
be785e35
DS
2984 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
2985 && new_select->sub_type == BGP_ROUTE_NORMAL)
2986 SET_FLAG(dest->flags,
2987 BGP_NODE_FIB_INSTALL_PENDING);
2988
ddb5b488
PZ
2989 if (new_select->type == ZEBRA_ROUTE_BGP
2990 && (new_select->sub_type == BGP_ROUTE_NORMAL
2991 || new_select->sub_type
2992 == BGP_ROUTE_IMPORTED))
2993
9bcb3eef 2994 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2995 bgp, afi, safi);
2996 }
d62a17ae 2997 }
d62a17ae 2998
2999 /* If there is a change of interest to peers, reannounce the
3000 * route. */
1defdda8 3001 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3002 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3003 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3004 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3005
3006 /* unicast routes must also be annouced to
3007 * labeled-unicast update-groups */
3008 if (safi == SAFI_UNICAST)
3009 group_announce_route(bgp, afi,
9bcb3eef 3010 SAFI_LABELED_UNICAST, dest,
d62a17ae 3011 new_select);
3012
1defdda8 3013 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3014 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3015 }
fee0f4c6 3016
3b0c17e1 3017 /* advertise/withdraw type-5 routes */
3018 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3019 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3020 bgp_process_evpn_route_injection(
9bcb3eef 3021 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3022
b1875e65 3023 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3024 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3025 bgp_zebra_clear_route_change_flags(dest);
3026 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3027 return;
d62a17ae 3028 }
8ad7271d 3029
d62a17ae 3030 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3031 */
9bcb3eef 3032 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3033
3034 /* bestpath has changed; bump version */
3035 if (old_select || new_select) {
9bcb3eef 3036 bgp_bump_version(dest);
d62a17ae 3037
3038 if (!bgp->t_rmap_def_originate_eval) {
3039 bgp_lock(bgp);
3040 thread_add_timer(
3041 bm->master,
3042 update_group_refresh_default_originate_route_map,
3043 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3044 &bgp->t_rmap_def_originate_eval);
3045 }
3046 }
3f9c7369 3047
d62a17ae 3048 if (old_select)
9bcb3eef 3049 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3050 if (new_select) {
ddb5b488
PZ
3051 if (debug)
3052 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3053 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3054 bgp_path_info_unset_flag(dest, new_select,
3055 BGP_PATH_ATTR_CHANGED);
1defdda8 3056 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3057 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3058 }
338b3424 3059
49e5a4a0 3060#ifdef ENABLE_BGP_VNC
d62a17ae 3061 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3062 if (old_select != new_select) {
3063 if (old_select) {
3064 vnc_import_bgp_exterior_del_route(bgp, p,
3065 old_select);
3066 vnc_import_bgp_del_route(bgp, p, old_select);
3067 }
3068 if (new_select) {
3069 vnc_import_bgp_exterior_add_route(bgp, p,
3070 new_select);
3071 vnc_import_bgp_add_route(bgp, p, new_select);
3072 }
3073 }
3074 }
65efcfce
LB
3075#endif
3076
9bcb3eef 3077 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3078
3079 /* unicast routes must also be annouced to labeled-unicast update-groups
3080 */
3081 if (safi == SAFI_UNICAST)
9bcb3eef 3082 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3083 new_select);
3084
3085 /* FIB update. */
3086 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3087 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3088
d62a17ae 3089 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3090 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3091 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3092 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3093
be785e35
DS
3094 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3095 SET_FLAG(dest->flags,
3096 BGP_NODE_FIB_INSTALL_PENDING);
3097
2b659f33
MK
3098 /* if this is an evpn imported type-5 prefix,
3099 * we need to withdraw the route first to clear
3100 * the nh neigh and the RMAC entry.
3101 */
3102 if (old_select &&
3103 is_route_parent_evpn(old_select))
3104 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3105
9bcb3eef 3106 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3107 } else {
d62a17ae 3108 /* Withdraw the route from the kernel. */
3109 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3110 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3111 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3112 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3113
568e10ca 3114 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3115 }
718e3744 3116 }
3064bf43 3117
9bcb3eef 3118 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3119 old_select);
5424b7ba 3120
d62a17ae 3121 /* Clear any route change flags. */
9bcb3eef 3122 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3123
18ee8310 3124 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3125 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3126 bgp_path_info_reap(dest, old_select);
d62a17ae 3127
9bcb3eef 3128 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3129 return;
718e3744 3130}
3131
f009ff26 3132/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3133int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3134{
9bcb3eef 3135 struct bgp_dest *dest;
f009ff26 3136 int cnt = 0;
3137 struct afi_safi_info *thread_info;
f009ff26 3138
56c226e7
DS
3139 if (bgp->gr_info[afi][safi].t_route_select) {
3140 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3141
3142 thread_info = THREAD_ARG(t);
3143 XFREE(MTYPE_TMP, thread_info);
f009ff26 3144 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3145 }
f009ff26 3146
3147 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3148 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3149 get_afi_safi_str(afi, safi, false),
26742171 3150 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3151 }
3152
3153 /* Process the route list */
6338d242
DS
3154 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3155 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3156 dest = bgp_route_next(dest)) {
3157 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3158 continue;
3159
3160 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3161 bgp->gr_info[afi][safi].gr_deferred--;
3162 bgp_process_main_one(bgp, dest, afi, safi);
3163 cnt++;
3164 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3165 bgp_dest_unlock_node(dest);
3166 break;
f009ff26 3167 }
f009ff26 3168 }
3169
9e3b51a7 3170 /* Send EOR message when all routes are processed */
6338d242 3171 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3172 bgp_send_delayed_eor(bgp);
8c48b3b6 3173 /* Send route processing complete message to RIB */
3174 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3175 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3176 return 0;
9e3b51a7 3177 }
f009ff26 3178
3179 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3180
3181 thread_info->afi = afi;
3182 thread_info->safi = safi;
3183 thread_info->bgp = bgp;
3184
3185 /* If there are more routes to be processed, start the
3186 * selection timer
3187 */
3188 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3189 BGP_ROUTE_SELECT_DELAY,
3190 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3191 return 0;
3192}
3193
aac24838 3194static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3195{
aac24838
JB
3196 struct bgp_process_queue *pqnode = data;
3197 struct bgp *bgp = pqnode->bgp;
d62a17ae 3198 struct bgp_table *table;
9bcb3eef 3199 struct bgp_dest *dest;
aac24838
JB
3200
3201 /* eoiu marker */
3202 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3203 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3204 /* should always have dedicated wq call */
3205 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3206 return WQ_SUCCESS;
3207 }
3208
ac021f40 3209 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3210 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3211 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3212 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3213 table = bgp_dest_table(dest);
3214 /* note, new DESTs may be added as part of processing */
3215 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3216
9bcb3eef 3217 bgp_dest_unlock_node(dest);
d62a17ae 3218 bgp_table_unlock(table);
3219 }
aac24838
JB
3220
3221 return WQ_SUCCESS;
3222}
3223
3224static void bgp_processq_del(struct work_queue *wq, void *data)
3225{
3226 struct bgp_process_queue *pqnode = data;
3227
3228 bgp_unlock(pqnode->bgp);
3229
3230 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3231}
3232
b6c386bb 3233void bgp_process_queue_init(struct bgp *bgp)
200df115 3234{
b6c386bb
DS
3235 if (!bgp->process_queue) {
3236 char name[BUFSIZ];
3237
3238 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3239 bgp->process_queue = work_queue_new(bm->master, name);
3240 }
3241
3242 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3243 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3244 bgp->process_queue->spec.max_retries = 0;
3245 bgp->process_queue->spec.hold = 50;
d62a17ae 3246 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3247 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3248}
3249
cfe8d15a 3250static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3251{
3252 struct bgp_process_queue *pqnode;
3253
a4d82a8a
PZ
3254 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3255 sizeof(struct bgp_process_queue));
aac24838
JB
3256
3257 /* unlocked in bgp_processq_del */
3258 pqnode->bgp = bgp_lock(bgp);
3259 STAILQ_INIT(&pqnode->pqueue);
3260
aac24838
JB
3261 return pqnode;
3262}
3263
9bcb3eef 3264void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3265{
aac24838 3266#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3267 struct work_queue *wq = bgp->process_queue;
d62a17ae 3268 struct bgp_process_queue *pqnode;
cfe8d15a 3269 int pqnode_reuse = 0;
495f0b13 3270
d62a17ae 3271 /* already scheduled for processing? */
9bcb3eef 3272 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3273 return;
2e02b9b2 3274
f009ff26 3275 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3276 * the workqueue
3277 */
9bcb3eef 3278 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3279 if (BGP_DEBUG(update, UPDATE_OUT))
3280 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3281 dest);
f009ff26 3282 return;
3283 }
3284
46aeabed
LS
3285 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3286 if (BGP_DEBUG(update, UPDATE_OUT))
3287 zlog_debug(
3288 "Soft reconfigure table in progress for route %p",
3289 dest);
3290 return;
3291 }
3292
aac24838 3293 if (wq == NULL)
d62a17ae 3294 return;
3295
aac24838 3296 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3297 limit only if is from the same BGP view and it's not an EOIU marker
3298 */
aac24838
JB
3299 if (work_queue_item_count(wq)) {
3300 struct work_queue_item *item = work_queue_last_item(wq);
3301 pqnode = item->data;
228da428 3302
a4d82a8a
PZ
3303 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3304 || pqnode->bgp != bgp
3305 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3306 pqnode = bgp_processq_alloc(bgp);
3307 else
3308 pqnode_reuse = 1;
aac24838 3309 } else
cfe8d15a 3310 pqnode = bgp_processq_alloc(bgp);
aac24838 3311 /* all unlocked in bgp_process_wq */
9bcb3eef 3312 bgp_table_lock(bgp_dest_table(dest));
aac24838 3313
9bcb3eef
DS
3314 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3315 bgp_dest_lock_node(dest);
aac24838 3316
60466a63 3317 /* can't be enqueued twice */
9bcb3eef
DS
3318 assert(STAILQ_NEXT(dest, pq) == NULL);
3319 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3320 pqnode->queued++;
3321
cfe8d15a
LB
3322 if (!pqnode_reuse)
3323 work_queue_add(wq, pqnode);
3324
d62a17ae 3325 return;
fee0f4c6 3326}
0a486e5f 3327
d62a17ae 3328void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3329{
d62a17ae 3330 struct bgp_process_queue *pqnode;
cb1faec9 3331
b6c386bb 3332 if (bgp->process_queue == NULL)
d62a17ae 3333 return;
2e02b9b2 3334
cfe8d15a 3335 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3336
aac24838 3337 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3338 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3339}
3340
d62a17ae 3341static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3342{
d62a17ae 3343 struct peer *peer;
0a486e5f 3344
d62a17ae 3345 peer = THREAD_ARG(thread);
3346 peer->t_pmax_restart = NULL;
0a486e5f 3347
d62a17ae 3348 if (bgp_debug_neighbor_events(peer))
3349 zlog_debug(
3350 "%s Maximum-prefix restart timer expired, restore peering",
3351 peer->host);
0a486e5f 3352
a9bafa95 3353 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3354 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3355
d62a17ae 3356 return 0;
0a486e5f 3357}
3358
9cbd06e0
DA
3359static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3360 safi_t safi)
3361{
3362 uint32_t count = 0;
f41b0459 3363 bool filtered = false;
9cbd06e0
DA
3364 struct bgp_dest *dest;
3365 struct bgp_adj_in *ain;
40bb2ccf 3366 struct attr attr = {};
9cbd06e0
DA
3367 struct bgp_table *table = peer->bgp->rib[afi][safi];
3368
3369 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3370 for (ain = dest->adj_in; ain; ain = ain->next) {
3371 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3372
3373 attr = *ain->attr;
9cbd06e0
DA
3374
3375 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3376 == FILTER_DENY)
f41b0459
DA
3377 filtered = true;
3378
3379 if (bgp_input_modifier(
3380 peer, rn_p, &attr, afi, safi,
3381 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3382 NULL, 0, NULL)
3383 == RMAP_DENY)
3384 filtered = true;
3385
3386 if (filtered)
9cbd06e0 3387 count++;
f41b0459
DA
3388
3389 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3390 }
3391 }
3392
3393 return count;
3394}
3395
3dc339cd
DA
3396bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3397 int always)
718e3744 3398{
d62a17ae 3399 iana_afi_t pkt_afi;
5c525538 3400 iana_safi_t pkt_safi;
9cbd06e0
DA
3401 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3402 PEER_FLAG_MAX_PREFIX_FORCE))
3403 ? bgp_filtered_routes_count(peer, afi, safi)
3404 + peer->pcount[afi][safi]
3405 : peer->pcount[afi][safi];
9cabb64b 3406
d62a17ae 3407 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3408 return false;
e0701b79 3409
9cbd06e0 3410 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3411 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3412 PEER_STATUS_PREFIX_LIMIT)
3413 && !always)
3dc339cd 3414 return false;
e0701b79 3415
d62a17ae 3416 zlog_info(
6cde4b45 3417 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3418 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3419 peer->pmax[afi][safi]);
d62a17ae 3420 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3421
3422 if (CHECK_FLAG(peer->af_flags[afi][safi],
3423 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3424 return false;
d62a17ae 3425
3426 /* Convert AFI, SAFI to values for packet. */
3427 pkt_afi = afi_int2iana(afi);
3428 pkt_safi = safi_int2iana(safi);
3429 {
d7c0a89a 3430 uint8_t ndata[7];
d62a17ae 3431
3432 ndata[0] = (pkt_afi >> 8);
3433 ndata[1] = pkt_afi;
3434 ndata[2] = pkt_safi;
3435 ndata[3] = (peer->pmax[afi][safi] >> 24);
3436 ndata[4] = (peer->pmax[afi][safi] >> 16);
3437 ndata[5] = (peer->pmax[afi][safi] >> 8);
3438 ndata[6] = (peer->pmax[afi][safi]);
3439
3440 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3441 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3442 BGP_NOTIFY_CEASE_MAX_PREFIX,
3443 ndata, 7);
3444 }
3445
3446 /* Dynamic peers will just close their connection. */
3447 if (peer_dynamic_neighbor(peer))
3dc339cd 3448 return true;
d62a17ae 3449
3450 /* restart timer start */
3451 if (peer->pmax_restart[afi][safi]) {
3452 peer->v_pmax_restart =
3453 peer->pmax_restart[afi][safi] * 60;
3454
3455 if (bgp_debug_neighbor_events(peer))
3456 zlog_debug(
3457 "%s Maximum-prefix restart timer started for %d secs",
3458 peer->host, peer->v_pmax_restart);
3459
3460 BGP_TIMER_ON(peer->t_pmax_restart,
3461 bgp_maximum_prefix_restart_timer,
3462 peer->v_pmax_restart);
3463 }
3464
3dc339cd 3465 return true;
d62a17ae 3466 } else
3467 UNSET_FLAG(peer->af_sflags[afi][safi],
3468 PEER_STATUS_PREFIX_LIMIT);
3469
b1823b69
DS
3470 if (pcount
3471 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3472 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3473 PEER_STATUS_PREFIX_THRESHOLD)
3474 && !always)
3dc339cd 3475 return false;
d62a17ae 3476
3477 zlog_info(
6cde4b45 3478 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3479 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3480 peer->pmax[afi][safi]);
d62a17ae 3481 SET_FLAG(peer->af_sflags[afi][safi],
3482 PEER_STATUS_PREFIX_THRESHOLD);
3483 } else
3484 UNSET_FLAG(peer->af_sflags[afi][safi],
3485 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3486 return false;
718e3744 3487}
3488
b40d939b 3489/* Unconditionally remove the route from the RIB, without taking
3490 * damping into consideration (eg, because the session went down)
3491 */
9bcb3eef 3492void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3493 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3494{
f009ff26 3495
3496 struct bgp *bgp = NULL;
3497 bool delete_route = false;
3498
9bcb3eef
DS
3499 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3500 safi);
d62a17ae 3501
f009ff26 3502 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3503 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3504
f009ff26 3505 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3506 * flag
3507 */
3508 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3509 delete_route = true;
9bcb3eef 3510 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3511 delete_route = true;
f009ff26 3512 if (delete_route) {
9bcb3eef
DS
3513 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3514 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3515 bgp = pi->peer->bgp;
26742171 3516 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3517 }
3518 }
3519 }
4a11bf2c 3520
9bcb3eef
DS
3521 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3522 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3523}
3524
9bcb3eef 3525static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3526 struct peer *peer, afi_t afi, safi_t safi,
3527 struct prefix_rd *prd)
3528{
9bcb3eef 3529 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3530
d62a17ae 3531 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3532 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3533 */
b4f7f45b
IR
3534 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3535 && peer->sort == BGP_PEER_EBGP)
3536 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3537 == BGP_DAMP_SUPPRESSED) {
3538 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3539 safi);
3540 return;
d62a17ae 3541 }
3542
49e5a4a0 3543#ifdef ENABLE_BGP_VNC
d62a17ae 3544 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3545 struct bgp_dest *pdest = NULL;
d62a17ae 3546 struct bgp_table *table = NULL;
3547
9bcb3eef
DS
3548 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3549 (struct prefix *)prd);
3550 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3551 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3552
3553 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3554 peer->bgp, prd, table, p, pi);
d62a17ae 3555 }
9bcb3eef 3556 bgp_dest_unlock_node(pdest);
d62a17ae 3557 }
3558 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3559 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3560
b54892e0
DS
3561 vnc_import_bgp_del_route(peer->bgp, p, pi);
3562 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3563 }
65efcfce 3564 }
d62a17ae 3565#endif
128ea8ab 3566
d62a17ae 3567 /* If this is an EVPN route, process for un-import. */
3568 if (safi == SAFI_EVPN)
b54892e0 3569 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3570
9bcb3eef 3571 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3572}
3573
4b7e6066
DS
3574struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3575 struct peer *peer, struct attr *attr,
9bcb3eef 3576 struct bgp_dest *dest)
fb018d25 3577{
4b7e6066 3578 struct bgp_path_info *new;
fb018d25 3579
d62a17ae 3580 /* Make new BGP info. */
4b7e6066 3581 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3582 new->type = type;
3583 new->instance = instance;
3584 new->sub_type = sub_type;
3585 new->peer = peer;
3586 new->attr = attr;
3587 new->uptime = bgp_clock();
9bcb3eef 3588 new->net = dest;
d62a17ae 3589 return new;
fb018d25
DS
3590}
3591
c265ee22 3592/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3593bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3594 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3595 struct bgp_dest *dest)
d62a17ae 3596{
2dbe3fa9 3597 bool ret = false;
b099a5c8
DA
3598 bool is_bgp_static_route =
3599 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3600 : false;
d62a17ae 3601
e8442016
DS
3602 /*
3603 * Only validated for unicast and multicast currently.
3604 * Also valid for EVPN where the nexthop is an IP address.
3605 * If we are a bgp static route being checked then there is
3606 * no need to check to see if the nexthop is martian as
3607 * that it should be ok.
3608 */
3609 if (is_bgp_static_route ||
3610 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3611 return false;
d62a17ae 3612
3613 /* If NEXT_HOP is present, validate it. */
3614 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3615 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3616 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3617 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3618 return true;
d62a17ae 3619 }
c265ee22 3620
d62a17ae 3621 /* If MP_NEXTHOP is present, validate it. */
3622 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3623 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3624 * it is not an IPv6 link-local address.
0355b41d
DA
3625 *
3626 * If we receive an UPDATE with nexthop length set to 32 bytes
3627 * we shouldn't discard an UPDATE if it's set to (::).
3628 * The link-local (2st) is validated along the code path later.
d62a17ae 3629 */
3630 if (attr->mp_nexthop_len) {
3631 switch (attr->mp_nexthop_len) {
3632 case BGP_ATTR_NHLEN_IPV4:
3633 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3634 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3635 || IPV4_CLASS_DE(
3636 ntohl(attr->mp_nexthop_global_in.s_addr))
3637 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3638 dest));
d62a17ae 3639 break;
3640
3641 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3642 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3643 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3644 &attr->mp_nexthop_global)
d62a17ae 3645 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3646 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3647 &attr->mp_nexthop_global)
3648 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3649 dest));
d62a17ae 3650 break;
0355b41d
DA
3651 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3652 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3653 || IN6_IS_ADDR_MULTICAST(
3654 &attr->mp_nexthop_global)
3655 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3656 dest));
0355b41d 3657 break;
d62a17ae 3658
3659 default:
3dc339cd 3660 ret = true;
d62a17ae 3661 break;
3662 }
3663 }
c265ee22 3664
d62a17ae 3665 return ret;
3666}
3667
aade37d7 3668static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3669{
3670 struct community *old;
3671 struct community *new;
3672 struct community *merge;
aade37d7 3673 struct community *no_export;
2721dd61
DA
3674
3675 old = attr->community;
aade37d7 3676 no_export = community_str2com("no-export");
2721dd61 3677
b4efa101
DA
3678 assert(no_export);
3679
2721dd61 3680 if (old) {
aade37d7 3681 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3682
3683 if (!old->refcnt)
3684 community_free(&old);
3685
3686 new = community_uniq_sort(merge);
3687 community_free(&merge);
3688 } else {
aade37d7 3689 new = community_dup(no_export);
2721dd61
DA
3690 }
3691
aade37d7 3692 community_free(&no_export);
2721dd61
DA
3693
3694 attr->community = new;
3695 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3696}
3697
5a1ae2c2 3698int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3699 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3700 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3701 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3702 struct bgp_route_evpn *evpn)
d62a17ae 3703{
3704 int ret;
3705 int aspath_loop_count = 0;
9bcb3eef 3706 struct bgp_dest *dest;
d62a17ae 3707 struct bgp *bgp;
3708 struct attr new_attr;
3709 struct attr *attr_new;
40381db7 3710 struct bgp_path_info *pi;
4b7e6066
DS
3711 struct bgp_path_info *new;
3712 struct bgp_path_info_extra *extra;
d62a17ae 3713 const char *reason;
3714 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3715 int connected = 0;
3716 int do_loop_check = 1;
3717 int has_valid_label = 0;
7c312383 3718 afi_t nh_afi;
949b0f24 3719 uint8_t pi_type = 0;
3720 uint8_t pi_sub_type = 0;
9146341f 3721 bool force_evpn_import = false;
907707db 3722 safi_t orig_safi = safi;
949b0f24 3723
c7bb4f00 3724 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3725 char pfxprint[PREFIX2STR_BUFFER];
3726
3727 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3728 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3729 afi, safi, attr);
6401252f
QY
3730 }
3731
49e5a4a0 3732#ifdef ENABLE_BGP_VNC
d62a17ae 3733 int vnc_implicit_withdraw = 0;
65efcfce 3734#endif
d62a17ae 3735 int same_attr = 0;
718e3744 3736
907707db
MS
3737 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3738 if (orig_safi == SAFI_LABELED_UNICAST)
3739 safi = SAFI_UNICAST;
3740
d62a17ae 3741 memset(&new_attr, 0, sizeof(struct attr));
3742 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3743 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3744
d62a17ae 3745 bgp = peer->bgp;
9bcb3eef 3746 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3747 /* TODO: Check to see if we can get rid of "is_valid_label" */
3748 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3749 has_valid_label = (num_labels > 0) ? 1 : 0;
3750 else
3751 has_valid_label = bgp_is_valid_label(label);
718e3744 3752
28f66de2
MS
3753 if (has_valid_label)
3754 assert(label != NULL);
3755
66ff6089
AD
3756 /* Update overlay index of the attribute */
3757 if (afi == AFI_L2VPN && evpn)
3758 memcpy(&attr->evpn_overlay, evpn,
3759 sizeof(struct bgp_route_evpn));
3760
d62a17ae 3761 /* When peer's soft reconfiguration enabled. Record input packet in
3762 Adj-RIBs-In. */
3763 if (!soft_reconfig
3764 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3765 && peer != bgp->peer_self)
9bcb3eef 3766 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3767
3768 /* Check previously received route. */
9bcb3eef 3769 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3770 if (pi->peer == peer && pi->type == type
3771 && pi->sub_type == sub_type
3772 && pi->addpath_rx_id == addpath_id)
d62a17ae 3773 break;
3774
3775 /* AS path local-as loop check. */
3776 if (peer->change_local_as) {
c4368918
DW
3777 if (peer->allowas_in[afi][safi])
3778 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3779 else if (!CHECK_FLAG(peer->flags,
3780 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3781 aspath_loop_count = 1;
3782
3783 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3784 > aspath_loop_count) {
b4d46cc9 3785 peer->stat_pfx_aspath_loop++;
692174a1 3786 reason = "as-path contains our own AS;";
d62a17ae 3787 goto filtered;
3788 }
718e3744 3789 }
718e3744 3790
d62a17ae 3791 /* If the peer is configured for "allowas-in origin" and the last ASN in
3792 * the
3793 * as-path is our ASN then we do not need to call aspath_loop_check
3794 */
3795 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3796 if (aspath_get_last_as(attr->aspath) == bgp->as)
3797 do_loop_check = 0;
3798
3799 /* AS path loop check. */
3800 if (do_loop_check) {
3801 if (aspath_loop_check(attr->aspath, bgp->as)
3802 > peer->allowas_in[afi][safi]
3803 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3804 && aspath_loop_check(attr->aspath, bgp->confed_id)
3805 > peer->allowas_in[afi][safi])) {
b4d46cc9 3806 peer->stat_pfx_aspath_loop++;
d62a17ae 3807 reason = "as-path contains our own AS;";
3808 goto filtered;
3809 }
3810 }
aac9ef6c 3811
d62a17ae 3812 /* Route reflector originator ID check. */
3813 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3814 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3815 peer->stat_pfx_originator_loop++;
d62a17ae 3816 reason = "originator is us;";
3817 goto filtered;
3818 }
718e3744 3819
d62a17ae 3820 /* Route reflector cluster ID check. */
3821 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3822 peer->stat_pfx_cluster_loop++;
d62a17ae 3823 reason = "reflected from the same cluster;";
3824 goto filtered;
3825 }
718e3744 3826
d62a17ae 3827 /* Apply incoming filter. */
907707db 3828 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3829 peer->stat_pfx_filter++;
d62a17ae 3830 reason = "filter;";
3831 goto filtered;
3832 }
718e3744 3833
a8b72dc6
DA
3834 /* RFC 8212 to prevent route leaks.
3835 * This specification intends to improve this situation by requiring the
3836 * explicit configuration of both BGP Import and Export Policies for any
3837 * External BGP (EBGP) session such as customers, peers, or
3838 * confederation boundaries for all enabled address families. Through
3839 * codification of the aforementioned requirement, operators will
3840 * benefit from consistent behavior across different BGP
3841 * implementations.
3842 */
1d3fdccf 3843 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3844 if (!bgp_inbound_policy_exists(peer,
3845 &peer->filter[afi][safi])) {
3846 reason = "inbound policy missing";
3847 goto filtered;
3848 }
3849
fb29348a
DA
3850 /* draft-ietf-idr-deprecate-as-set-confed-set
3851 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3852 * Eventually, This document (if approved) updates RFC 4271
3853 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3854 * and obsoletes RFC 6472.
3855 */
7f972cd8 3856 if (peer->bgp->reject_as_sets)
fb29348a
DA
3857 if (aspath_check_as_sets(attr->aspath)) {
3858 reason =
3859 "as-path contains AS_SET or AS_CONFED_SET type;";
3860 goto filtered;
3861 }
3862
6f4f49b2 3863 new_attr = *attr;
d62a17ae 3864
3865 /* Apply incoming route-map.
3866 * NB: new_attr may now contain newly allocated values from route-map
3867 * "set"
3868 * commands, so we need bgp_attr_flush in the error paths, until we
3869 * intern
3870 * the attr (which takes over the memory references) */
907707db 3871 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3872 num_labels, dest)
3873 == RMAP_DENY) {
b4d46cc9 3874 peer->stat_pfx_filter++;
d62a17ae 3875 reason = "route-map;";
3876 bgp_attr_flush(&new_attr);
3877 goto filtered;
3878 }
718e3744 3879
05864da7 3880 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3881 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3882 /* remove from RIB previous entry */
3883 bgp_zebra_withdraw(p, pi, bgp, safi);
3884 }
3885
7f323236
DW
3886 if (peer->sort == BGP_PEER_EBGP) {
3887
2721dd61
DA
3888 /* rfc7999:
3889 * A BGP speaker receiving an announcement tagged with the
3890 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3891 * NO_EXPORT community as defined in RFC1997, or a
3892 * similar community, to prevent propagation of the
3893 * prefix outside the local AS. The community to prevent
3894 * propagation SHOULD be chosen according to the operator's
3895 * routing policy.
3896 */
3897 if (new_attr.community
3898 && community_include(new_attr.community,
3899 COMMUNITY_BLACKHOLE))
aade37d7 3900 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3901
a4d82a8a
PZ
3902 /* If we receive the graceful-shutdown community from an eBGP
3903 * peer we must lower local-preference */
3904 if (new_attr.community
3905 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3906 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3907 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3908
a4d82a8a
PZ
3909 /* If graceful-shutdown is configured then add the GSHUT
3910 * community to all paths received from eBGP peers */
637e5ba4 3911 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3912 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3913 }
3914
949b0f24 3915 if (pi) {
3916 pi_type = pi->type;
3917 pi_sub_type = pi->sub_type;
3918 }
3919
d62a17ae 3920 /* next hop check. */
a4d82a8a 3921 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3922 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3923 &new_attr, dest)) {
b4d46cc9 3924 peer->stat_pfx_nh_invalid++;
d62a17ae 3925 reason = "martian or self next-hop;";
3926 bgp_attr_flush(&new_attr);
3927 goto filtered;
3928 }
718e3744 3929
5c14a191 3930 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3931 peer->stat_pfx_nh_invalid++;
4e802e66 3932 reason = "self mac;";
4dbf2038 3933 bgp_attr_flush(&new_attr);
4e802e66
DS
3934 goto filtered;
3935 }
3936
a1b773e2
DS
3937 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3938 * condition :
3939 * Suppress fib is enabled
3940 * BGP_OPT_NO_FIB is not enabled
3941 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3942 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3943 */
3944 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3945 && (sub_type == BGP_ROUTE_NORMAL)
3946 && (!bgp_option_check(BGP_OPT_NO_FIB))
3947 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3948 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3949
9cbd06e0
DA
3950 /* If maximum prefix count is configured and current prefix
3951 * count exeed it.
3952 */
4dbf2038
IR
3953 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
3954 bgp_attr_flush(&new_attr);
9cbd06e0 3955 return -1;
4dbf2038
IR
3956 }
3957
3958 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 3959
d62a17ae 3960 /* If the update is implicit withdraw. */
40381db7
DS
3961 if (pi) {
3962 pi->uptime = bgp_clock();
3963 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3964
9bcb3eef 3965 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3966
d62a17ae 3967 /* Same attribute comes in. */
40381db7 3968 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3969 && same_attr
d62a17ae 3970 && (!has_valid_label
40381db7 3971 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3972 num_labels * sizeof(mpls_label_t))
66ff6089 3973 == 0)) {
b4f7f45b
IR
3974 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3975 BGP_CONFIG_DAMPENING)
d62a17ae 3976 && peer->sort == BGP_PEER_EBGP
40381db7 3977 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3978 if (bgp_debug_update(peer, p, NULL, 1)) {
3979 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3980 afi, safi, prd, p, label,
3981 num_labels, addpath_id ? 1 : 0,
66ff6089 3982 addpath_id, evpn, pfx_buf,
a4d82a8a 3983 sizeof(pfx_buf));
d62a17ae 3984 zlog_debug("%s rcvd %s", peer->host,
3985 pfx_buf);
3986 }
3987
9bcb3eef 3988 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3989 != BGP_DAMP_SUPPRESSED) {
40381db7 3990 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3991 safi);
9bcb3eef 3992 bgp_process(bgp, dest, afi, safi);
d62a17ae 3993 }
3994 } else /* Duplicate - odd */
3995 {
3996 if (bgp_debug_update(peer, p, NULL, 1)) {
3997 if (!peer->rcvd_attr_printed) {
3998 zlog_debug(
3999 "%s rcvd UPDATE w/ attr: %s",
4000 peer->host,
4001 peer->rcvd_attr_str);
4002 peer->rcvd_attr_printed = 1;
4003 }
4004
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));
d62a17ae 4010 zlog_debug(
4011 "%s rcvd %s...duplicate ignored",
4012 peer->host, pfx_buf);
4013 }
4014
4015 /* graceful restart STALE flag unset. */
40381db7 4016 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4017 bgp_path_info_unset_flag(
9bcb3eef
DS
4018 dest, pi, BGP_PATH_STALE);
4019 bgp_dest_set_defer_flag(dest, false);
4020 bgp_process(bgp, dest, afi, safi);
d62a17ae 4021 }
4022 }
4023
9bcb3eef 4024 bgp_dest_unlock_node(dest);
d62a17ae 4025 bgp_attr_unintern(&attr_new);
4026
4027 return 0;
4028 }
718e3744 4029
d62a17ae 4030 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4031 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4032 if (bgp_debug_update(peer, p, NULL, 1)) {
4033 bgp_debug_rdpfxpath2str(
a4d82a8a 4034 afi, safi, prd, p, label, num_labels,
66ff6089 4035 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4036 pfx_buf, sizeof(pfx_buf));
d62a17ae 4037 zlog_debug(
4038 "%s rcvd %s, flapped quicker than processing",
4039 peer->host, pfx_buf);
4040 }
4041
9bcb3eef 4042 bgp_path_info_restore(dest, pi);
9146341f 4043
4044 /*
4045 * If the BGP_PATH_REMOVED flag is set, then EVPN
4046 * routes would have been unimported already when a
4047 * prior BGP withdraw processing happened. Such routes
4048 * need to be imported again, so flag accordingly.
4049 */
4050 force_evpn_import = true;
d62a17ae 4051 }
718e3744 4052
d62a17ae 4053 /* Received Logging. */
4054 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4055 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4056 num_labels, addpath_id ? 1 : 0,
66ff6089 4057 addpath_id, evpn, pfx_buf,
a4d82a8a 4058 sizeof(pfx_buf));
d62a17ae 4059 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4060 }
718e3744 4061
d62a17ae 4062 /* graceful restart STALE flag unset. */
f009ff26 4063 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4064 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4065 bgp_dest_set_defer_flag(dest, false);
f009ff26 4066 }
d62a17ae 4067
4068 /* The attribute is changed. */
9bcb3eef 4069 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4070
4071 /* implicit withdraw, decrement aggregate and pcount here.
4072 * only if update is accepted, they'll increment below.
4073 */
40381db7 4074 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4075
4076 /* Update bgp route dampening information. */
b4f7f45b 4077 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4078 && peer->sort == BGP_PEER_EBGP) {
4079 /* This is implicit withdraw so we should update
b4f7f45b
IR
4080 dampening
4081 information. */
40381db7 4082 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4083 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4084 }
49e5a4a0 4085#ifdef ENABLE_BGP_VNC
d62a17ae 4086 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4087 struct bgp_dest *pdest = NULL;
d62a17ae 4088 struct bgp_table *table = NULL;
4089
9bcb3eef
DS
4090 pdest = bgp_node_get(bgp->rib[afi][safi],
4091 (struct prefix *)prd);
4092 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4093 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4094
4095 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4096 bgp, prd, table, p, pi);
d62a17ae 4097 }
9bcb3eef 4098 bgp_dest_unlock_node(pdest);
d62a17ae 4099 }
4100 if ((afi == AFI_IP || afi == AFI_IP6)
4101 && (safi == SAFI_UNICAST)) {
40381db7 4102 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4103 /*
4104 * Implicit withdraw case.
4105 */
4106 ++vnc_implicit_withdraw;
40381db7
DS
4107 vnc_import_bgp_del_route(bgp, p, pi);
4108 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4109 }
4110 }
65efcfce 4111#endif
128ea8ab 4112
d62a17ae 4113 /* Special handling for EVPN update of an existing route. If the
4114 * extended community attribute has changed, we need to
4115 * un-import
4116 * the route using its existing extended community. It will be
4117 * subsequently processed for import with the new extended
4118 * community.
4119 */
6f8c9c11
PR
4120 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4121 && !same_attr) {
40381db7 4122 if ((pi->attr->flag
d62a17ae 4123 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4124 && (attr_new->flag
4125 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4126 int cmp;
4127
b53e67a3
DA
4128 cmp = ecommunity_cmp(
4129 bgp_attr_get_ecommunity(pi->attr),
4130 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4131 if (!cmp) {
4132 if (bgp_debug_update(peer, p, NULL, 1))
4133 zlog_debug(
4134 "Change in EXT-COMM, existing %s new %s",
4135 ecommunity_str(
b53e67a3
DA
4136 bgp_attr_get_ecommunity(
4137 pi->attr)),
d62a17ae 4138 ecommunity_str(
b53e67a3
DA
4139 bgp_attr_get_ecommunity(
4140 attr_new)));
6f8c9c11
PR
4141 if (safi == SAFI_EVPN)
4142 bgp_evpn_unimport_route(
4143 bgp, afi, safi, p, pi);
4144 else /* SAFI_MPLS_VPN */
4145 vpn_leak_to_vrf_withdraw(bgp,
4146 pi);
d62a17ae 4147 }
4148 }
4149 }
718e3744 4150
d62a17ae 4151 /* Update to new attribute. */
40381db7
DS
4152 bgp_attr_unintern(&pi->attr);
4153 pi->attr = attr_new;
d62a17ae 4154
4155 /* Update MPLS label */
4156 if (has_valid_label) {
40381db7 4157 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4158 if (extra->label != label) {
4159 memcpy(&extra->label, label,
dbd587da 4160 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4161 extra->num_labels = num_labels;
4162 }
b57ba6d2
MK
4163 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4164 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4165 }
718e3744 4166
e496b420
HS
4167 /* Update SRv6 SID */
4168 if (attr->srv6_l3vpn) {
4169 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4170 if (sid_diff(&extra->sid[0].sid,
4171 &attr->srv6_l3vpn->sid)) {
4172 sid_copy(&extra->sid[0].sid,
e496b420
HS
4173 &attr->srv6_l3vpn->sid);
4174 extra->num_sids = 1;
cc8f05df 4175
16f3db2d
RS
4176 extra->sid[0].loc_block_len = 0;
4177 extra->sid[0].loc_node_len = 0;
4178 extra->sid[0].func_len = 0;
4179 extra->sid[0].arg_len = 0;
4180
4181 if (attr->srv6_l3vpn->loc_block_len != 0) {
4182 extra->sid[0].loc_block_len =
4183 attr->srv6_l3vpn->loc_block_len;
4184 extra->sid[0].loc_node_len =
4185 attr->srv6_l3vpn->loc_node_len;
4186 extra->sid[0].func_len =
4187 attr->srv6_l3vpn->func_len;
4188 extra->sid[0].arg_len =
4189 attr->srv6_l3vpn->arg_len;
4190 }
4191
cc8f05df
RS
4192 /*
4193 * draft-ietf-bess-srv6-services-07
4194 * The part of SRv6 SID may be encoded as MPLS
4195 * Label for the efficient packing.
4196 */
4197 if (attr->srv6_l3vpn->transposition_len != 0)
4198 transpose_sid(
16f3db2d 4199 &extra->sid[0].sid,
cc8f05df
RS
4200 decode_label(label),
4201 attr->srv6_l3vpn
4202 ->transposition_offset,
4203 attr->srv6_l3vpn
4204 ->transposition_len);
e496b420
HS
4205 }
4206 } else if (attr->srv6_vpn) {
4207 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4208 if (sid_diff(&extra->sid[0].sid,
4209 &attr->srv6_vpn->sid)) {
4210 sid_copy(&extra->sid[0].sid,
4211 &attr->srv6_vpn->sid);
e496b420
HS
4212 extra->num_sids = 1;
4213 }
4214 }
4215
49e5a4a0 4216#ifdef ENABLE_BGP_VNC
d62a17ae 4217 if ((afi == AFI_IP || afi == AFI_IP6)
4218 && (safi == SAFI_UNICAST)) {
4219 if (vnc_implicit_withdraw) {
4220 /*
4221 * Add back the route with its new attributes
4222 * (e.g., nexthop).
4223 * The route is still selected, until the route
4224 * selection
4225 * queued by bgp_process actually runs. We have
4226 * to make this
4227 * update to the VNC side immediately to avoid
4228 * racing against
4229 * configuration changes (e.g., route-map
4230 * changes) which
4231 * trigger re-importation of the entire RIB.
4232 */
40381db7
DS
4233 vnc_import_bgp_add_route(bgp, p, pi);
4234 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4235 }
4236 }
65efcfce
LB
4237#endif
4238
d62a17ae 4239 /* Update bgp route dampening information. */
b4f7f45b 4240 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4241 && peer->sort == BGP_PEER_EBGP) {
4242 /* Now we do normal update dampening. */
9bcb3eef 4243 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4244 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4245 bgp_dest_unlock_node(dest);
d62a17ae 4246 return 0;
4247 }
4248 }
128ea8ab 4249
d62a17ae 4250 /* Nexthop reachability check - for unicast and
4251 * labeled-unicast.. */
7c312383
AD
4252 if (((afi == AFI_IP || afi == AFI_IP6)
4253 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4254 || (safi == SAFI_EVPN &&
4255 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4256 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4257 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4258 && !CHECK_FLAG(peer->flags,
4259 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4260 && !CHECK_FLAG(bgp->flags,
4261 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4262 connected = 1;
4263 else
4264 connected = 0;
4265
960035b2
PZ
4266 struct bgp *bgp_nexthop = bgp;
4267
40381db7
DS
4268 if (pi->extra && pi->extra->bgp_orig)
4269 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4270
7c312383
AD
4271 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4272
4273 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4274 safi, pi, NULL, connected,
4275 p)
a4d82a8a 4276 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4277 bgp_path_info_set_flag(dest, pi,
4278 BGP_PATH_VALID);
d62a17ae 4279 else {
4280 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4281 zlog_debug("%s(%pI4): NH unresolved",
4282 __func__,
4283 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4284 }
9bcb3eef 4285 bgp_path_info_unset_flag(dest, pi,
18ee8310 4286 BGP_PATH_VALID);
d62a17ae 4287 }
4288 } else
9bcb3eef 4289 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4290
49e5a4a0 4291#ifdef ENABLE_BGP_VNC
d62a17ae 4292 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4293 struct bgp_dest *pdest = NULL;
d62a17ae 4294 struct bgp_table *table = NULL;
4295
9bcb3eef
DS
4296 pdest = bgp_node_get(bgp->rib[afi][safi],
4297 (struct prefix *)prd);
4298 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4299 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4300
4301 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4302 bgp, prd, table, p, pi);
d62a17ae 4303 }
9bcb3eef 4304 bgp_dest_unlock_node(pdest);
d62a17ae 4305 }
4306#endif
718e3744 4307
d62a17ae 4308 /* If this is an EVPN route and some attribute has changed,
9146341f 4309 * or we are explicitly told to perform a route import, process
d62a17ae 4310 * route for import. If the extended community has changed, we
4311 * would
4312 * have done the un-import earlier and the import would result
4313 * in the
4314 * route getting injected into appropriate L2 VNIs. If it is
4315 * just
4316 * some other attribute change, the import will result in
4317 * updating
4318 * the attributes for the route in the VNI(s).
4319 */
9146341f 4320 if (safi == SAFI_EVPN &&
4321 (!same_attr || force_evpn_import) &&
7c312383 4322 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4323 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4324
4325 /* Process change. */
40381db7 4326 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4327
9bcb3eef
DS
4328 bgp_process(bgp, dest, afi, safi);
4329 bgp_dest_unlock_node(dest);
558d1fec 4330
ddb5b488
PZ
4331 if (SAFI_UNICAST == safi
4332 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4333 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4334
40381db7 4335 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4336 }
4337 if ((SAFI_MPLS_VPN == safi)
4338 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4339
40381db7 4340 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4341 }
4342
49e5a4a0 4343#ifdef ENABLE_BGP_VNC
d62a17ae 4344 if (SAFI_MPLS_VPN == safi) {
4345 mpls_label_t label_decoded = decode_label(label);
28070ee3 4346
d62a17ae 4347 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4348 type, sub_type, &label_decoded);
4349 }
4350 if (SAFI_ENCAP == safi) {
4351 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4352 type, sub_type, NULL);
4353 }
28070ee3
PZ
4354#endif
4355
d62a17ae 4356 return 0;
4357 } // End of implicit withdraw
718e3744 4358
d62a17ae 4359 /* Received Logging. */
4360 if (bgp_debug_update(peer, p, NULL, 1)) {
4361 if (!peer->rcvd_attr_printed) {
4362 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4363 peer->rcvd_attr_str);
4364 peer->rcvd_attr_printed = 1;
4365 }
718e3744 4366
a4d82a8a 4367 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4368 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4369 pfx_buf, sizeof(pfx_buf));
d62a17ae 4370 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4371 }
718e3744 4372
d62a17ae 4373 /* Make new BGP info. */
9bcb3eef 4374 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4375
d62a17ae 4376 /* Update MPLS label */
4377 if (has_valid_label) {
18ee8310 4378 extra = bgp_path_info_extra_get(new);
8ba71050 4379 if (extra->label != label) {
dbd587da
QY
4380 memcpy(&extra->label, label,
4381 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4382 extra->num_labels = num_labels;
4383 }
b57ba6d2
MK
4384 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4385 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4386 }
718e3744 4387
e496b420
HS
4388 /* Update SRv6 SID */
4389 if (safi == SAFI_MPLS_VPN) {
4390 extra = bgp_path_info_extra_get(new);
4391 if (attr->srv6_l3vpn) {
16f3db2d 4392 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4393 extra->num_sids = 1;
cc8f05df 4394
16f3db2d
RS
4395 extra->sid[0].loc_block_len =
4396 attr->srv6_l3vpn->loc_block_len;
4397 extra->sid[0].loc_node_len =
4398 attr->srv6_l3vpn->loc_node_len;
4399 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4400 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
4401
cc8f05df
RS
4402 /*
4403 * draft-ietf-bess-srv6-services-07
4404 * The part of SRv6 SID may be encoded as MPLS Label for
4405 * the efficient packing.
4406 */
4407 if (attr->srv6_l3vpn->transposition_len != 0)
4408 transpose_sid(
16f3db2d 4409 &extra->sid[0].sid, decode_label(label),
cc8f05df
RS
4410 attr->srv6_l3vpn->transposition_offset,
4411 attr->srv6_l3vpn->transposition_len);
e496b420 4412 } else if (attr->srv6_vpn) {
16f3db2d 4413 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4414 extra->num_sids = 1;
4415 }
4416 }
4417
d62a17ae 4418 /* Nexthop reachability check. */
7c312383
AD
4419 if (((afi == AFI_IP || afi == AFI_IP6)
4420 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4421 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4422 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4423 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4424 && !CHECK_FLAG(peer->flags,
4425 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4426 && !CHECK_FLAG(bgp->flags,
4427 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4428 connected = 1;
4429 else
4430 connected = 0;
4431
7c312383
AD
4432 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4433
4053e952 4434 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4435 connected, p)
a4d82a8a 4436 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4437 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4438 else {
4439 if (BGP_DEBUG(nht, NHT)) {
4440 char buf1[INET6_ADDRSTRLEN];
4441 inet_ntop(AF_INET,
4442 (const void *)&attr_new->nexthop,
4443 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4444 zlog_debug("%s(%s): NH unresolved", __func__,
4445 buf1);
d62a17ae 4446 }
9bcb3eef 4447 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4448 }
4449 } else
9bcb3eef 4450 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4451
d62a17ae 4452 /* Addpath ID */
4453 new->addpath_rx_id = addpath_id;
4454
4455 /* Increment prefix */
4456 bgp_aggregate_increment(bgp, p, new, afi, safi);
4457
4458 /* Register new BGP information. */
9bcb3eef 4459 bgp_path_info_add(dest, new);
d62a17ae 4460
4461 /* route_node_get lock */
9bcb3eef 4462 bgp_dest_unlock_node(dest);
558d1fec 4463
49e5a4a0 4464#ifdef ENABLE_BGP_VNC
d62a17ae 4465 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4466 struct bgp_dest *pdest = NULL;
d62a17ae 4467 struct bgp_table *table = NULL;
4468
9bcb3eef
DS
4469 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4470 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4471 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4472
4473 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4474 bgp, prd, table, p, new);
4475 }
9bcb3eef 4476 bgp_dest_unlock_node(pdest);
d62a17ae 4477 }
65efcfce
LB
4478#endif
4479
d62a17ae 4480 /* If this is an EVPN route, process for import. */
7c312383 4481 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4482 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4483
9bcb3eef 4484 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4485
d62a17ae 4486 /* Process change. */
9bcb3eef 4487 bgp_process(bgp, dest, afi, safi);
718e3744 4488
ddb5b488
PZ
4489 if (SAFI_UNICAST == safi
4490 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4491 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4492 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4493 }
4494 if ((SAFI_MPLS_VPN == safi)
4495 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4496
4497 vpn_leak_to_vrf_update(bgp, new);
4498 }
49e5a4a0 4499#ifdef ENABLE_BGP_VNC
d62a17ae 4500 if (SAFI_MPLS_VPN == safi) {
4501 mpls_label_t label_decoded = decode_label(label);
28070ee3 4502
d62a17ae 4503 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4504 sub_type, &label_decoded);
4505 }
4506 if (SAFI_ENCAP == safi) {
4507 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4508 sub_type, NULL);
4509 }
28070ee3
PZ
4510#endif
4511
d62a17ae 4512 return 0;
718e3744 4513
d62a17ae 4514/* This BGP update is filtered. Log the reason then update BGP
4515 entry. */
4516filtered:
9bcb3eef 4517 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4518
d62a17ae 4519 if (bgp_debug_update(peer, p, NULL, 1)) {
4520 if (!peer->rcvd_attr_printed) {
4521 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4522 peer->rcvd_attr_str);
4523 peer->rcvd_attr_printed = 1;
4524 }
718e3744 4525
a4d82a8a 4526 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4527 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4528 pfx_buf, sizeof(pfx_buf));
d62a17ae 4529 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4530 peer->host, pfx_buf, reason);
4531 }
128ea8ab 4532
40381db7 4533 if (pi) {
d62a17ae 4534 /* If this is an EVPN route, un-import it as it is now filtered.
4535 */
4536 if (safi == SAFI_EVPN)
40381db7 4537 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4538
ddb5b488
PZ
4539 if (SAFI_UNICAST == safi
4540 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4541 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4542
40381db7 4543 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4544 }
4545 if ((SAFI_MPLS_VPN == safi)
4546 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4547
40381db7 4548 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4549 }
4550
9bcb3eef 4551 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4552 }
4553
9bcb3eef 4554 bgp_dest_unlock_node(dest);
558d1fec 4555
49e5a4a0 4556#ifdef ENABLE_BGP_VNC
d62a17ae 4557 /*
4558 * Filtered update is treated as an implicit withdrawal (see
4559 * bgp_rib_remove()
4560 * a few lines above)
4561 */
4562 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4563 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4564 0);
4565 }
97736e32
PZ
4566#endif
4567
d62a17ae 4568 return 0;
718e3744 4569}
4570
26a3ffd6 4571int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4572 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4573 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4574 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4575{
d62a17ae 4576 struct bgp *bgp;
4577 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4578 struct bgp_dest *dest;
40381db7 4579 struct bgp_path_info *pi;
718e3744 4580
49e5a4a0 4581#ifdef ENABLE_BGP_VNC
d62a17ae 4582 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4583 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4584 0);
4585 }
28070ee3
PZ
4586#endif
4587
d62a17ae 4588 bgp = peer->bgp;
4589
4590 /* Lookup node. */
9bcb3eef 4591 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4592
4593 /* If peer is soft reconfiguration enabled. Record input packet for
4594 * further calculation.
4595 *
4596 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4597 * routes that are filtered. This tanks out Quagga RS pretty badly due
4598 * to
4599 * the iteration over all RS clients.
4600 * Since we need to remove the entry from adj_in anyway, do that first
4601 * and
4602 * if there was no entry, we don't need to do anything more.
4603 */
4604 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4605 && peer != bgp->peer_self)
9bcb3eef 4606 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4607 peer->stat_pfx_dup_withdraw++;
4608
d62a17ae 4609 if (bgp_debug_update(peer, p, NULL, 1)) {
4610 bgp_debug_rdpfxpath2str(
a4d82a8a 4611 afi, safi, prd, p, label, num_labels,
6c995628
AD
4612 addpath_id ? 1 : 0, addpath_id, NULL,
4613 pfx_buf, sizeof(pfx_buf));
d62a17ae 4614 zlog_debug(
4615 "%s withdrawing route %s not in adj-in",
4616 peer->host, pfx_buf);
4617 }
9bcb3eef 4618 bgp_dest_unlock_node(dest);
d62a17ae 4619 return 0;
4620 }
cd808e74 4621
d62a17ae 4622 /* Lookup withdrawn route. */
9bcb3eef 4623 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4624 if (pi->peer == peer && pi->type == type
4625 && pi->sub_type == sub_type
4626 && pi->addpath_rx_id == addpath_id)
d62a17ae 4627 break;
4628
4629 /* Logging. */
4630 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4631 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4632 addpath_id ? 1 : 0, addpath_id, NULL,
4633 pfx_buf, sizeof(pfx_buf));
d62a17ae 4634 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4635 pfx_buf);
4636 }
718e3744 4637
d62a17ae 4638 /* Withdraw specified route from routing table. */
40381db7 4639 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4640 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4641 if (SAFI_UNICAST == safi
4642 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4643 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4644 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4645 }
4646 if ((SAFI_MPLS_VPN == safi)
4647 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4648
40381db7 4649 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4650 }
4651 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4652 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4653 addpath_id ? 1 : 0, addpath_id, NULL,
4654 pfx_buf, sizeof(pfx_buf));
d62a17ae 4655 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4656 }
718e3744 4657
d62a17ae 4658 /* Unlock bgp_node_get() lock. */
9bcb3eef 4659 bgp_dest_unlock_node(dest);
d62a17ae 4660
4661 return 0;
718e3744 4662}
6b0655a2 4663
d62a17ae 4664void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4665 int withdraw)
718e3744 4666{
d62a17ae 4667 struct update_subgroup *subgrp;
4668 subgrp = peer_subgroup(peer, afi, safi);
4669 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4670}
6182d65b 4671
718e3744 4672
3f9c7369
DS
4673/*
4674 * bgp_stop_announce_route_timer
4675 */
d62a17ae 4676void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4677{
d62a17ae 4678 if (!paf->t_announce_route)
4679 return;
4680
50478845 4681 thread_cancel(&paf->t_announce_route);
718e3744 4682}
6b0655a2 4683
3f9c7369
DS
4684/*
4685 * bgp_announce_route_timer_expired
4686 *
4687 * Callback that is invoked when the route announcement timer for a
4688 * peer_af expires.
4689 */
d62a17ae 4690static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4691{
d62a17ae 4692 struct peer_af *paf;
4693 struct peer *peer;
558d1fec 4694
d62a17ae 4695 paf = THREAD_ARG(t);
4696 peer = paf->peer;
718e3744 4697
feb17238 4698 if (!peer_established(peer))
d62a17ae 4699 return 0;
3f9c7369 4700
d62a17ae 4701 if (!peer->afc_nego[paf->afi][paf->safi])
4702 return 0;
3f9c7369 4703
d62a17ae 4704 peer_af_announce_route(paf, 1);
c5aec50b
MK
4705
4706 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4707 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4708
d62a17ae 4709 return 0;
718e3744 4710}
4711
3f9c7369
DS
4712/*
4713 * bgp_announce_route
4714 *
4715 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4716 *
4717 * if force is true we will force an update even if the update
4718 * limiting code is attempted to kick in.
3f9c7369 4719 */
e1a32ec1 4720void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4721{
4722 struct peer_af *paf;
4723 struct update_subgroup *subgrp;
4724
4725 paf = peer_af_find(peer, afi, safi);
4726 if (!paf)
4727 return;
4728 subgrp = PAF_SUBGRP(paf);
4729
4730 /*
4731 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4732 * or a refresh has already been triggered.
4733 */
4734 if (!subgrp || paf->t_announce_route)
4735 return;
4736
e1a32ec1
DS
4737 if (force)
4738 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4739
d62a17ae 4740 /*
4741 * Start a timer to stagger/delay the announce. This serves
4742 * two purposes - announcement can potentially be combined for
4743 * multiple peers and the announcement doesn't happen in the
4744 * vty context.
4745 */
4746 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4747 (subgrp->peer_count == 1)
4748 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4749 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4750 &paf->t_announce_route);
3f9c7369
DS
4751}
4752
4753/*
4754 * Announce routes from all AF tables to a peer.
4755 *
4756 * This should ONLY be called when there is a need to refresh the
4757 * routes to the peer based on a policy change for this peer alone
4758 * or a route refresh request received from the peer.
4759 * The operation will result in splitting the peer from its existing
4760 * subgroups and putting it in new subgroups.
4761 */
d62a17ae 4762void bgp_announce_route_all(struct peer *peer)
718e3744 4763{
d62a17ae 4764 afi_t afi;
4765 safi_t safi;
4766
05c7a1cc 4767 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4768 bgp_announce_route(peer, afi, safi, false);
718e3744 4769}
6b0655a2 4770
46aeabed
LS
4771/* Flag or unflag bgp_dest to determine whether it should be treated by
4772 * bgp_soft_reconfig_table_task.
4773 * Flag if flag is true. Unflag if flag is false.
4774 */
4775static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4776{
4777 struct bgp_dest *dest;
4778 struct bgp_adj_in *ain;
4779
4780 if (!table)
4781 return;
4782
4783 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4784 for (ain = dest->adj_in; ain; ain = ain->next) {
4785 if (ain->peer != NULL)
4786 break;
4787 }
4788 if (flag && ain != NULL && ain->peer != NULL)
4789 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4790 else
4791 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4792 }
4793}
4794
4795static int bgp_soft_reconfig_table_update(struct peer *peer,
4796 struct bgp_dest *dest,
4797 struct bgp_adj_in *ain, afi_t afi,
4798 safi_t safi, struct prefix_rd *prd)
4799{
4800 struct bgp_path_info *pi;
4801 uint32_t num_labels = 0;
4802 mpls_label_t *label_pnt = NULL;
4803 struct bgp_route_evpn evpn;
4804
4805 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4806 if (pi->peer == peer)
4807 break;
4808
4809 if (pi && pi->extra)
4810 num_labels = pi->extra->num_labels;
4811 if (num_labels)
4812 label_pnt = &pi->extra->label[0];
4813 if (pi)
4814 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4815 sizeof(evpn));
4816 else
4817 memset(&evpn, 0, sizeof(evpn));
4818
4819 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4820 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4821 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4822 &evpn);
4823}
4824
d62a17ae 4825static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4826 struct bgp_table *table,
4827 struct prefix_rd *prd)
718e3744 4828{
d62a17ae 4829 int ret;
9bcb3eef 4830 struct bgp_dest *dest;
d62a17ae 4831 struct bgp_adj_in *ain;
718e3744 4832
d62a17ae 4833 if (!table)
4834 table = peer->bgp->rib[afi][safi];
718e3744 4835
9bcb3eef
DS
4836 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4837 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4838 if (ain->peer != peer)
4839 continue;
8692c506 4840
46aeabed
LS
4841 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4842 afi, safi, prd);
ea47320b
DL
4843
4844 if (ret < 0) {
9bcb3eef 4845 bgp_dest_unlock_node(dest);
ea47320b 4846 return;
d62a17ae 4847 }
4848 }
718e3744 4849}
4850
46aeabed
LS
4851/* Do soft reconfig table per bgp table.
4852 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4853 * when BGP_NODE_SOFT_RECONFIG is set,
4854 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4855 * Schedule a new thread to continue the job.
4856 * Without splitting the full job into several part,
4857 * vtysh waits for the job to finish before responding to a BGP command
4858 */
4859static int bgp_soft_reconfig_table_task(struct thread *thread)
4860{
4861 uint32_t iter, max_iter;
4862 int ret;
4863 struct bgp_dest *dest;
4864 struct bgp_adj_in *ain;
4865 struct peer *peer;
4866 struct bgp_table *table;
4867 struct prefix_rd *prd;
4868 struct listnode *node, *nnode;
4869
4870 table = THREAD_ARG(thread);
4871 prd = NULL;
4872
4873 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4874 if (table->soft_reconfig_init) {
4875 /* first call of the function with a new srta structure.
4876 * Don't do any treatment this time on nodes
4877 * in order vtysh to respond quickly
4878 */
4879 max_iter = 0;
4880 }
4881
4882 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4883 dest = bgp_route_next(dest)) {
4884 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4885 continue;
4886
4887 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4888
4889 for (ain = dest->adj_in; ain; ain = ain->next) {
4890 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4891 nnode, peer)) {
4892 if (ain->peer != peer)
4893 continue;
4894
4895 ret = bgp_soft_reconfig_table_update(
4896 peer, dest, ain, table->afi,
4897 table->safi, prd);
4898 iter++;
4899
4900 if (ret < 0) {
4901 bgp_dest_unlock_node(dest);
4902 listnode_delete(
4903 table->soft_reconfig_peers,
4904 peer);
4905 bgp_announce_route(peer, table->afi,
e1a32ec1 4906 table->safi, false);
46aeabed
LS
4907 if (list_isempty(
4908 table->soft_reconfig_peers)) {
4909 list_delete(
4910 &table->soft_reconfig_peers);
4911 bgp_soft_reconfig_table_flag(
4912 table, false);
4913 return 0;
4914 }
4915 }
4916 }
4917 }
4918 }
4919
4920 /* we're either starting the initial iteration,
4921 * or we're going to continue an ongoing iteration
4922 */
4923 if (dest || table->soft_reconfig_init) {
4924 table->soft_reconfig_init = false;
4925 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4926 table, 0, &table->soft_reconfig_thread);
4927 return 0;
4928 }
4929 /* we're done, clean up the background iteration context info and
4930 schedule route annoucement
4931 */
4932 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4933 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 4934 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
4935 }
4936
4937 list_delete(&table->soft_reconfig_peers);
4938
4939 return 0;
4940}
4941
4942
4943/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4944 * and peer.
4945 * - bgp cannot be NULL
4946 * - if table and peer are NULL, cancel all threads within the bgp instance
4947 * - if table is NULL and peer is not,
4948 * remove peer in all threads within the bgp instance
4949 * - if peer is NULL, cancel all threads matching table within the bgp instance
4950 */
4951void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4952 const struct bgp_table *table,
4953 const struct peer *peer)
4954{
4955 struct peer *npeer;
4956 struct listnode *node, *nnode;
4957 int afi, safi;
4958 struct bgp_table *ntable;
4959
4960 if (!bgp)
4961 return;
4962
4963 FOREACH_AFI_SAFI (afi, safi) {
4964 ntable = bgp->rib[afi][safi];
4965 if (!ntable)
4966 continue;
4967 if (table && table != ntable)
4968 continue;
4969
4970 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4971 npeer)) {
4972 if (peer && peer != npeer)
4973 continue;
4974 listnode_delete(ntable->soft_reconfig_peers, npeer);
4975 }
4976
4977 if (!ntable->soft_reconfig_peers
4978 || !list_isempty(ntable->soft_reconfig_peers))
4979 continue;
4980
4981 list_delete(&ntable->soft_reconfig_peers);
4982 bgp_soft_reconfig_table_flag(ntable, false);
4983 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4984 }
4985}
4986
d62a17ae 4987void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4988{
9bcb3eef 4989 struct bgp_dest *dest;
d62a17ae 4990 struct bgp_table *table;
46aeabed
LS
4991 struct listnode *node, *nnode;
4992 struct peer *npeer;
4993 struct peer_af *paf;
718e3744 4994
feb17238 4995 if (!peer_established(peer))
d62a17ae 4996 return;
718e3744 4997
d62a17ae 4998 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
4999 && (safi != SAFI_EVPN)) {
5000 table = peer->bgp->rib[afi][safi];
5001 if (!table)
5002 return;
5003
5004 table->soft_reconfig_init = true;
5005
5006 if (!table->soft_reconfig_peers)
5007 table->soft_reconfig_peers = list_new();
5008 npeer = NULL;
5009 /* add peer to the table soft_reconfig_peers if not already
5010 * there
5011 */
5012 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5013 npeer)) {
5014 if (peer == npeer)
5015 break;
5016 }
5017 if (peer != npeer)
5018 listnode_add(table->soft_reconfig_peers, peer);
5019
5020 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5021 * on table would start back at the beginning.
5022 */
5023 bgp_soft_reconfig_table_flag(table, true);
5024
5025 if (!table->soft_reconfig_thread)
5026 thread_add_event(bm->master,
5027 bgp_soft_reconfig_table_task, table, 0,
5028 &table->soft_reconfig_thread);
5029 /* Cancel bgp_announce_route_timer_expired threads.
5030 * bgp_announce_route_timer_expired threads have been scheduled
5031 * to announce routes as soon as the soft_reconfigure process
5032 * finishes.
5033 * In this case, soft_reconfigure is also scheduled by using
5034 * a thread but is planned after the
5035 * bgp_announce_route_timer_expired threads. It means that,
5036 * without cancelling the threads, the route announcement task
5037 * would run before the soft reconfiguration one. That would
5038 * useless and would block vtysh during several seconds. Route
5039 * announcements are rescheduled as soon as the soft_reconfigure
5040 * process finishes.
5041 */
5042 paf = peer_af_find(peer, afi, safi);
5043 if (paf)
5044 bgp_stop_announce_route_timer(paf);
5045 } else
9bcb3eef
DS
5046 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5047 dest = bgp_route_next(dest)) {
5048 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5049
b54892e0
DS
5050 if (table == NULL)
5051 continue;
8692c506 5052
9bcb3eef 5053 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5054 struct prefix_rd prd;
5055
5056 prd.family = AF_UNSPEC;
5057 prd.prefixlen = 64;
5058 memcpy(&prd.val, p->u.val, 8);
5059
5060 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5061 }
718e3744 5062}
6b0655a2 5063
228da428 5064
d62a17ae 5065struct bgp_clear_node_queue {
9bcb3eef 5066 struct bgp_dest *dest;
228da428
CC
5067};
5068
d62a17ae 5069static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5070{
d62a17ae 5071 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5072 struct bgp_dest *dest = cnq->dest;
d62a17ae 5073 struct peer *peer = wq->spec.data;
40381db7 5074 struct bgp_path_info *pi;
3103e8d2 5075 struct bgp *bgp;
9bcb3eef
DS
5076 afi_t afi = bgp_dest_table(dest)->afi;
5077 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5078
9bcb3eef 5079 assert(dest && peer);
3103e8d2 5080 bgp = peer->bgp;
d62a17ae 5081
5082 /* It is possible that we have multiple paths for a prefix from a peer
5083 * if that peer is using AddPath.
5084 */
9bcb3eef 5085 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5086 if (pi->peer != peer)
ea47320b
DL
5087 continue;
5088
5089 /* graceful restart STALE flag set. */
9af52ccf
DA
5090 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5091 && peer->nsf[afi][safi])
5092 || CHECK_FLAG(peer->af_sflags[afi][safi],
5093 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5094 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5095 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5096 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5097 else {
5098 /* If this is an EVPN route, process for
5099 * un-import. */
5100 if (safi == SAFI_EVPN)
9bcb3eef
DS
5101 bgp_evpn_unimport_route(
5102 bgp, afi, safi,
5103 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5104 /* Handle withdraw for VRF route-leaking and L3VPN */
5105 if (SAFI_UNICAST == safi
5106 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5107 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5108 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5109 bgp, pi);
960035b2 5110 }
3103e8d2 5111 if (SAFI_MPLS_VPN == safi &&
960035b2 5112 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5113 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5114 }
3103e8d2 5115
9bcb3eef 5116 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5117 }
ea47320b 5118 }
d62a17ae 5119 return WQ_SUCCESS;
200df115 5120}
5121
d62a17ae 5122static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5123{
d62a17ae 5124 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5125 struct bgp_dest *dest = cnq->dest;
5126 struct bgp_table *table = bgp_dest_table(dest);
228da428 5127
9bcb3eef 5128 bgp_dest_unlock_node(dest);
d62a17ae 5129 bgp_table_unlock(table);
5130 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5131}
5132
d62a17ae 5133static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5134{
d62a17ae 5135 struct peer *peer = wq->spec.data;
64e580a7 5136
d62a17ae 5137 /* Tickle FSM to start moving again */
5138 BGP_EVENT_ADD(peer, Clearing_Completed);
5139
5140 peer_unlock(peer); /* bgp_clear_route */
200df115 5141}
718e3744 5142
d62a17ae 5143static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5144{
d62a17ae 5145 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5146
5147 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5148#undef CLEAR_QUEUE_NAME_LEN
5149
0ce1ca80 5150 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5151 peer->clear_node_queue->spec.hold = 10;
5152 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5153 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5154 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5155 peer->clear_node_queue->spec.max_retries = 0;
5156
5157 /* we only 'lock' this peer reference when the queue is actually active
5158 */
5159 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5160}
5161
d62a17ae 5162static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5163 struct bgp_table *table)
65ca75e0 5164{
9bcb3eef 5165 struct bgp_dest *dest;
b6c386bb 5166 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5167
d62a17ae 5168 if (!table)
5169 table = peer->bgp->rib[afi][safi];
dc83d712 5170
d62a17ae 5171 /* If still no table => afi/safi isn't configured at all or smth. */
5172 if (!table)
5173 return;
dc83d712 5174
9bcb3eef 5175 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5176 struct bgp_path_info *pi, *next;
d62a17ae 5177 struct bgp_adj_in *ain;
5178 struct bgp_adj_in *ain_next;
5179
5180 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5181 * queued for every clearing peer, regardless of whether it is
5182 * relevant to the peer at hand.
5183 *
5184 * Overview: There are 3 different indices which need to be
5185 * scrubbed, potentially, when a peer is removed:
5186 *
5187 * 1 peer's routes visible via the RIB (ie accepted routes)
5188 * 2 peer's routes visible by the (optional) peer's adj-in index
5189 * 3 other routes visible by the peer's adj-out index
5190 *
5191 * 3 there is no hurry in scrubbing, once the struct peer is
5192 * removed from bgp->peer, we could just GC such deleted peer's
5193 * adj-outs at our leisure.
5194 *
5195 * 1 and 2 must be 'scrubbed' in some way, at least made
5196 * invisible via RIB index before peer session is allowed to be
5197 * brought back up. So one needs to know when such a 'search' is
5198 * complete.
5199 *
5200 * Ideally:
5201 *
5202 * - there'd be a single global queue or a single RIB walker
5203 * - rather than tracking which route_nodes still need to be
5204 * examined on a peer basis, we'd track which peers still
5205 * aren't cleared
5206 *
5207 * Given that our per-peer prefix-counts now should be reliable,
5208 * this may actually be achievable. It doesn't seem to be a huge
5209 * problem at this time,
5210 *
5211 * It is possible that we have multiple paths for a prefix from
5212 * a peer
5213 * if that peer is using AddPath.
5214 */
9bcb3eef 5215 ain = dest->adj_in;
d62a17ae 5216 while (ain) {
5217 ain_next = ain->next;
5218
6a840fd9 5219 if (ain->peer == peer)
9bcb3eef 5220 bgp_adj_in_remove(dest, ain);
d62a17ae 5221
5222 ain = ain_next;
5223 }
5224
9bcb3eef 5225 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5226 next = pi->next;
5227 if (pi->peer != peer)
d62a17ae 5228 continue;
5229
5230 if (force)
9bcb3eef 5231 bgp_path_info_reap(dest, pi);
d62a17ae 5232 else {
5233 struct bgp_clear_node_queue *cnq;
5234
5235 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5236 bgp_table_lock(bgp_dest_table(dest));
5237 bgp_dest_lock_node(dest);
d62a17ae 5238 cnq = XCALLOC(
5239 MTYPE_BGP_CLEAR_NODE_QUEUE,
5240 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5241 cnq->dest = dest;
d62a17ae 5242 work_queue_add(peer->clear_node_queue, cnq);
5243 break;
5244 }
5245 }
5246 }
5247 return;
5248}
5249
5250void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5251{
9bcb3eef 5252 struct bgp_dest *dest;
d62a17ae 5253 struct bgp_table *table;
5254
5255 if (peer->clear_node_queue == NULL)
5256 bgp_clear_node_queue_init(peer);
5257
5258 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5259 * Idle until it receives a Clearing_Completed event. This protects
5260 * against peers which flap faster than we can we clear, which could
5261 * lead to:
5262 *
5263 * a) race with routes from the new session being installed before
5264 * clear_route_node visits the node (to delete the route of that
5265 * peer)
5266 * b) resource exhaustion, clear_route_node likely leads to an entry
5267 * on the process_main queue. Fast-flapping could cause that queue
5268 * to grow and grow.
5269 */
5270
5271 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5272 * the unlock will happen upon work-queue completion; other wise, the
5273 * unlock happens at the end of this function.
5274 */
5275 if (!peer->clear_node_queue->thread)
5276 peer_lock(peer);
5277
5278 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5279 bgp_clear_route_table(peer, afi, safi, NULL);
5280 else
9bcb3eef
DS
5281 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5282 dest = bgp_route_next(dest)) {
5283 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5284 if (!table)
5285 continue;
5286
5287 bgp_clear_route_table(peer, afi, safi, table);
5288 }
d62a17ae 5289
5290 /* unlock if no nodes got added to the clear-node-queue. */
5291 if (!peer->clear_node_queue->thread)
5292 peer_unlock(peer);
718e3744 5293}
d62a17ae 5294
5295void bgp_clear_route_all(struct peer *peer)
718e3744 5296{
d62a17ae 5297 afi_t afi;
5298 safi_t safi;
718e3744 5299
05c7a1cc
QY
5300 FOREACH_AFI_SAFI (afi, safi)
5301 bgp_clear_route(peer, afi, safi);
65efcfce 5302
49e5a4a0 5303#ifdef ENABLE_BGP_VNC
d62a17ae 5304 rfapiProcessPeerDown(peer);
65efcfce 5305#endif
718e3744 5306}
5307
d62a17ae 5308void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5309{
d62a17ae 5310 struct bgp_table *table;
9bcb3eef 5311 struct bgp_dest *dest;
d62a17ae 5312 struct bgp_adj_in *ain;
5313 struct bgp_adj_in *ain_next;
718e3744 5314
d62a17ae 5315 table = peer->bgp->rib[afi][safi];
718e3744 5316
d62a17ae 5317 /* It is possible that we have multiple paths for a prefix from a peer
5318 * if that peer is using AddPath.
5319 */
9bcb3eef
DS
5320 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5321 ain = dest->adj_in;
43143c8f 5322
d62a17ae 5323 while (ain) {
5324 ain_next = ain->next;
43143c8f 5325
6a840fd9 5326 if (ain->peer == peer)
9bcb3eef 5327 bgp_adj_in_remove(dest, ain);
43143c8f 5328
d62a17ae 5329 ain = ain_next;
5330 }
5331 }
718e3744 5332}
93406d87 5333
1479ed2f
DA
5334/* If any of the routes from the peer have been marked with the NO_LLGR
5335 * community, either as sent by the peer, or as the result of a configured
5336 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5337 * operation of [RFC4271].
5338 */
d62a17ae 5339void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5340{
9bcb3eef 5341 struct bgp_dest *dest;
40381db7 5342 struct bgp_path_info *pi;
d62a17ae 5343 struct bgp_table *table;
5344
9af52ccf 5345 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5346 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5347 dest = bgp_route_next(dest)) {
5348 struct bgp_dest *rm;
d62a17ae 5349
5350 /* look for neighbor in tables */
9bcb3eef 5351 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5352 if (!table)
ea47320b
DL
5353 continue;
5354
5355 for (rm = bgp_table_top(table); rm;
5356 rm = bgp_route_next(rm))
9bcb3eef 5357 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5358 pi = pi->next) {
40381db7 5359 if (pi->peer != peer)
ea47320b 5360 continue;
1479ed2f
DA
5361 if (CHECK_FLAG(
5362 peer->af_sflags[afi][safi],
5363 PEER_STATUS_LLGR_WAIT) &&
5364 pi->attr->community &&
5365 !community_include(
5366 pi->attr->community,
5367 COMMUNITY_NO_LLGR))
5368 break;
40381db7 5369 if (!CHECK_FLAG(pi->flags,
1defdda8 5370 BGP_PATH_STALE))
ea47320b
DL
5371 break;
5372
641065d4
KM
5373 /*
5374 * If this is VRF leaked route
5375 * process for withdraw.
5376 */
5377 if (pi->sub_type ==
5378 BGP_ROUTE_IMPORTED &&
5379 peer->bgp->inst_type ==
5380 BGP_INSTANCE_TYPE_DEFAULT)
5381 vpn_leak_to_vrf_withdraw(
5382 peer->bgp, pi);
5383
40381db7 5384 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5385 break;
5386 }
d62a17ae 5387 }
5388 } else {
9bcb3eef
DS
5389 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5390 dest = bgp_route_next(dest))
5391 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5392 pi = pi->next) {
40381db7 5393 if (pi->peer != peer)
ea47320b 5394 continue;
1479ed2f
DA
5395 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5396 PEER_STATUS_LLGR_WAIT) &&
5397 pi->attr->community &&
5398 !community_include(pi->attr->community,
5399 COMMUNITY_NO_LLGR))
5400 break;
40381db7 5401 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 5402 break;
641065d4
KM
5403 if (safi == SAFI_UNICAST &&
5404 (peer->bgp->inst_type ==
5405 BGP_INSTANCE_TYPE_VRF ||
5406 peer->bgp->inst_type ==
5407 BGP_INSTANCE_TYPE_DEFAULT))
5408 vpn_leak_from_vrf_withdraw(
5409 bgp_get_default(), peer->bgp,
5410 pi);
5411
9bcb3eef 5412 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5413 break;
5414 }
d62a17ae 5415 }
93406d87 5416}
6b0655a2 5417
9af52ccf
DA
5418void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5419{
5420 struct bgp_dest *dest, *ndest;
5421 struct bgp_path_info *pi;
5422 struct bgp_table *table;
5423
5424 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5425 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5426 dest = bgp_route_next(dest)) {
5427 table = bgp_dest_get_bgp_table_info(dest);
5428 if (!table)
5429 continue;
5430
5431 for (ndest = bgp_table_top(table); ndest;
5432 ndest = bgp_route_next(ndest)) {
5433 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5434 pi = pi->next) {
5435 if (pi->peer != peer)
5436 continue;
5437
5438 if ((CHECK_FLAG(
5439 peer->af_sflags[afi][safi],
5440 PEER_STATUS_ENHANCED_REFRESH))
5441 && !CHECK_FLAG(pi->flags,
5442 BGP_PATH_STALE)
5443 && !CHECK_FLAG(
5444 pi->flags,
5445 BGP_PATH_UNUSEABLE)) {
5446 if (bgp_debug_neighbor_events(
5447 peer))
5448 zlog_debug(
5449 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5450 peer->host,
5451 afi2str(afi),
5452 safi2str(safi),
5453 bgp_dest_get_prefix(
5454 ndest));
5455
5456 bgp_path_info_set_flag(
5457 ndest, pi,
5458 BGP_PATH_STALE);
5459 }
5460 }
5461 }
5462 }
5463 } else {
5464 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5465 dest = bgp_route_next(dest)) {
5466 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5467 pi = pi->next) {
5468 if (pi->peer != peer)
5469 continue;
5470
5471 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5472 PEER_STATUS_ENHANCED_REFRESH))
5473 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5474 && !CHECK_FLAG(pi->flags,
5475 BGP_PATH_UNUSEABLE)) {
5476 if (bgp_debug_neighbor_events(peer))
5477 zlog_debug(
5478 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5479 peer->host,
5480 afi2str(afi),
5481 safi2str(safi),
5482 bgp_dest_get_prefix(
5483 dest));
5484
5485 bgp_path_info_set_flag(dest, pi,
5486 BGP_PATH_STALE);
5487 }
5488 }
5489 }
5490 }
5491}
5492
3dc339cd 5493bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5494{
e0df4c04 5495 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5496 return true;
e0df4c04 5497
9dac9fc8
DA
5498 if (peer->sort == BGP_PEER_EBGP
5499 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5500 || FILTER_LIST_OUT_NAME(filter)
5501 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5502 return true;
5503 return false;
9dac9fc8
DA
5504}
5505
3dc339cd 5506bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5507{
e0df4c04 5508 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5509 return true;
e0df4c04 5510
9dac9fc8
DA
5511 if (peer->sort == BGP_PEER_EBGP
5512 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5513 || FILTER_LIST_IN_NAME(filter)
5514 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5515 return true;
5516 return false;
9dac9fc8
DA
5517}
5518
568e10ca 5519static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5520 safi_t safi)
bb86c601 5521{
9bcb3eef 5522 struct bgp_dest *dest;
40381db7 5523 struct bgp_path_info *pi;
4b7e6066 5524 struct bgp_path_info *next;
bb86c601 5525
9bcb3eef
DS
5526 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5527 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5528 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5529
40381db7 5530 next = pi->next;
1b7bb747
CS
5531
5532 /* Unimport EVPN routes from VRFs */
5533 if (safi == SAFI_EVPN)
5534 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5535 SAFI_EVPN, p, pi);
1b7bb747 5536
40381db7
DS
5537 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5538 && pi->type == ZEBRA_ROUTE_BGP
5539 && (pi->sub_type == BGP_ROUTE_NORMAL
5540 || pi->sub_type == BGP_ROUTE_AGGREGATE
5541 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5542
d62a17ae 5543 if (bgp_fibupd_safi(safi))
b54892e0 5544 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5545 }
9514b37d 5546
9bcb3eef 5547 bgp_path_info_reap(dest, pi);
d62a17ae 5548 }
bb86c601
LB
5549}
5550
718e3744 5551/* Delete all kernel routes. */
d62a17ae 5552void bgp_cleanup_routes(struct bgp *bgp)
5553{
5554 afi_t afi;
9bcb3eef 5555 struct bgp_dest *dest;
67009e22 5556 struct bgp_table *table;
d62a17ae 5557
5558 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5559 if (afi == AFI_L2VPN)
5560 continue;
568e10ca 5561 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5562 SAFI_UNICAST);
d62a17ae 5563 /*
5564 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5565 */
5566 if (afi != AFI_L2VPN) {
5567 safi_t safi;
5568 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5569 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5570 dest = bgp_route_next(dest)) {
5571 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5572 if (table != NULL) {
5573 bgp_cleanup_table(bgp, table, safi);
5574 bgp_table_finish(&table);
9bcb3eef
DS
5575 bgp_dest_set_bgp_table_info(dest, NULL);
5576 bgp_dest_unlock_node(dest);
d62a17ae 5577 }
5578 }
5579 safi = SAFI_ENCAP;
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 }
5591 }
9bcb3eef
DS
5592 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5593 dest = bgp_route_next(dest)) {
5594 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5595 if (table != NULL) {
5596 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5597 bgp_table_finish(&table);
9bcb3eef
DS
5598 bgp_dest_set_bgp_table_info(dest, NULL);
5599 bgp_dest_unlock_node(dest);
d62a17ae 5600 }
bb86c601 5601 }
718e3744 5602}
5603
d62a17ae 5604void bgp_reset(void)
718e3744 5605{
d62a17ae 5606 vty_reset();
5607 bgp_zclient_reset();
5608 access_list_reset();
5609 prefix_list_reset();
718e3744 5610}
6b0655a2 5611
be92fc9f 5612bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5613{
d62a17ae 5614 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5615 && CHECK_FLAG(peer->af_cap[afi][safi],
5616 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5617}
5618
718e3744 5619/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5620 value. */
d62a17ae 5621int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5622 struct bgp_nlri *packet)
5623{
d7c0a89a
QY
5624 uint8_t *pnt;
5625 uint8_t *lim;
d62a17ae 5626 struct prefix p;
5627 int psize;
5628 int ret;
5629 afi_t afi;
5630 safi_t safi;
be92fc9f 5631 bool addpath_capable;
d7c0a89a 5632 uint32_t addpath_id;
d62a17ae 5633
d62a17ae 5634 pnt = packet->nlri;
5635 lim = pnt + packet->length;
5636 afi = packet->afi;
5637 safi = packet->safi;
5638 addpath_id = 0;
be92fc9f 5639 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5640
5641 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5642 syntactic validity. If the field is syntactically incorrect,
5643 then the Error Subcode is set to Invalid Network Field. */
5644 for (; pnt < lim; pnt += psize) {
5645 /* Clear prefix structure. */
5646 memset(&p, 0, sizeof(struct prefix));
5647
be92fc9f 5648 if (addpath_capable) {
d62a17ae 5649
5650 /* When packet overflow occurs return immediately. */
761ed665 5651 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5652 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5653
a3a850a1 5654 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5655 addpath_id = ntohl(addpath_id);
d62a17ae 5656 pnt += BGP_ADDPATH_ID_LEN;
5657 }
718e3744 5658
d62a17ae 5659 /* Fetch prefix length. */
5660 p.prefixlen = *pnt++;
5661 /* afi/safi validity already verified by caller,
5662 * bgp_update_receive */
5663 p.family = afi2family(afi);
5664
5665 /* Prefix length check. */
5666 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5667 flog_err(
e50f7cfd 5668 EC_BGP_UPDATE_RCV,
14454c9f 5669 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5670 peer->host, p.prefixlen, packet->afi);
513386b5 5671 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5672 }
6b0655a2 5673
d62a17ae 5674 /* Packet size overflow check. */
5675 psize = PSIZE(p.prefixlen);
5676
5677 /* When packet overflow occur return immediately. */
5678 if (pnt + psize > lim) {
af4c2728 5679 flog_err(
e50f7cfd 5680 EC_BGP_UPDATE_RCV,
d62a17ae 5681 "%s [Error] Update packet error (prefix length %d overflows packet)",
5682 peer->host, p.prefixlen);
513386b5 5683 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5684 }
5685
5686 /* Defensive coding, double-check the psize fits in a struct
5687 * prefix */
5688 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5689 flog_err(
e50f7cfd 5690 EC_BGP_UPDATE_RCV,
d62a17ae 5691 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5692 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5693 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5694 }
5695
5696 /* Fetch prefix from NLRI packet. */
a85297a7 5697 memcpy(p.u.val, pnt, psize);
d62a17ae 5698
5699 /* Check address. */
5700 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5701 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5702 /* From RFC4271 Section 6.3:
5703 *
5704 * If a prefix in the NLRI field is semantically
5705 * incorrect
5706 * (e.g., an unexpected multicast IP address),
5707 * an error SHOULD
5708 * be logged locally, and the prefix SHOULD be
5709 * ignored.
a4d82a8a 5710 */
af4c2728 5711 flog_err(
e50f7cfd 5712 EC_BGP_UPDATE_RCV,
23d0a753
DA
5713 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5714 peer->host, &p.u.prefix4);
d62a17ae 5715 continue;
5716 }
5717 }
5718
5719 /* Check address. */
5720 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5721 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5722 flog_err(
e50f7cfd 5723 EC_BGP_UPDATE_RCV,
c0d72166
DS
5724 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5725 peer->host, &p.u.prefix6);
d62a17ae 5726
5727 continue;
5728 }
5729 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5730 flog_err(
e50f7cfd 5731 EC_BGP_UPDATE_RCV,
c0d72166
DS
5732 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5733 peer->host, &p.u.prefix6);
d62a17ae 5734
5735 continue;
5736 }
5737 }
5738
5739 /* Normal process. */
5740 if (attr)
5741 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5742 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5743 NULL, NULL, 0, 0, NULL);
d62a17ae 5744 else
5745 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5746 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5747 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5748 NULL);
d62a17ae 5749
513386b5
DA
5750 /* Do not send BGP notification twice when maximum-prefix count
5751 * overflow. */
5752 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5753 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5754
5755 /* Address family configuration mismatch. */
d62a17ae 5756 if (ret < 0)
513386b5 5757 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5758 }
5759
5760 /* Packet length consistency check. */
5761 if (pnt != lim) {
af4c2728 5762 flog_err(
e50f7cfd 5763 EC_BGP_UPDATE_RCV,
d62a17ae 5764 "%s [Error] Update packet error (prefix length mismatch with total length)",
5765 peer->host);
513386b5 5766 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5767 }
6b0655a2 5768
513386b5 5769 return BGP_NLRI_PARSE_OK;
718e3744 5770}
5771
d62a17ae 5772static struct bgp_static *bgp_static_new(void)
718e3744 5773{
d62a17ae 5774 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5775}
5776
d62a17ae 5777static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5778{
0a22ddfb 5779 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5780 route_map_counter_decrement(bgp_static->rmap.map);
5781
0a22ddfb 5782 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5783 XFREE(MTYPE_BGP_STATIC, bgp_static);
5784}
5785
5f040085 5786void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5787 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5788{
9bcb3eef 5789 struct bgp_dest *dest;
40381db7 5790 struct bgp_path_info *pi;
4b7e6066 5791 struct bgp_path_info *new;
40381db7 5792 struct bgp_path_info rmap_path;
d62a17ae 5793 struct attr attr;
5794 struct attr *attr_new;
b68885f9 5795 route_map_result_t ret;
49e5a4a0 5796#ifdef ENABLE_BGP_VNC
d62a17ae 5797 int vnc_implicit_withdraw = 0;
65efcfce 5798#endif
fee0f4c6 5799
d62a17ae 5800 assert(bgp_static);
dd8103a9 5801
9bcb3eef 5802 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5803
d62a17ae 5804 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5805
d62a17ae 5806 attr.nexthop = bgp_static->igpnexthop;
5807 attr.med = bgp_static->igpmetric;
5808 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5809
d62a17ae 5810 if (bgp_static->atomic)
5811 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5812
d62a17ae 5813 /* Store label index, if required. */
5814 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5815 attr.label_index = bgp_static->label_index;
5816 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5817 }
718e3744 5818
d62a17ae 5819 /* Apply route-map. */
5820 if (bgp_static->rmap.name) {
5821 struct attr attr_tmp = attr;
80ced710 5822
40381db7
DS
5823 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5824 rmap_path.peer = bgp->peer_self;
5825 rmap_path.attr = &attr_tmp;
fee0f4c6 5826
d62a17ae 5827 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5828
1782514f 5829 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5830
d62a17ae 5831 bgp->peer_self->rmap_type = 0;
718e3744 5832
d62a17ae 5833 if (ret == RMAP_DENYMATCH) {
5834 /* Free uninterned attribute. */
5835 bgp_attr_flush(&attr_tmp);
718e3744 5836
d62a17ae 5837 /* Unintern original. */
5838 aspath_unintern(&attr.aspath);
5839 bgp_static_withdraw(bgp, p, afi, safi);
5840 return;
5841 }
7f323236 5842
637e5ba4 5843 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5844 bgp_attr_add_gshut_community(&attr_tmp);
5845
d62a17ae 5846 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5847 } else {
5848
637e5ba4 5849 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5850 bgp_attr_add_gshut_community(&attr);
5851
d62a17ae 5852 attr_new = bgp_attr_intern(&attr);
7f323236 5853 }
718e3744 5854
9bcb3eef 5855 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5856 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5857 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5858 break;
5859
40381db7
DS
5860 if (pi) {
5861 if (attrhash_cmp(pi->attr, attr_new)
5862 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5863 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5864 bgp_dest_unlock_node(dest);
d62a17ae 5865 bgp_attr_unintern(&attr_new);
5866 aspath_unintern(&attr.aspath);
5867 return;
5868 } else {
5869 /* The attribute is changed. */
9bcb3eef 5870 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5871
5872 /* Rewrite BGP route information. */
40381db7 5873 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5874 bgp_path_info_restore(dest, pi);
d62a17ae 5875 else
40381db7 5876 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5877#ifdef ENABLE_BGP_VNC
d62a17ae 5878 if ((afi == AFI_IP || afi == AFI_IP6)
5879 && (safi == SAFI_UNICAST)) {
40381db7 5880 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5881 /*
5882 * Implicit withdraw case.
40381db7 5883 * We have to do this before pi is
d62a17ae 5884 * changed
5885 */
5886 ++vnc_implicit_withdraw;
40381db7 5887 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5888 vnc_import_bgp_exterior_del_route(
40381db7 5889 bgp, p, pi);
d62a17ae 5890 }
5891 }
65efcfce 5892#endif
40381db7
DS
5893 bgp_attr_unintern(&pi->attr);
5894 pi->attr = attr_new;
5895 pi->uptime = bgp_clock();
49e5a4a0 5896#ifdef ENABLE_BGP_VNC
d62a17ae 5897 if ((afi == AFI_IP || afi == AFI_IP6)
5898 && (safi == SAFI_UNICAST)) {
5899 if (vnc_implicit_withdraw) {
40381db7 5900 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5901 vnc_import_bgp_exterior_add_route(
40381db7 5902 bgp, p, pi);
d62a17ae 5903 }
5904 }
65efcfce 5905#endif
718e3744 5906
d62a17ae 5907 /* Nexthop reachability check. */
892fedb6 5908 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5909 && (safi == SAFI_UNICAST
5910 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5911
5912 struct bgp *bgp_nexthop = bgp;
5913
40381db7
DS
5914 if (pi->extra && pi->extra->bgp_orig)
5915 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5916
5917 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5918 afi, safi, pi, NULL,
654a5978 5919 0, p))
9bcb3eef 5920 bgp_path_info_set_flag(dest, pi,
18ee8310 5921 BGP_PATH_VALID);
d62a17ae 5922 else {
5923 if (BGP_DEBUG(nht, NHT)) {
5924 char buf1[INET6_ADDRSTRLEN];
5925 inet_ntop(p->family,
5926 &p->u.prefix, buf1,
5927 INET6_ADDRSTRLEN);
5928 zlog_debug(
5929 "%s(%s): Route not in table, not advertising",
15569c58 5930 __func__, buf1);
d62a17ae 5931 }
18ee8310 5932 bgp_path_info_unset_flag(
9bcb3eef 5933 dest, pi, BGP_PATH_VALID);
d62a17ae 5934 }
5935 } else {
5936 /* Delete the NHT structure if any, if we're
5937 * toggling between
5938 * enabling/disabling import check. We
5939 * deregister the route
5940 * from NHT to avoid overloading NHT and the
5941 * process interaction
5942 */
40381db7 5943 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5944 bgp_path_info_set_flag(dest, pi,
5945 BGP_PATH_VALID);
d62a17ae 5946 }
5947 /* Process change. */
40381db7 5948 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5949 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5950
5951 if (SAFI_UNICAST == safi
5952 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5953 || bgp->inst_type
5954 == BGP_INSTANCE_TYPE_DEFAULT)) {
5955 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5956 pi);
ddb5b488
PZ
5957 }
5958
9bcb3eef 5959 bgp_dest_unlock_node(dest);
d62a17ae 5960 aspath_unintern(&attr.aspath);
5961 return;
5962 }
718e3744 5963 }
718e3744 5964
d62a17ae 5965 /* Make new BGP info. */
5966 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5967 attr_new, dest);
d62a17ae 5968 /* Nexthop reachability check. */
892fedb6 5969 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5970 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5971 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5972 p))
9bcb3eef 5973 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5974 else {
5975 if (BGP_DEBUG(nht, NHT)) {
5976 char buf1[INET6_ADDRSTRLEN];
5977 inet_ntop(p->family, &p->u.prefix, buf1,
5978 INET6_ADDRSTRLEN);
5979 zlog_debug(
5980 "%s(%s): Route not in table, not advertising",
15569c58 5981 __func__, buf1);
d62a17ae 5982 }
9bcb3eef 5983 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5984 }
5985 } else {
5986 /* Delete the NHT structure if any, if we're toggling between
5987 * enabling/disabling import check. We deregister the route
5988 * from NHT to avoid overloading NHT and the process interaction
5989 */
5990 bgp_unlink_nexthop(new);
5991
9bcb3eef 5992 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5993 }
078430f6 5994
d62a17ae 5995 /* Aggregate address increment. */
5996 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5997
d62a17ae 5998 /* Register new BGP information. */
9bcb3eef 5999 bgp_path_info_add(dest, new);
718e3744 6000
d62a17ae 6001 /* route_node_get lock */
9bcb3eef 6002 bgp_dest_unlock_node(dest);
d62a17ae 6003
6004 /* Process change. */
9bcb3eef 6005 bgp_process(bgp, dest, afi, safi);
d62a17ae 6006
ddb5b488
PZ
6007 if (SAFI_UNICAST == safi
6008 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6009 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6010 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6011 }
6012
d62a17ae 6013 /* Unintern original. */
6014 aspath_unintern(&attr.aspath);
718e3744 6015}
6016
5f040085 6017void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6018 safi_t safi)
718e3744 6019{
9bcb3eef 6020 struct bgp_dest *dest;
40381db7 6021 struct bgp_path_info *pi;
718e3744 6022
9bcb3eef 6023 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6024
d62a17ae 6025 /* Check selected route and self inserted route. */
9bcb3eef 6026 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6027 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6028 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6029 break;
6030
6031 /* Withdraw static BGP route from routing table. */
40381db7 6032 if (pi) {
ddb5b488
PZ
6033 if (SAFI_UNICAST == safi
6034 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6035 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6036 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6037 }
40381db7
DS
6038 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6039 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6040 bgp_path_info_delete(dest, pi);
6041 bgp_process(bgp, dest, afi, safi);
d62a17ae 6042 }
718e3744 6043
d62a17ae 6044 /* Unlock bgp_node_lookup. */
9bcb3eef 6045 bgp_dest_unlock_node(dest);
718e3744 6046}
6047
137446f9
LB
6048/*
6049 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6050 */
5f040085 6051static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6052 afi_t afi, safi_t safi,
6053 struct prefix_rd *prd)
718e3744 6054{
9bcb3eef 6055 struct bgp_dest *dest;
40381db7 6056 struct bgp_path_info *pi;
718e3744 6057
9bcb3eef 6058 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6059
d62a17ae 6060 /* Check selected route and self inserted route. */
9bcb3eef 6061 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6062 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6063 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6064 break;
718e3744 6065
d62a17ae 6066 /* Withdraw static BGP route from routing table. */
40381db7 6067 if (pi) {
49e5a4a0 6068#ifdef ENABLE_BGP_VNC
d62a17ae 6069 rfapiProcessWithdraw(
40381db7 6070 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6071 1); /* Kill, since it is an administrative change */
65efcfce 6072#endif
ddb5b488
PZ
6073 if (SAFI_MPLS_VPN == safi
6074 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6075 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6076 }
40381db7 6077 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6078 bgp_path_info_delete(dest, pi);
6079 bgp_process(bgp, dest, afi, safi);
d62a17ae 6080 }
718e3744 6081
d62a17ae 6082 /* Unlock bgp_node_lookup. */
9bcb3eef 6083 bgp_dest_unlock_node(dest);
718e3744 6084}
6085
5f040085 6086static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6087 struct bgp_static *bgp_static, afi_t afi,
6088 safi_t safi)
137446f9 6089{
9bcb3eef 6090 struct bgp_dest *dest;
4b7e6066 6091 struct bgp_path_info *new;
d62a17ae 6092 struct attr *attr_new;
6093 struct attr attr = {0};
40381db7 6094 struct bgp_path_info *pi;
49e5a4a0 6095#ifdef ENABLE_BGP_VNC
d62a17ae 6096 mpls_label_t label = 0;
65efcfce 6097#endif
d7c0a89a 6098 uint32_t num_labels = 0;
137446f9 6099
d62a17ae 6100 assert(bgp_static);
137446f9 6101
b57ba6d2
MK
6102 if (bgp_static->label != MPLS_INVALID_LABEL)
6103 num_labels = 1;
9bcb3eef
DS
6104 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6105 &bgp_static->prd);
137446f9 6106
d62a17ae 6107 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 6108
d62a17ae 6109 attr.nexthop = bgp_static->igpnexthop;
6110 attr.med = bgp_static->igpmetric;
6111 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6112
d62a17ae 6113 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6114 || (safi == SAFI_ENCAP)) {
6115 if (afi == AFI_IP) {
6116 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6117 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6118 }
6119 }
6120 if (afi == AFI_L2VPN) {
b04c1e99
IR
6121 if (bgp_static->gatewayIp.family == AF_INET) {
6122 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6123 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6124 &bgp_static->gatewayIp.u.prefix4,
6125 IPV4_MAX_BYTELEN);
b04c1e99
IR
6126 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6127 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6128 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6129 &bgp_static->gatewayIp.u.prefix6,
6130 IPV6_MAX_BYTELEN);
b04c1e99 6131 }
0a50c248 6132 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6133 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6134 struct bgp_encap_type_vxlan bet;
6135 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 6136 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6137 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6138 }
6139 if (bgp_static->router_mac) {
6140 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6141 }
6142 }
6143 /* Apply route-map. */
6144 if (bgp_static->rmap.name) {
6145 struct attr attr_tmp = attr;
40381db7 6146 struct bgp_path_info rmap_path;
b68885f9 6147 route_map_result_t ret;
137446f9 6148
40381db7
DS
6149 rmap_path.peer = bgp->peer_self;
6150 rmap_path.attr = &attr_tmp;
137446f9 6151
d62a17ae 6152 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6153
1782514f 6154 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6155
d62a17ae 6156 bgp->peer_self->rmap_type = 0;
137446f9 6157
d62a17ae 6158 if (ret == RMAP_DENYMATCH) {
6159 /* Free uninterned attribute. */
6160 bgp_attr_flush(&attr_tmp);
137446f9 6161
d62a17ae 6162 /* Unintern original. */
6163 aspath_unintern(&attr.aspath);
6164 bgp_static_withdraw_safi(bgp, p, afi, safi,
6165 &bgp_static->prd);
6166 return;
6167 }
137446f9 6168
d62a17ae 6169 attr_new = bgp_attr_intern(&attr_tmp);
6170 } else {
6171 attr_new = bgp_attr_intern(&attr);
6172 }
137446f9 6173
9bcb3eef 6174 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6175 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6176 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6177 break;
6178
40381db7 6179 if (pi) {
40381db7 6180 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6181 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6182 bgp_dest_unlock_node(dest);
d62a17ae 6183 bgp_attr_unintern(&attr_new);
6184 aspath_unintern(&attr.aspath);
6185 return;
6186 } else {
6187 /* The attribute is changed. */
9bcb3eef 6188 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6189
6190 /* Rewrite BGP route information. */
40381db7 6191 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6192 bgp_path_info_restore(dest, pi);
d62a17ae 6193 else
40381db7
DS
6194 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6195 bgp_attr_unintern(&pi->attr);
6196 pi->attr = attr_new;
6197 pi->uptime = bgp_clock();
49e5a4a0 6198#ifdef ENABLE_BGP_VNC
40381db7
DS
6199 if (pi->extra)
6200 label = decode_label(&pi->extra->label[0]);
65efcfce 6201#endif
137446f9 6202
d62a17ae 6203 /* Process change. */
40381db7 6204 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6205 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6206
6207 if (SAFI_MPLS_VPN == safi
6208 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6209 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6210 }
49e5a4a0 6211#ifdef ENABLE_BGP_VNC
40381db7
DS
6212 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6213 pi->attr, afi, safi, pi->type,
6214 pi->sub_type, &label);
65efcfce 6215#endif
9bcb3eef 6216 bgp_dest_unlock_node(dest);
d62a17ae 6217 aspath_unintern(&attr.aspath);
6218 return;
6219 }
6220 }
137446f9
LB
6221
6222
d62a17ae 6223 /* Make new BGP info. */
6224 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6225 attr_new, dest);
1defdda8 6226 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6227 bgp_path_info_extra_get(new);
b57ba6d2
MK
6228 if (num_labels) {
6229 new->extra->label[0] = bgp_static->label;
6230 new->extra->num_labels = num_labels;
6231 }
49e5a4a0 6232#ifdef ENABLE_BGP_VNC
d62a17ae 6233 label = decode_label(&bgp_static->label);
65efcfce 6234#endif
137446f9 6235
d62a17ae 6236 /* Aggregate address increment. */
6237 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6238
d62a17ae 6239 /* Register new BGP information. */
9bcb3eef 6240 bgp_path_info_add(dest, new);
d62a17ae 6241 /* route_node_get lock */
9bcb3eef 6242 bgp_dest_unlock_node(dest);
137446f9 6243
d62a17ae 6244 /* Process change. */
9bcb3eef 6245 bgp_process(bgp, dest, afi, safi);
137446f9 6246
ddb5b488
PZ
6247 if (SAFI_MPLS_VPN == safi
6248 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6249 vpn_leak_to_vrf_update(bgp, new);
6250 }
49e5a4a0 6251#ifdef ENABLE_BGP_VNC
d62a17ae 6252 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6253 safi, new->type, new->sub_type, &label);
65efcfce
LB
6254#endif
6255
d62a17ae 6256 /* Unintern original. */
6257 aspath_unintern(&attr.aspath);
137446f9
LB
6258}
6259
718e3744 6260/* Configure static BGP network. When user don't run zebra, static
6261 route should be installed as valid. */
585f1adc
IR
6262static int bgp_static_set(struct vty *vty, const char *negate,
6263 const char *ip_str, afi_t afi, safi_t safi,
6264 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6265{
585f1adc
IR
6266 VTY_DECLVAR_CONTEXT(bgp, bgp);
6267 int ret;
d62a17ae 6268 struct prefix p;
6269 struct bgp_static *bgp_static;
9bcb3eef 6270 struct bgp_dest *dest;
d7c0a89a 6271 uint8_t need_update = 0;
d62a17ae 6272
585f1adc
IR
6273 /* Convert IP prefix string to struct prefix. */
6274 ret = str2prefix(ip_str, &p);
6275 if (!ret) {
6276 vty_out(vty, "%% Malformed prefix\n");
6277 return CMD_WARNING_CONFIG_FAILED;
6278 }
6279 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6280 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6281 return CMD_WARNING_CONFIG_FAILED;
6282 }
6283
d62a17ae 6284 apply_mask(&p);
718e3744 6285
e2a86ad9 6286 if (negate) {
718e3744 6287
e2a86ad9 6288 /* Set BGP static route configuration. */
9bcb3eef 6289 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6290
9bcb3eef 6291 if (!dest) {
585f1adc
IR
6292 vty_out(vty, "%% Can't find static route specified\n");
6293 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6294 }
6295
9bcb3eef 6296 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6297
e2a86ad9
DS
6298 if ((label_index != BGP_INVALID_LABEL_INDEX)
6299 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6300 vty_out(vty,
6301 "%% label-index doesn't match static route\n");
70d9b134 6302 bgp_dest_unlock_node(dest);
585f1adc 6303 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6304 }
d62a17ae 6305
e2a86ad9
DS
6306 if ((rmap && bgp_static->rmap.name)
6307 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6308 vty_out(vty,
6309 "%% route-map name doesn't match static route\n");
70d9b134 6310 bgp_dest_unlock_node(dest);
585f1adc 6311 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6312 }
718e3744 6313
e2a86ad9
DS
6314 /* Update BGP RIB. */
6315 if (!bgp_static->backdoor)
6316 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6317
e2a86ad9
DS
6318 /* Clear configuration. */
6319 bgp_static_free(bgp_static);
9bcb3eef
DS
6320 bgp_dest_set_bgp_static_info(dest, NULL);
6321 bgp_dest_unlock_node(dest);
6322 bgp_dest_unlock_node(dest);
e2a86ad9 6323 } else {
718e3744 6324
e2a86ad9 6325 /* Set BGP static route configuration. */
9bcb3eef
DS
6326 dest = bgp_node_get(bgp->route[afi][safi], &p);
6327 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6328 if (bgp_static) {
e2a86ad9 6329 /* Configuration change. */
e2a86ad9
DS
6330 /* Label index cannot be changed. */
6331 if (bgp_static->label_index != label_index) {
585f1adc
IR
6332 vty_out(vty, "%% cannot change label-index\n");
6333 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6334 }
d62a17ae 6335
e2a86ad9 6336 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6337 if (bgp_static->valid
6338 && bgp_static->backdoor != backdoor)
e2a86ad9 6339 need_update = 1;
718e3744 6340
e2a86ad9 6341 bgp_static->backdoor = backdoor;
718e3744 6342
e2a86ad9 6343 if (rmap) {
0a22ddfb
QY
6344 XFREE(MTYPE_ROUTE_MAP_NAME,
6345 bgp_static->rmap.name);
b4897fa5 6346 route_map_counter_decrement(
6347 bgp_static->rmap.map);
e2a86ad9
DS
6348 bgp_static->rmap.name =
6349 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6350 bgp_static->rmap.map =
6351 route_map_lookup_by_name(rmap);
b4897fa5 6352 route_map_counter_increment(
6353 bgp_static->rmap.map);
e2a86ad9 6354 } else {
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.map = NULL;
6360 bgp_static->valid = 0;
6361 }
9bcb3eef 6362 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6363 } else {
6364 /* New configuration. */
6365 bgp_static = bgp_static_new();
6366 bgp_static->backdoor = backdoor;
6367 bgp_static->valid = 0;
6368 bgp_static->igpmetric = 0;
975a328e 6369 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6370 bgp_static->label_index = label_index;
718e3744 6371
e2a86ad9 6372 if (rmap) {
0a22ddfb
QY
6373 XFREE(MTYPE_ROUTE_MAP_NAME,
6374 bgp_static->rmap.name);
b4897fa5 6375 route_map_counter_decrement(
6376 bgp_static->rmap.map);
e2a86ad9
DS
6377 bgp_static->rmap.name =
6378 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6379 bgp_static->rmap.map =
6380 route_map_lookup_by_name(rmap);
b4897fa5 6381 route_map_counter_increment(
6382 bgp_static->rmap.map);
e2a86ad9 6383 }
9bcb3eef 6384 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6385 }
d62a17ae 6386
e2a86ad9
DS
6387 bgp_static->valid = 1;
6388 if (need_update)
6389 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6390
e2a86ad9
DS
6391 if (!bgp_static->backdoor)
6392 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6393 }
d62a17ae 6394
585f1adc 6395 return CMD_SUCCESS;
d62a17ae 6396}
6397
6398void bgp_static_add(struct bgp *bgp)
6399{
6400 afi_t afi;
6401 safi_t safi;
9bcb3eef
DS
6402 struct bgp_dest *dest;
6403 struct bgp_dest *rm;
d62a17ae 6404 struct bgp_table *table;
6405 struct bgp_static *bgp_static;
6406
47fc6261 6407 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6408 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6409 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6410 dest = bgp_route_next(dest)) {
6411 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6412 continue;
ea47320b 6413
05c7a1cc
QY
6414 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6415 || (safi == SAFI_EVPN)) {
9bcb3eef 6416 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6417
6418 for (rm = bgp_table_top(table); rm;
6419 rm = bgp_route_next(rm)) {
a78beeb5 6420 bgp_static =
9bcb3eef 6421 bgp_dest_get_bgp_static_info(
5a8ba9fc 6422 rm);
9bcb3eef
DS
6423 bgp_static_update_safi(
6424 bgp, bgp_dest_get_prefix(rm),
6425 bgp_static, afi, safi);
d62a17ae 6426 }
05c7a1cc 6427 } else {
5a8ba9fc 6428 bgp_static_update(
9bcb3eef
DS
6429 bgp, bgp_dest_get_prefix(dest),
6430 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6431 safi);
ea47320b 6432 }
05c7a1cc 6433 }
47fc6261 6434 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6435}
6436
718e3744 6437/* Called from bgp_delete(). Delete all static routes from the BGP
6438 instance. */
d62a17ae 6439void bgp_static_delete(struct bgp *bgp)
6440{
6441 afi_t afi;
6442 safi_t safi;
9bcb3eef
DS
6443 struct bgp_dest *dest;
6444 struct bgp_dest *rm;
d62a17ae 6445 struct bgp_table *table;
6446 struct bgp_static *bgp_static;
6447
05c7a1cc 6448 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6449 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6450 dest = bgp_route_next(dest)) {
6451 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6452 continue;
ea47320b 6453
05c7a1cc
QY
6454 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6455 || (safi == SAFI_EVPN)) {
9bcb3eef 6456 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6457
6458 for (rm = bgp_table_top(table); rm;
6459 rm = bgp_route_next(rm)) {
a78beeb5 6460 bgp_static =
9bcb3eef 6461 bgp_dest_get_bgp_static_info(
5a8ba9fc 6462 rm);
c7d14ba6
PG
6463 if (!bgp_static)
6464 continue;
6465
05c7a1cc 6466 bgp_static_withdraw_safi(
9bcb3eef 6467 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6468 AFI_IP, safi,
6469 (struct prefix_rd *)
9bcb3eef
DS
6470 bgp_dest_get_prefix(
6471 dest));
ea47320b 6472 bgp_static_free(bgp_static);
811c6797 6473 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6474 NULL);
811c6797 6475 bgp_dest_unlock_node(rm);
d62a17ae 6476 }
05c7a1cc 6477 } else {
9bcb3eef 6478 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6479 bgp_static_withdraw(bgp,
9bcb3eef 6480 bgp_dest_get_prefix(dest),
b54892e0 6481 afi, safi);
05c7a1cc 6482 bgp_static_free(bgp_static);
9bcb3eef
DS
6483 bgp_dest_set_bgp_static_info(dest, NULL);
6484 bgp_dest_unlock_node(dest);
ea47320b 6485 }
05c7a1cc 6486 }
d62a17ae 6487}
6488
6489void bgp_static_redo_import_check(struct bgp *bgp)
6490{
6491 afi_t afi;
6492 safi_t safi;
9bcb3eef
DS
6493 struct bgp_dest *dest;
6494 struct bgp_dest *rm;
d62a17ae 6495 struct bgp_table *table;
6496 struct bgp_static *bgp_static;
6497
6498 /* Use this flag to force reprocessing of the route */
892fedb6 6499 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6500 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6501 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6502 dest = bgp_route_next(dest)) {
6503 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6504 continue;
ea47320b 6505
05c7a1cc
QY
6506 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6507 || (safi == SAFI_EVPN)) {
9bcb3eef 6508 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6509
6510 for (rm = bgp_table_top(table); rm;
6511 rm = bgp_route_next(rm)) {
a78beeb5 6512 bgp_static =
9bcb3eef 6513 bgp_dest_get_bgp_static_info(
5a8ba9fc 6514 rm);
9bcb3eef
DS
6515 bgp_static_update_safi(
6516 bgp, bgp_dest_get_prefix(rm),
6517 bgp_static, afi, safi);
d62a17ae 6518 }
05c7a1cc 6519 } else {
9bcb3eef
DS
6520 bgp_static = bgp_dest_get_bgp_static_info(dest);
6521 bgp_static_update(bgp,
6522 bgp_dest_get_prefix(dest),
6523 bgp_static, afi, safi);
ea47320b 6524 }
05c7a1cc
QY
6525 }
6526 }
892fedb6 6527 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6528}
6529
6530static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6531 safi_t safi)
6532{
6533 struct bgp_table *table;
9bcb3eef 6534 struct bgp_dest *dest;
40381db7 6535 struct bgp_path_info *pi;
d62a17ae 6536
dfb6fd1d
NT
6537 /* Do not install the aggregate route if BGP is in the
6538 * process of termination.
6539 */
892fedb6
DA
6540 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6541 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6542 return;
6543
d62a17ae 6544 table = bgp->rib[afi][safi];
9bcb3eef
DS
6545 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6546 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6547 if (pi->peer == bgp->peer_self
6548 && ((pi->type == ZEBRA_ROUTE_BGP
6549 && pi->sub_type == BGP_ROUTE_STATIC)
6550 || (pi->type != ZEBRA_ROUTE_BGP
6551 && pi->sub_type
d62a17ae 6552 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6553 bgp_aggregate_decrement(
6554 bgp, bgp_dest_get_prefix(dest), pi, afi,
6555 safi);
40381db7 6556 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6557 bgp_path_info_delete(dest, pi);
6558 bgp_process(bgp, dest, afi, safi);
d62a17ae 6559 }
6560 }
6561 }
ad4cbda1 6562}
6563
6564/*
6565 * Purge all networks and redistributed routes from routing table.
6566 * Invoked upon the instance going down.
6567 */
d62a17ae 6568void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6569{
d62a17ae 6570 afi_t afi;
6571 safi_t safi;
ad4cbda1 6572
05c7a1cc
QY
6573 FOREACH_AFI_SAFI (afi, safi)
6574 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6575}
6576
137446f9
LB
6577/*
6578 * gpz 110624
6579 * Currently this is used to set static routes for VPN and ENCAP.
6580 * I think it can probably be factored with bgp_static_set.
6581 */
d62a17ae 6582int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6583 const char *ip_str, const char *rd_str,
6584 const char *label_str, const char *rmap_str,
6585 int evpn_type, const char *esi, const char *gwip,
6586 const char *ethtag, const char *routermac)
6587{
6588 VTY_DECLVAR_CONTEXT(bgp, bgp);
6589 int ret;
6590 struct prefix p;
6591 struct prefix_rd prd;
9bcb3eef
DS
6592 struct bgp_dest *pdest;
6593 struct bgp_dest *dest;
d62a17ae 6594 struct bgp_table *table;
6595 struct bgp_static *bgp_static;
6596 mpls_label_t label = MPLS_INVALID_LABEL;
6597 struct prefix gw_ip;
6598
6599 /* validate ip prefix */
6600 ret = str2prefix(ip_str, &p);
6601 if (!ret) {
6602 vty_out(vty, "%% Malformed prefix\n");
6603 return CMD_WARNING_CONFIG_FAILED;
6604 }
6605 apply_mask(&p);
6606 if ((afi == AFI_L2VPN)
6607 && (bgp_build_evpn_prefix(evpn_type,
6608 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6609 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6610 return CMD_WARNING_CONFIG_FAILED;
6611 }
718e3744 6612
d62a17ae 6613 ret = str2prefix_rd(rd_str, &prd);
6614 if (!ret) {
6615 vty_out(vty, "%% Malformed rd\n");
6616 return CMD_WARNING_CONFIG_FAILED;
6617 }
718e3744 6618
d62a17ae 6619 if (label_str) {
6620 unsigned long label_val;
6621 label_val = strtoul(label_str, NULL, 10);
6622 encode_label(label_val, &label);
6623 }
9bedbb1e 6624
d62a17ae 6625 if (safi == SAFI_EVPN) {
6626 if (esi && str2esi(esi, NULL) == 0) {
6627 vty_out(vty, "%% Malformed ESI\n");
6628 return CMD_WARNING_CONFIG_FAILED;
6629 }
6630 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6631 vty_out(vty, "%% Malformed Router MAC\n");
6632 return CMD_WARNING_CONFIG_FAILED;
6633 }
6634 if (gwip) {
6635 memset(&gw_ip, 0, sizeof(struct prefix));
6636 ret = str2prefix(gwip, &gw_ip);
6637 if (!ret) {
6638 vty_out(vty, "%% Malformed GatewayIp\n");
6639 return CMD_WARNING_CONFIG_FAILED;
6640 }
6641 if ((gw_ip.family == AF_INET
3714a385 6642 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6643 (struct prefix_evpn *)&p))
6644 || (gw_ip.family == AF_INET6
3714a385 6645 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6646 (struct prefix_evpn *)&p))) {
6647 vty_out(vty,
6648 "%% GatewayIp family differs with IP prefix\n");
6649 return CMD_WARNING_CONFIG_FAILED;
6650 }
6651 }
6652 }
9bcb3eef
DS
6653 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6654 if (!bgp_dest_has_bgp_path_info_data(pdest))
6655 bgp_dest_set_bgp_table_info(pdest,
67009e22 6656 bgp_table_init(bgp, afi, safi));
9bcb3eef 6657 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6658
9bcb3eef 6659 dest = bgp_node_get(table, &p);
d62a17ae 6660
9bcb3eef 6661 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6662 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6663 bgp_dest_unlock_node(dest);
d62a17ae 6664 } else {
6665 /* New configuration. */
6666 bgp_static = bgp_static_new();
6667 bgp_static->backdoor = 0;
6668 bgp_static->valid = 0;
6669 bgp_static->igpmetric = 0;
975a328e 6670 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6671 bgp_static->label = label;
6672 bgp_static->prd = prd;
6673
6674 if (rmap_str) {
0a22ddfb 6675 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6676 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6677 bgp_static->rmap.name =
6678 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6679 bgp_static->rmap.map =
6680 route_map_lookup_by_name(rmap_str);
b4897fa5 6681 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6682 }
718e3744 6683
d62a17ae 6684 if (safi == SAFI_EVPN) {
6685 if (esi) {
6686 bgp_static->eth_s_id =
6687 XCALLOC(MTYPE_ATTR,
0a50c248 6688 sizeof(esi_t));
d62a17ae 6689 str2esi(esi, bgp_static->eth_s_id);
6690 }
6691 if (routermac) {
6692 bgp_static->router_mac =
28328ea9 6693 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6694 (void)prefix_str2mac(routermac,
6695 bgp_static->router_mac);
d62a17ae 6696 }
6697 if (gwip)
6698 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6699 }
9bcb3eef 6700 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6701
d62a17ae 6702 bgp_static->valid = 1;
6703 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6704 }
718e3744 6705
d62a17ae 6706 return CMD_SUCCESS;
718e3744 6707}
6708
6709/* Configure static BGP network. */
d62a17ae 6710int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6711 const char *ip_str, const char *rd_str,
6712 const char *label_str, int evpn_type, const char *esi,
6713 const char *gwip, const char *ethtag)
6714{
6715 VTY_DECLVAR_CONTEXT(bgp, bgp);
6716 int ret;
6717 struct prefix p;
6718 struct prefix_rd prd;
9bcb3eef
DS
6719 struct bgp_dest *pdest;
6720 struct bgp_dest *dest;
d62a17ae 6721 struct bgp_table *table;
6722 struct bgp_static *bgp_static;
6723 mpls_label_t label = MPLS_INVALID_LABEL;
6724
6725 /* Convert IP prefix string to struct prefix. */
6726 ret = str2prefix(ip_str, &p);
6727 if (!ret) {
6728 vty_out(vty, "%% Malformed prefix\n");
6729 return CMD_WARNING_CONFIG_FAILED;
6730 }
6731 apply_mask(&p);
6732 if ((afi == AFI_L2VPN)
6733 && (bgp_build_evpn_prefix(evpn_type,
6734 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6735 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6736 return CMD_WARNING_CONFIG_FAILED;
6737 }
6738 ret = str2prefix_rd(rd_str, &prd);
6739 if (!ret) {
6740 vty_out(vty, "%% Malformed rd\n");
6741 return CMD_WARNING_CONFIG_FAILED;
6742 }
718e3744 6743
d62a17ae 6744 if (label_str) {
6745 unsigned long label_val;
6746 label_val = strtoul(label_str, NULL, 10);
6747 encode_label(label_val, &label);
6748 }
718e3744 6749
9bcb3eef
DS
6750 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6751 if (!bgp_dest_has_bgp_path_info_data(pdest))
6752 bgp_dest_set_bgp_table_info(pdest,
67009e22 6753 bgp_table_init(bgp, afi, safi));
d62a17ae 6754 else
9bcb3eef
DS
6755 bgp_dest_unlock_node(pdest);
6756 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6757
9bcb3eef 6758 dest = bgp_node_lookup(table, &p);
6b0655a2 6759
9bcb3eef 6760 if (dest) {
d62a17ae 6761 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6762
9bcb3eef 6763 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6764 bgp_static_free(bgp_static);
9bcb3eef
DS
6765 bgp_dest_set_bgp_static_info(dest, NULL);
6766 bgp_dest_unlock_node(dest);
6767 bgp_dest_unlock_node(dest);
d62a17ae 6768 } else
6769 vty_out(vty, "%% Can't find the route\n");
6770
6771 return CMD_SUCCESS;
6772}
6773
6774static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6775 const char *rmap_name)
6776{
6777 VTY_DECLVAR_CONTEXT(bgp, bgp);
6778 struct bgp_rmap *rmap;
6779
6780 rmap = &bgp->table_map[afi][safi];
6781 if (rmap_name) {
0a22ddfb 6782 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6783 route_map_counter_decrement(rmap->map);
d62a17ae 6784 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6785 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6786 route_map_counter_increment(rmap->map);
d62a17ae 6787 } else {
0a22ddfb 6788 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6789 route_map_counter_decrement(rmap->map);
d62a17ae 6790 rmap->map = NULL;
6791 }
73ac8160 6792
d62a17ae 6793 if (bgp_fibupd_safi(safi))
6794 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6795
d62a17ae 6796 return CMD_SUCCESS;
73ac8160
DS
6797}
6798
d62a17ae 6799static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6800 const char *rmap_name)
73ac8160 6801{
d62a17ae 6802 VTY_DECLVAR_CONTEXT(bgp, bgp);
6803 struct bgp_rmap *rmap;
73ac8160 6804
d62a17ae 6805 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6806 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6807 route_map_counter_decrement(rmap->map);
d62a17ae 6808 rmap->map = NULL;
73ac8160 6809
d62a17ae 6810 if (bgp_fibupd_safi(safi))
6811 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6812
d62a17ae 6813 return CMD_SUCCESS;
73ac8160
DS
6814}
6815
2b791107 6816void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6817 safi_t safi)
73ac8160 6818{
d62a17ae 6819 if (bgp->table_map[afi][safi].name) {
d62a17ae 6820 vty_out(vty, " table-map %s\n",
6821 bgp->table_map[afi][safi].name);
6822 }
73ac8160
DS
6823}
6824
73ac8160
DS
6825DEFUN (bgp_table_map,
6826 bgp_table_map_cmd,
6827 "table-map WORD",
6828 "BGP table to RIB route download filter\n"
6829 "Name of the route map\n")
6830{
d62a17ae 6831 int idx_word = 1;
6832 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6833 argv[idx_word]->arg);
73ac8160
DS
6834}
6835DEFUN (no_bgp_table_map,
6836 no_bgp_table_map_cmd,
6837 "no table-map WORD",
3a2d747c 6838 NO_STR
73ac8160
DS
6839 "BGP table to RIB route download filter\n"
6840 "Name of the route map\n")
6841{
d62a17ae 6842 int idx_word = 2;
6843 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6844 argv[idx_word]->arg);
73ac8160
DS
6845}
6846
585f1adc
IR
6847DEFPY(bgp_network,
6848 bgp_network_cmd,
6849 "[no] network \
6850 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6851 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6852 backdoor$backdoor}]",
6853 NO_STR
6854 "Specify a network to announce via BGP\n"
6855 "IPv4 prefix\n"
6856 "Network number\n"
6857 "Network mask\n"
6858 "Network mask\n"
6859 "Route-map to modify the attributes\n"
6860 "Name of the route map\n"
6861 "Label index to associate with the prefix\n"
6862 "Label index value\n"
6863 "Specify a BGP backdoor route\n")
6864{
6865 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6866
6867 if (address_str) {
6868 int ret;
718e3744 6869
e2a86ad9 6870 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6871 addr_prefix_str,
6872 sizeof(addr_prefix_str));
e2a86ad9
DS
6873 if (!ret) {
6874 vty_out(vty, "%% Inconsistent address and mask\n");
6875 return CMD_WARNING_CONFIG_FAILED;
6876 }
d62a17ae 6877 }
718e3744 6878
585f1adc
IR
6879 return bgp_static_set(
6880 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6881 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6882 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6883}
6884
585f1adc
IR
6885DEFPY(ipv6_bgp_network,
6886 ipv6_bgp_network_cmd,
6887 "[no] network X:X::X:X/M$prefix \
6888 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6889 NO_STR
6890 "Specify a network to announce via BGP\n"
6891 "IPv6 prefix\n"
6892 "Route-map to modify the attributes\n"
6893 "Name of the route map\n"
6894 "Label index to associate with the prefix\n"
6895 "Label index value\n")
37a87b8f 6896{
585f1adc
IR
6897 return bgp_static_set(
6898 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6899 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6900}
6901
d62a17ae 6902static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6903{
d62a17ae 6904 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6905}
6906
d62a17ae 6907static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6908{
365ab2e7
RZ
6909 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6910 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6911 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6912 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6913 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6914}
718e3744 6915
365ab2e7
RZ
6916/**
6917 * Helper function to avoid repeated code: prepare variables for a
6918 * `route_map_apply` call.
6919 *
6920 * \returns `true` on route map match, otherwise `false`.
6921 */
6922static bool aggr_suppress_map_test(struct bgp *bgp,
6923 struct bgp_aggregate *aggregate,
6924 struct bgp_path_info *pi)
6925{
6926 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6927 route_map_result_t rmr = RMAP_DENYMATCH;
6928 struct bgp_path_info rmap_path = {};
6929 struct attr attr = {};
6930
6931 /* No route map entries created, just don't match. */
6932 if (aggregate->suppress_map == NULL)
6933 return false;
6934
6935 /* Call route map matching and return result. */
6936 attr.aspath = aspath_empty();
6937 rmap_path.peer = bgp->peer_self;
6938 rmap_path.attr = &attr;
6939
6940 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6941 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6942 bgp->peer_self->rmap_type = 0;
6943
6944 bgp_attr_flush(&attr);
6945
6946 return rmr == RMAP_PERMITMATCH;
6947}
6948
4056a5f6
RZ
6949/** Test whether the aggregation has suppressed this path or not. */
6950static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6951 struct bgp_path_info *pi)
6952{
6953 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6954 return false;
6955
6956 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6957}
6958
6959/**
6960 * Suppress this path and keep the reference.
6961 *
6962 * \returns `true` if needs processing otherwise `false`.
6963 */
6964static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6965 struct bgp_path_info *pi)
6966{
6967 struct bgp_path_info_extra *pie;
6968
6969 /* Path is already suppressed by this aggregation. */
6970 if (aggr_suppress_exists(aggregate, pi))
6971 return false;
6972
6973 pie = bgp_path_info_extra_get(pi);
6974
6975 /* This is the first suppression, allocate memory and list it. */
6976 if (pie->aggr_suppressors == NULL)
6977 pie->aggr_suppressors = list_new();
6978
6979 listnode_add(pie->aggr_suppressors, aggregate);
6980
6981 /* Only mark for processing if suppressed. */
6982 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6983 if (BGP_DEBUG(update, UPDATE_OUT))
6984 zlog_debug("aggregate-address suppressing: %pFX",
6985 bgp_dest_get_prefix(pi->net));
6986
4056a5f6
RZ
6987 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6988 return true;
6989 }
6990
6991 return false;
6992}
6993
6994/**
6995 * Unsuppress this path and remove the reference.
6996 *
6997 * \returns `true` if needs processing otherwise `false`.
6998 */
6999static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7000 struct bgp_path_info *pi)
7001{
7002 /* Path wasn't suppressed. */
7003 if (!aggr_suppress_exists(aggregate, pi))
7004 return false;
7005
7006 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7007
7008 /* Unsuppress and free extra memory if last item. */
7009 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7010 if (BGP_DEBUG(update, UPDATE_OUT))
7011 zlog_debug("aggregate-address unsuppressing: %pFX",
7012 bgp_dest_get_prefix(pi->net));
7013
4056a5f6
RZ
7014 list_delete(&pi->extra->aggr_suppressors);
7015 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7016 return true;
7017 }
7018
7019 return false;
7020}
7021
3dc339cd
DA
7022static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7023 struct aspath *aspath,
7024 struct community *comm,
7025 struct ecommunity *ecomm,
7026 struct lcommunity *lcomm)
eaaf8adb
DS
7027{
7028 static struct aspath *ae = NULL;
7029
7030 if (!ae)
7031 ae = aspath_empty();
7032
40381db7 7033 if (!pi)
3dc339cd 7034 return false;
eaaf8adb 7035
40381db7 7036 if (origin != pi->attr->origin)
3dc339cd 7037 return false;
eaaf8adb 7038
40381db7 7039 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7040 return false;
29f7d023 7041
40381db7 7042 if (!community_cmp(pi->attr->community, comm))
3dc339cd 7043 return false;
eaaf8adb 7044
b53e67a3 7045 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7046 return false;
eaaf8adb 7047
dd18c5a9 7048 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 7049 return false;
dd18c5a9 7050
40381db7 7051 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7052 return false;
7ce8a8e0 7053
3dc339cd 7054 return true;
eaaf8adb
DS
7055}
7056
5f040085
DS
7057static void bgp_aggregate_install(
7058 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7059 uint8_t origin, struct aspath *aspath, struct community *community,
7060 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7061 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7062{
9bcb3eef 7063 struct bgp_dest *dest;
c701010e 7064 struct bgp_table *table;
6f94b685 7065 struct bgp_path_info *pi, *orig, *new;
20894f50 7066 struct attr *attr;
c701010e
DS
7067
7068 table = bgp->rib[afi][safi];
7069
9bcb3eef 7070 dest = bgp_node_get(table, p);
eaaf8adb 7071
9bcb3eef 7072 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7073 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7074 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7075 break;
7076
6aabb15d
RZ
7077 /*
7078 * If we have paths with different MEDs, then don't install
7079 * (or uninstall) the aggregate route.
7080 */
7081 if (aggregate->match_med && aggregate->med_mismatched)
7082 goto uninstall_aggregate_route;
7083
c701010e 7084 if (aggregate->count > 0) {
eaaf8adb
DS
7085 /*
7086 * If the aggregate information has not changed
7087 * no need to re-install it again.
7088 */
6f94b685 7089 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7090 ecommunity, lcommunity)) {
9bcb3eef 7091 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7092
7093 if (aspath)
7094 aspath_free(aspath);
7095 if (community)
3c1f53de 7096 community_free(&community);
3da2cc32
DS
7097 if (ecommunity)
7098 ecommunity_free(&ecommunity);
dd18c5a9
DS
7099 if (lcommunity)
7100 lcommunity_free(&lcommunity);
eaaf8adb
DS
7101
7102 return;
7103 }
7104
7105 /*
7106 * Mark the old as unusable
7107 */
40381db7 7108 if (pi)
9bcb3eef 7109 bgp_path_info_delete(dest, pi);
eaaf8adb 7110
20894f50
DA
7111 attr = bgp_attr_aggregate_intern(
7112 bgp, origin, aspath, community, ecommunity, lcommunity,
7113 aggregate, atomic_aggregate, p);
7114
7115 if (!attr) {
7116 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7117 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7118 zlog_debug("%s: %pFX null attribute", __func__,
7119 p);
20894f50
DA
7120 return;
7121 }
7122
3da2cc32 7123 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7124 bgp->peer_self, attr, dest);
20894f50 7125
1defdda8 7126 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7127
9bcb3eef
DS
7128 bgp_path_info_add(dest, new);
7129 bgp_process(bgp, dest, afi, safi);
c701010e 7130 } else {
6aabb15d 7131 uninstall_aggregate_route:
6f94b685 7132 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7133 if (pi->peer == bgp->peer_self
7134 && pi->type == ZEBRA_ROUTE_BGP
7135 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7136 break;
7137
7138 /* Withdraw static BGP route from routing table. */
40381db7 7139 if (pi) {
9bcb3eef
DS
7140 bgp_path_info_delete(dest, pi);
7141 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7142 }
7143 }
7144
9bcb3eef 7145 bgp_dest_unlock_node(dest);
c701010e
DS
7146}
7147
6aabb15d
RZ
7148/**
7149 * Check if the current path has different MED than other known paths.
7150 *
7151 * \returns `true` if the MED matched the others else `false`.
7152 */
7153static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7154 struct bgp *bgp, struct bgp_path_info *pi)
7155{
7156 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7157
7158 /* This is the first route being analyzed. */
7159 if (!aggregate->med_initialized) {
7160 aggregate->med_initialized = true;
7161 aggregate->med_mismatched = false;
7162 aggregate->med_matched_value = cur_med;
7163 } else {
7164 /* Check if routes with different MED showed up. */
7165 if (cur_med != aggregate->med_matched_value)
7166 aggregate->med_mismatched = true;
7167 }
7168
7169 return !aggregate->med_mismatched;
7170}
7171
7172/**
7173 * Initializes and tests all routes in the aggregate address path for MED
7174 * values.
7175 *
7176 * \returns `true` if all MEDs are the same otherwise `false`.
7177 */
7178static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7179 struct bgp *bgp, const struct prefix *p,
7180 afi_t afi, safi_t safi)
7181{
7182 struct bgp_table *table = bgp->rib[afi][safi];
7183 const struct prefix *dest_p;
7184 struct bgp_dest *dest, *top;
7185 struct bgp_path_info *pi;
7186 bool med_matched = true;
7187
7188 aggregate->med_initialized = false;
7189
7190 top = bgp_node_get(table, p);
7191 for (dest = bgp_node_get(table, p); dest;
7192 dest = bgp_route_next_until(dest, top)) {
7193 dest_p = bgp_dest_get_prefix(dest);
7194 if (dest_p->prefixlen <= p->prefixlen)
7195 continue;
7196
7197 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7198 if (BGP_PATH_HOLDDOWN(pi))
7199 continue;
7200 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7201 continue;
7202 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7203 med_matched = false;
7204 break;
7205 }
7206 }
7207 if (!med_matched)
7208 break;
7209 }
7210 bgp_dest_unlock_node(top);
7211
7212 return med_matched;
7213}
7214
7215/**
7216 * Toggles the route suppression status for this aggregate address
7217 * configuration.
7218 */
4056a5f6
RZ
7219void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7220 struct bgp *bgp, const struct prefix *p,
7221 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7222{
7223 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7224 const struct prefix *dest_p;
7225 struct bgp_dest *dest, *top;
7226 struct bgp_path_info *pi;
7227 bool toggle_suppression;
7228
7229 /* We've found a different MED we must revert any suppressed routes. */
7230 top = bgp_node_get(table, p);
7231 for (dest = bgp_node_get(table, p); dest;
7232 dest = bgp_route_next_until(dest, top)) {
7233 dest_p = bgp_dest_get_prefix(dest);
7234 if (dest_p->prefixlen <= p->prefixlen)
7235 continue;
7236
7237 toggle_suppression = false;
7238 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7239 if (BGP_PATH_HOLDDOWN(pi))
7240 continue;
7241 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7242 continue;
7243
6aabb15d
RZ
7244 /* We are toggling suppression back. */
7245 if (suppress) {
6aabb15d 7246 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7247 if (aggr_suppress_path(aggregate, pi))
7248 toggle_suppression = true;
6aabb15d
RZ
7249 continue;
7250 }
7251
6aabb15d 7252 /* Install route if there is no more suppression. */
4056a5f6 7253 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7254 toggle_suppression = true;
6aabb15d
RZ
7255 }
7256
7257 if (toggle_suppression)
7258 bgp_process(bgp, dest, afi, safi);
7259 }
7260 bgp_dest_unlock_node(top);
7261}
7262
7263/**
7264 * Aggregate address MED matching incremental test: this function is called
7265 * when the initial aggregation occurred and we are only testing a single
7266 * new path.
7267 *
7268 * In addition to testing and setting the MED validity it also installs back
7269 * suppressed routes (if summary is configured).
7270 *
7271 * Must not be called in `bgp_aggregate_route`.
7272 */
7273static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7274 struct bgp *bgp, const struct prefix *p,
7275 afi_t afi, safi_t safi,
7276 struct bgp_path_info *pi, bool is_adding)
7277{
7278 /* MED matching disabled. */
7279 if (!aggregate->match_med)
7280 return;
7281
7282 /* Aggregation with different MED, nothing to do. */
7283 if (aggregate->med_mismatched)
7284 return;
7285
7286 /*
7287 * Test the current entry:
7288 *
7289 * is_adding == true: if the new entry doesn't match then we must
7290 * install all suppressed routes.
7291 *
7292 * is_adding == false: if the entry being removed was the last
7293 * unmatching entry then we can suppress all routes.
7294 */
7295 if (!is_adding) {
7296 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7297 && aggregate->summary_only)
7298 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7299 safi, true);
7300 } else
7301 bgp_aggregate_med_match(aggregate, bgp, pi);
7302
7303 /* No mismatches, just quit. */
7304 if (!aggregate->med_mismatched)
7305 return;
7306
7307 /* Route summarization is disabled. */
7308 if (!aggregate->summary_only)
7309 return;
7310
7311 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7312}
7313
b5d58c32 7314/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7315void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7316 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7317{
7318 struct bgp_table *table;
9bcb3eef
DS
7319 struct bgp_dest *top;
7320 struct bgp_dest *dest;
d7c0a89a 7321 uint8_t origin;
d62a17ae 7322 struct aspath *aspath = NULL;
d62a17ae 7323 struct community *community = NULL;
3da2cc32 7324 struct ecommunity *ecommunity = NULL;
dd18c5a9 7325 struct lcommunity *lcommunity = NULL;
40381db7 7326 struct bgp_path_info *pi;
d62a17ae 7327 unsigned long match = 0;
d7c0a89a 7328 uint8_t atomic_aggregate = 0;
d62a17ae 7329
9f822fa2
S
7330 /* If the bgp instance is being deleted or self peer is deleted
7331 * then do not create aggregate route
7332 */
892fedb6
DA
7333 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7334 || (bgp->peer_self == NULL))
9f822fa2
S
7335 return;
7336
6aabb15d
RZ
7337 /* Initialize and test routes for MED difference. */
7338 if (aggregate->match_med)
7339 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7340
4056a5f6
RZ
7341 /*
7342 * Reset aggregate count: we might've been called from route map
7343 * update so in that case we must retest all more specific routes.
7344 *
7345 * \see `bgp_route_map_process_update`.
7346 */
7347 aggregate->count = 0;
7348 aggregate->incomplete_origin_count = 0;
7349 aggregate->incomplete_origin_count = 0;
7350 aggregate->egp_origin_count = 0;
7351
d62a17ae 7352 /* ORIGIN attribute: If at least one route among routes that are
7353 aggregated has ORIGIN with the value INCOMPLETE, then the
7354 aggregated route must have the ORIGIN attribute with the value
7355 INCOMPLETE. Otherwise, if at least one route among routes that
7356 are aggregated has ORIGIN with the value EGP, then the aggregated
7357 route must have the origin attribute with the value EGP. In all
7358 other case the value of the ORIGIN attribute of the aggregated
7359 route is INTERNAL. */
7360 origin = BGP_ORIGIN_IGP;
718e3744 7361
d62a17ae 7362 table = bgp->rib[afi][safi];
718e3744 7363
d62a17ae 7364 top = bgp_node_get(table, p);
9bcb3eef
DS
7365 for (dest = bgp_node_get(table, p); dest;
7366 dest = bgp_route_next_until(dest, top)) {
7367 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7368
9bcb3eef 7369 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7370 continue;
d62a17ae 7371
a77e2f4b
S
7372 /* If suppress fib is enabled and route not installed
7373 * in FIB, skip the route
7374 */
7375 if (!bgp_check_advertise(bgp, dest))
7376 continue;
7377
c2ff8b3e 7378 match = 0;
d62a17ae 7379
9bcb3eef 7380 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7381 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7382 continue;
718e3744 7383
40381db7 7384 if (pi->attr->flag
c2ff8b3e
DS
7385 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7386 atomic_aggregate = 1;
d62a17ae 7387
40381db7 7388 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7389 continue;
d62a17ae 7390
f273fef1
DS
7391 /*
7392 * summary-only aggregate route suppress
7393 * aggregated route announcements.
6aabb15d
RZ
7394 *
7395 * MED matching:
7396 * Don't create summaries if MED didn't match
7397 * otherwise neither the specific routes and the
7398 * aggregation will be announced.
f273fef1 7399 */
6aabb15d
RZ
7400 if (aggregate->summary_only
7401 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7402 if (aggr_suppress_path(aggregate, pi))
7403 match++;
d62a17ae 7404 }
c2ff8b3e 7405
365ab2e7
RZ
7406 /*
7407 * Suppress more specific routes that match the route
7408 * map results.
7409 *
7410 * MED matching:
7411 * Don't suppress routes if MED matching is enabled and
7412 * it mismatched otherwise we might end up with no
7413 * routes for this path.
7414 */
7415 if (aggregate->suppress_map_name
7416 && AGGREGATE_MED_VALID(aggregate)
7417 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7418 if (aggr_suppress_path(aggregate, pi))
7419 match++;
d62a17ae 7420 }
c2ff8b3e
DS
7421
7422 aggregate->count++;
7423
f273fef1
DS
7424 /*
7425 * If at least one route among routes that are
7426 * aggregated has ORIGIN with the value INCOMPLETE,
7427 * then the aggregated route MUST have the ORIGIN
7428 * attribute with the value INCOMPLETE. Otherwise, if
7429 * at least one route among routes that are aggregated
7430 * has ORIGIN with the value EGP, then the aggregated
7431 * route MUST have the ORIGIN attribute with the value
7432 * EGP.
7433 */
fc968841
NT
7434 switch (pi->attr->origin) {
7435 case BGP_ORIGIN_INCOMPLETE:
7436 aggregate->incomplete_origin_count++;
7437 break;
7438 case BGP_ORIGIN_EGP:
7439 aggregate->egp_origin_count++;
7440 break;
7441 default:
7442 /*Do nothing.
7443 */
7444 break;
7445 }
c2ff8b3e
DS
7446
7447 if (!aggregate->as_set)
7448 continue;
7449
f273fef1
DS
7450 /*
7451 * as-set aggregate route generate origin, as path,
7452 * and community aggregation.
7453 */
fc968841
NT
7454 /* Compute aggregate route's as-path.
7455 */
ef51a7d8 7456 bgp_compute_aggregate_aspath_hash(aggregate,
7457 pi->attr->aspath);
c2ff8b3e 7458
fc968841
NT
7459 /* Compute aggregate route's community.
7460 */
7461 if (pi->attr->community)
21fec674 7462 bgp_compute_aggregate_community_hash(
fc968841
NT
7463 aggregate,
7464 pi->attr->community);
dd18c5a9 7465
fc968841
NT
7466 /* Compute aggregate route's extended community.
7467 */
b53e67a3 7468 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7469 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7470 aggregate,
7471 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7472
7473 /* Compute aggregate route's large community.
7474 */
7475 if (pi->attr->lcommunity)
f1eb1f05 7476 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7477 aggregate,
7478 pi->attr->lcommunity);
d62a17ae 7479 }
c2ff8b3e 7480 if (match)
9bcb3eef 7481 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7482 }
21fec674 7483 if (aggregate->as_set) {
ef51a7d8 7484 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7485 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7486 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7487 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7488 }
7489
f1eb1f05 7490
9bcb3eef 7491 bgp_dest_unlock_node(top);
718e3744 7492
718e3744 7493
fc968841
NT
7494 if (aggregate->incomplete_origin_count > 0)
7495 origin = BGP_ORIGIN_INCOMPLETE;
7496 else if (aggregate->egp_origin_count > 0)
7497 origin = BGP_ORIGIN_EGP;
d62a17ae 7498
229757f1
DA
7499 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7500 origin = aggregate->origin;
7501
fc968841
NT
7502 if (aggregate->as_set) {
7503 if (aggregate->aspath)
7504 /* Retrieve aggregate route's as-path.
7505 */
7506 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7507
fc968841
NT
7508 if (aggregate->community)
7509 /* Retrieve aggregate route's community.
7510 */
7511 community = community_dup(aggregate->community);
3da2cc32 7512
fc968841
NT
7513 if (aggregate->ecommunity)
7514 /* Retrieve aggregate route's ecommunity.
7515 */
7516 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7517
fc968841
NT
7518 if (aggregate->lcommunity)
7519 /* Retrieve aggregate route's lcommunity.
7520 */
7521 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7522 }
718e3744 7523
c701010e 7524 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7525 ecommunity, lcommunity, atomic_aggregate,
7526 aggregate);
718e3744 7527}
7528
5f040085
DS
7529void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7530 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7531{
7532 struct bgp_table *table;
9bcb3eef
DS
7533 struct bgp_dest *top;
7534 struct bgp_dest *dest;
40381db7 7535 struct bgp_path_info *pi;
3b7db173
DS
7536 unsigned long match;
7537
7538 table = bgp->rib[afi][safi];
7539
7540 /* If routes exists below this node, generate aggregate routes. */
7541 top = bgp_node_get(table, p);
9bcb3eef
DS
7542 for (dest = bgp_node_get(table, p); dest;
7543 dest = bgp_route_next_until(dest, top)) {
7544 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7545
9bcb3eef 7546 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7547 continue;
7548 match = 0;
7549
9bcb3eef 7550 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7551 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7552 continue;
7553
40381db7 7554 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7555 continue;
7556
92b175bd
RZ
7557 /*
7558 * This route is suppressed: attempt to unsuppress it.
7559 *
7560 * `aggr_unsuppress_path` will fail if this particular
7561 * aggregate route was not the suppressor.
7562 */
7563 if (pi->extra && pi->extra->aggr_suppressors &&
7564 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7565 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7566 match++;
3b7db173 7567 }
365ab2e7 7568
3b7db173 7569 aggregate->count--;
fc968841
NT
7570
7571 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7572 aggregate->incomplete_origin_count--;
7573 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7574 aggregate->egp_origin_count--;
7575
7576 if (aggregate->as_set) {
7577 /* Remove as-path from aggregate.
7578 */
ef51a7d8 7579 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7580 aggregate,
7581 pi->attr->aspath);
7582
7583 if (pi->attr->community)
7584 /* Remove community from aggregate.
7585 */
21fec674 7586 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7587 aggregate,
7588 pi->attr->community);
7589
b53e67a3 7590 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7591 /* Remove ecommunity from aggregate.
7592 */
4edd83f9 7593 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7594 aggregate,
7595 bgp_attr_get_ecommunity(
7596 pi->attr));
fc968841
NT
7597
7598 if (pi->attr->lcommunity)
7599 /* Remove lcommunity from aggregate.
7600 */
f1eb1f05 7601 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7602 aggregate,
7603 pi->attr->lcommunity);
7604 }
3b7db173
DS
7605 }
7606
7607 /* If this node was suppressed, process the change. */
7608 if (match)
9bcb3eef 7609 bgp_process(bgp, dest, afi, safi);
3b7db173 7610 }
f1eb1f05 7611 if (aggregate->as_set) {
ef51a7d8 7612 aspath_free(aggregate->aspath);
7613 aggregate->aspath = NULL;
21fec674 7614 if (aggregate->community)
7615 community_free(&aggregate->community);
4edd83f9 7616 if (aggregate->ecommunity)
7617 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7618 if (aggregate->lcommunity)
7619 lcommunity_free(&aggregate->lcommunity);
7620 }
7621
9bcb3eef 7622 bgp_dest_unlock_node(top);
3b7db173 7623}
718e3744 7624
5f040085
DS
7625static void bgp_add_route_to_aggregate(struct bgp *bgp,
7626 const struct prefix *aggr_p,
fc968841
NT
7627 struct bgp_path_info *pinew, afi_t afi,
7628 safi_t safi,
7629 struct bgp_aggregate *aggregate)
7630{
7631 uint8_t origin;
7632 struct aspath *aspath = NULL;
7633 uint8_t atomic_aggregate = 0;
7634 struct community *community = NULL;
7635 struct ecommunity *ecommunity = NULL;
7636 struct lcommunity *lcommunity = NULL;
7637
a4559740 7638 /* If the bgp instance is being deleted or self peer is deleted
7639 * then do not create aggregate route
7640 */
7641 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7642 || (bgp->peer_self == NULL))
7643 return;
7644
fc968841
NT
7645 /* ORIGIN attribute: If at least one route among routes that are
7646 * aggregated has ORIGIN with the value INCOMPLETE, then the
7647 * aggregated route must have the ORIGIN attribute with the value
7648 * INCOMPLETE. Otherwise, if at least one route among routes that
7649 * are aggregated has ORIGIN with the value EGP, then the aggregated
7650 * route must have the origin attribute with the value EGP. In all
7651 * other case the value of the ORIGIN attribute of the aggregated
7652 * route is INTERNAL.
7653 */
7654 origin = BGP_ORIGIN_IGP;
7655
7656 aggregate->count++;
7657
6aabb15d
RZ
7658 /*
7659 * This must be called before `summary` check to avoid
7660 * "suppressing" twice.
7661 */
7662 if (aggregate->match_med)
7663 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7664 pinew, true);
7665
7666 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7667 aggr_suppress_path(aggregate, pinew);
fc968841 7668
365ab2e7
RZ
7669 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7670 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7671 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7672
7673 switch (pinew->attr->origin) {
7674 case BGP_ORIGIN_INCOMPLETE:
7675 aggregate->incomplete_origin_count++;
7676 break;
7677 case BGP_ORIGIN_EGP:
7678 aggregate->egp_origin_count++;
7679 break;
7680 default:
7681 /* Do nothing.
7682 */
7683 break;
7684 }
7685
7686 if (aggregate->incomplete_origin_count > 0)
7687 origin = BGP_ORIGIN_INCOMPLETE;
7688 else if (aggregate->egp_origin_count > 0)
7689 origin = BGP_ORIGIN_EGP;
7690
229757f1
DA
7691 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7692 origin = aggregate->origin;
7693
fc968841
NT
7694 if (aggregate->as_set) {
7695 /* Compute aggregate route's as-path.
7696 */
7697 bgp_compute_aggregate_aspath(aggregate,
7698 pinew->attr->aspath);
7699
7700 /* Compute aggregate route's community.
7701 */
7702 if (pinew->attr->community)
7703 bgp_compute_aggregate_community(
7704 aggregate,
7705 pinew->attr->community);
7706
7707 /* Compute aggregate route's extended community.
7708 */
b53e67a3 7709 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7710 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7711 aggregate,
7712 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7713
7714 /* Compute aggregate route's large community.
7715 */
7716 if (pinew->attr->lcommunity)
7717 bgp_compute_aggregate_lcommunity(
7718 aggregate,
7719 pinew->attr->lcommunity);
7720
7721 /* Retrieve aggregate route's as-path.
7722 */
7723 if (aggregate->aspath)
7724 aspath = aspath_dup(aggregate->aspath);
7725
7726 /* Retrieve aggregate route's community.
7727 */
7728 if (aggregate->community)
7729 community = community_dup(aggregate->community);
7730
7731 /* Retrieve aggregate route's ecommunity.
7732 */
7733 if (aggregate->ecommunity)
7734 ecommunity = ecommunity_dup(aggregate->ecommunity);
7735
7736 /* Retrieve aggregate route's lcommunity.
7737 */
7738 if (aggregate->lcommunity)
7739 lcommunity = lcommunity_dup(aggregate->lcommunity);
7740 }
7741
7742 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7743 aspath, community, ecommunity,
7744 lcommunity, atomic_aggregate, aggregate);
7745}
7746
7747static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7748 safi_t safi,
7749 struct bgp_path_info *pi,
7750 struct bgp_aggregate *aggregate,
5f040085 7751 const struct prefix *aggr_p)
fc968841
NT
7752{
7753 uint8_t origin;
7754 struct aspath *aspath = NULL;
7755 uint8_t atomic_aggregate = 0;
7756 struct community *community = NULL;
7757 struct ecommunity *ecommunity = NULL;
7758 struct lcommunity *lcommunity = NULL;
7759 unsigned long match = 0;
7760
a4559740 7761 /* If the bgp instance is being deleted or self peer is deleted
7762 * then do not create aggregate route
7763 */
7764 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7765 || (bgp->peer_self == NULL))
7766 return;
7767
fc968841
NT
7768 if (BGP_PATH_HOLDDOWN(pi))
7769 return;
7770
7771 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7772 return;
7773
4056a5f6
RZ
7774 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7775 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7776 match++;
fc968841 7777
365ab2e7 7778 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7779 && aggr_suppress_map_test(bgp, aggregate, pi))
7780 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7781 match++;
fc968841 7782
6aabb15d 7783 /*
365ab2e7 7784 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7785 * "unsuppressing" twice.
7786 */
7787 if (aggregate->match_med)
7788 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7789 true);
7790
fc968841
NT
7791 if (aggregate->count > 0)
7792 aggregate->count--;
7793
7794 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7795 aggregate->incomplete_origin_count--;
7796 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7797 aggregate->egp_origin_count--;
7798
7799 if (aggregate->as_set) {
7800 /* Remove as-path from aggregate.
7801 */
7802 bgp_remove_aspath_from_aggregate(aggregate,
7803 pi->attr->aspath);
7804
7805 if (pi->attr->community)
7806 /* Remove community from aggregate.
7807 */
7808 bgp_remove_community_from_aggregate(
7809 aggregate,
7810 pi->attr->community);
7811
b53e67a3 7812 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7813 /* Remove ecommunity from aggregate.
7814 */
7815 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7816 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7817
7818 if (pi->attr->lcommunity)
7819 /* Remove lcommunity from aggregate.
7820 */
7821 bgp_remove_lcommunity_from_aggregate(
7822 aggregate,
7823 pi->attr->lcommunity);
7824 }
7825
7826 /* If this node was suppressed, process the change. */
7827 if (match)
7828 bgp_process(bgp, pi->net, afi, safi);
7829
7830 origin = BGP_ORIGIN_IGP;
7831 if (aggregate->incomplete_origin_count > 0)
7832 origin = BGP_ORIGIN_INCOMPLETE;
7833 else if (aggregate->egp_origin_count > 0)
7834 origin = BGP_ORIGIN_EGP;
7835
229757f1
DA
7836 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7837 origin = aggregate->origin;
7838
fc968841
NT
7839 if (aggregate->as_set) {
7840 /* Retrieve aggregate route's as-path.
7841 */
7842 if (aggregate->aspath)
7843 aspath = aspath_dup(aggregate->aspath);
7844
7845 /* Retrieve aggregate route's community.
7846 */
7847 if (aggregate->community)
7848 community = community_dup(aggregate->community);
7849
7850 /* Retrieve aggregate route's ecommunity.
7851 */
7852 if (aggregate->ecommunity)
7853 ecommunity = ecommunity_dup(aggregate->ecommunity);
7854
7855 /* Retrieve aggregate route's lcommunity.
7856 */
7857 if (aggregate->lcommunity)
7858 lcommunity = lcommunity_dup(aggregate->lcommunity);
7859 }
7860
7861 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7862 aspath, community, ecommunity,
7863 lcommunity, atomic_aggregate, aggregate);
7864}
7865
5a1ae2c2 7866void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7867 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7868{
9bcb3eef
DS
7869 struct bgp_dest *child;
7870 struct bgp_dest *dest;
d62a17ae 7871 struct bgp_aggregate *aggregate;
7872 struct bgp_table *table;
718e3744 7873
d62a17ae 7874 table = bgp->aggregate[afi][safi];
f018db83 7875
d62a17ae 7876 /* No aggregates configured. */
7877 if (bgp_table_top_nolock(table) == NULL)
7878 return;
f018db83 7879
d62a17ae 7880 if (p->prefixlen == 0)
7881 return;
718e3744 7882
40381db7 7883 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7884 return;
718e3744 7885
a77e2f4b
S
7886 /* If suppress fib is enabled and route not installed
7887 * in FIB, do not update the aggregate route
7888 */
7889 if (!bgp_check_advertise(bgp, pi->net))
7890 return;
7891
d62a17ae 7892 child = bgp_node_get(table, p);
718e3744 7893
d62a17ae 7894 /* Aggregate address configuration check. */
9bcb3eef
DS
7895 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7896 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7897
9bcb3eef
DS
7898 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7899 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7900 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7901 aggregate);
d62a17ae 7902 }
b1e62edd 7903 }
9bcb3eef 7904 bgp_dest_unlock_node(child);
718e3744 7905}
7906
5a1ae2c2 7907void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7908 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7909{
9bcb3eef
DS
7910 struct bgp_dest *child;
7911 struct bgp_dest *dest;
d62a17ae 7912 struct bgp_aggregate *aggregate;
7913 struct bgp_table *table;
718e3744 7914
d62a17ae 7915 table = bgp->aggregate[afi][safi];
718e3744 7916
d62a17ae 7917 /* No aggregates configured. */
7918 if (bgp_table_top_nolock(table) == NULL)
7919 return;
718e3744 7920
d62a17ae 7921 if (p->prefixlen == 0)
7922 return;
718e3744 7923
d62a17ae 7924 child = bgp_node_get(table, p);
718e3744 7925
d62a17ae 7926 /* Aggregate address configuration check. */
9bcb3eef
DS
7927 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7928 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7929
9bcb3eef
DS
7930 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7931 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7932 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7933 aggregate, dest_p);
d62a17ae 7934 }
b1e62edd 7935 }
9bcb3eef 7936 bgp_dest_unlock_node(child);
d62a17ae 7937}
718e3744 7938
718e3744 7939/* Aggregate route attribute. */
7940#define AGGREGATE_SUMMARY_ONLY 1
7941#define AGGREGATE_AS_SET 1
fb29348a 7942#define AGGREGATE_AS_UNSET 0
718e3744 7943
229757f1
DA
7944static const char *bgp_origin2str(uint8_t origin)
7945{
7946 switch (origin) {
7947 case BGP_ORIGIN_IGP:
7948 return "igp";
7949 case BGP_ORIGIN_EGP:
7950 return "egp";
7951 case BGP_ORIGIN_INCOMPLETE:
7952 return "incomplete";
7953 }
7954 return "n/a";
7955}
7956
fdeb5a81 7957static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7958{
7959 switch (v_state) {
fdeb5a81
DS
7960 case RPKI_NOT_BEING_USED:
7961 return "not used";
7962 case RPKI_VALID:
b5b99af8 7963 return "valid";
fdeb5a81 7964 case RPKI_NOTFOUND:
b5b99af8 7965 return "not found";
fdeb5a81 7966 case RPKI_INVALID:
b5b99af8 7967 return "invalid";
b5b99af8 7968 }
fdeb5a81
DS
7969
7970 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7971 return "ERROR";
7972}
7973
585f1adc
IR
7974static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7975 afi_t afi, safi_t safi)
718e3744 7976{
585f1adc
IR
7977 VTY_DECLVAR_CONTEXT(bgp, bgp);
7978 int ret;
7979 struct prefix p;
9bcb3eef 7980 struct bgp_dest *dest;
d62a17ae 7981 struct bgp_aggregate *aggregate;
718e3744 7982
585f1adc
IR
7983 /* Convert string to prefix structure. */
7984 ret = str2prefix(prefix_str, &p);
7985 if (!ret) {
7986 vty_out(vty, "Malformed prefix\n");
7987 return CMD_WARNING_CONFIG_FAILED;
7988 }
7989 apply_mask(&p);
a4559740 7990
d62a17ae 7991 /* Old configuration check. */
585f1adc 7992 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 7993 if (!dest) {
585f1adc
IR
7994 vty_out(vty,
7995 "%% There is no aggregate-address configuration.\n");
7996 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 7997 }
f6269b4f 7998
9bcb3eef 7999 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8000 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8001 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8002 NULL, NULL, 0, aggregate);
d62a17ae 8003
8004 /* Unlock aggregate address configuration. */
9bcb3eef 8005 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8006
8007 if (aggregate->community)
8008 community_free(&aggregate->community);
8009
8010 if (aggregate->community_hash) {
8011 /* Delete all communities in the hash.
8012 */
8013 hash_clean(aggregate->community_hash,
8014 bgp_aggr_community_remove);
8015 /* Free up the community_hash.
8016 */
8017 hash_free(aggregate->community_hash);
8018 }
8019
8020 if (aggregate->ecommunity)
8021 ecommunity_free(&aggregate->ecommunity);
8022
8023 if (aggregate->ecommunity_hash) {
8024 /* Delete all ecommunities in the hash.
8025 */
8026 hash_clean(aggregate->ecommunity_hash,
8027 bgp_aggr_ecommunity_remove);
8028 /* Free up the ecommunity_hash.
8029 */
8030 hash_free(aggregate->ecommunity_hash);
8031 }
8032
8033 if (aggregate->lcommunity)
8034 lcommunity_free(&aggregate->lcommunity);
8035
8036 if (aggregate->lcommunity_hash) {
8037 /* Delete all lcommunities in the hash.
8038 */
8039 hash_clean(aggregate->lcommunity_hash,
8040 bgp_aggr_lcommunity_remove);
8041 /* Free up the lcommunity_hash.
8042 */
8043 hash_free(aggregate->lcommunity_hash);
8044 }
8045
8046 if (aggregate->aspath)
8047 aspath_free(aggregate->aspath);
8048
8049 if (aggregate->aspath_hash) {
8050 /* Delete all as-paths in the hash.
8051 */
8052 hash_clean(aggregate->aspath_hash,
8053 bgp_aggr_aspath_remove);
8054 /* Free up the aspath_hash.
8055 */
8056 hash_free(aggregate->aspath_hash);
8057 }
8058
d62a17ae 8059 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8060 bgp_dest_unlock_node(dest);
8061 bgp_dest_unlock_node(dest);
d62a17ae 8062
585f1adc 8063 return CMD_SUCCESS;
d62a17ae 8064}
8065
585f1adc
IR
8066static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8067 safi_t safi, const char *rmap,
8068 uint8_t summary_only, uint8_t as_set,
8069 uint8_t origin, bool match_med,
8070 const char *suppress_map)
d62a17ae 8071{
585f1adc 8072 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8073 int ret;
585f1adc 8074 struct prefix p;
9bcb3eef 8075 struct bgp_dest *dest;
d62a17ae 8076 struct bgp_aggregate *aggregate;
fb29348a 8077 uint8_t as_set_new = as_set;
d62a17ae 8078
365ab2e7 8079 if (suppress_map && summary_only) {
585f1adc 8080 vty_out(vty,
365ab2e7 8081 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8082 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8083 }
8084
585f1adc
IR
8085 /* Convert string to prefix structure. */
8086 ret = str2prefix(prefix_str, &p);
8087 if (!ret) {
8088 vty_out(vty, "Malformed prefix\n");
8089 return CMD_WARNING_CONFIG_FAILED;
8090 }
8091 apply_mask(&p);
d62a17ae 8092
585f1adc
IR
8093 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8094 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8095 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8096 prefix_str);
8097 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8098 }
8099
d62a17ae 8100 /* Old configuration check. */
585f1adc 8101 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8102 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8103
20894f50 8104 if (aggregate) {
585f1adc 8105 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8106 /* try to remove the old entry */
585f1adc 8107 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8108 if (ret) {
585f1adc 8109 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8110 bgp_dest_unlock_node(dest);
585f1adc 8111 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8112 }
8113 }
718e3744 8114
d62a17ae 8115 /* Make aggregate address structure. */
8116 aggregate = bgp_aggregate_new();
8117 aggregate->summary_only = summary_only;
6aabb15d 8118 aggregate->match_med = match_med;
fb29348a
DA
8119
8120 /* Network operators MUST NOT locally generate any new
8121 * announcements containing AS_SET or AS_CONFED_SET. If they have
8122 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8123 * SHOULD withdraw those routes and re-announce routes for the
8124 * aggregate or component prefixes (i.e., the more-specific routes
8125 * subsumed by the previously aggregated route) without AS_SET
8126 * or AS_CONFED_SET in the updates.
8127 */
7f972cd8 8128 if (bgp->reject_as_sets) {
fb29348a
DA
8129 if (as_set == AGGREGATE_AS_SET) {
8130 as_set_new = AGGREGATE_AS_UNSET;
8131 zlog_warn(
63efca0e 8132 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8133 __func__);
585f1adc 8134 vty_out(vty,
fb29348a
DA
8135 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8136 }
8137 }
8138
8139 aggregate->as_set = as_set_new;
d62a17ae 8140 aggregate->safi = safi;
229757f1
DA
8141 /* Override ORIGIN attribute if defined.
8142 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8143 * to IGP which is not what rfc4271 says.
8144 * This enables the same behavior, optionally.
8145 */
8146 aggregate->origin = origin;
20894f50
DA
8147
8148 if (rmap) {
8149 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8150 route_map_counter_decrement(aggregate->rmap.map);
8151 aggregate->rmap.name =
8152 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8153 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8154 route_map_counter_increment(aggregate->rmap.map);
8155 }
365ab2e7
RZ
8156
8157 if (suppress_map) {
8158 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8159 route_map_counter_decrement(aggregate->suppress_map);
8160
8161 aggregate->suppress_map_name =
8162 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8163 aggregate->suppress_map =
8164 route_map_lookup_by_name(aggregate->suppress_map_name);
8165 route_map_counter_increment(aggregate->suppress_map);
8166 }
8167
9bcb3eef 8168 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8169
d62a17ae 8170 /* Aggregate address insert into BGP routing table. */
585f1adc 8171 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8172
585f1adc 8173 return CMD_SUCCESS;
718e3744 8174}
8175
585f1adc
IR
8176DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8177 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8178 "as-set$as_set_s"
8179 "|summary-only$summary_only"
8180 "|route-map WORD$rmap_name"
8181 "|origin <egp|igp|incomplete>$origin_s"
8182 "|matching-MED-only$match_med"
8183 "|suppress-map WORD$suppress_map"
8184 "}]",
8185 NO_STR
8186 "Configure BGP aggregate entries\n"
8187 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
8188 "Generate AS set path information\n"
8189 "Filter more specific routes from updates\n"
8190 "Apply route map to aggregate network\n"
8191 "Route map name\n"
8192 "BGP origin code\n"
8193 "Remote EGP\n"
8194 "Local IGP\n"
8195 "Unknown heritage\n"
8196 "Only aggregate routes with matching MED\n"
8197 "Suppress the selected more specific routes\n"
8198 "Route map with the route selectors\n")
8199{
8200 const char *prefix_s = NULL;
554b3b10 8201 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8202 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8203 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8204 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8205
554b3b10 8206 if (addr_str) {
7533cad7
QY
8207 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8208 sizeof(prefix_buf))
554b3b10
RZ
8209 == 0) {
8210 vty_out(vty, "%% Inconsistent address and mask\n");
8211 return CMD_WARNING_CONFIG_FAILED;
8212 }
585f1adc
IR
8213 prefix_s = prefix_buf;
8214 } else
8215 prefix_s = prefix_str;
37a87b8f 8216
585f1adc
IR
8217 if (origin_s) {
8218 if (strcmp(origin_s, "egp") == 0)
8219 origin = BGP_ORIGIN_EGP;
8220 else if (strcmp(origin_s, "igp") == 0)
8221 origin = BGP_ORIGIN_IGP;
8222 else if (strcmp(origin_s, "incomplete") == 0)
8223 origin = BGP_ORIGIN_INCOMPLETE;
8224 }
90e21f35 8225
585f1adc
IR
8226 if (as_set_s)
8227 as_set = AGGREGATE_AS_SET;
554b3b10 8228
585f1adc 8229 /* Handle configuration removal, otherwise installation. */
554b3b10 8230 if (no)
585f1adc
IR
8231 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8232
8233 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8234 summary_only != NULL, as_set, origin,
8235 match_med != NULL, suppress_map);
8236}
8237
8238DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8239 "[no] aggregate-address X:X::X:X/M$prefix [{"
8240 "as-set$as_set_s"
8241 "|summary-only$summary_only"
8242 "|route-map WORD$rmap_name"
8243 "|origin <egp|igp|incomplete>$origin_s"
8244 "|matching-MED-only$match_med"
8245 "|suppress-map WORD$suppress_map"
8246 "}]",
8247 NO_STR
8248 "Configure BGP aggregate entries\n"
8249 "Aggregate prefix\n"
8250 "Generate AS set path information\n"
8251 "Filter more specific routes from updates\n"
8252 "Apply route map to aggregate network\n"
8253 "Route map name\n"
8254 "BGP origin code\n"
8255 "Remote EGP\n"
8256 "Local IGP\n"
8257 "Unknown heritage\n"
8258 "Only aggregate routes with matching MED\n"
8259 "Suppress the selected more specific routes\n"
8260 "Route map with the route selectors\n")
8261{
8262 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8263 int as_set = AGGREGATE_AS_UNSET;
8264
8265 if (origin_s) {
8266 if (strcmp(origin_s, "egp") == 0)
8267 origin = BGP_ORIGIN_EGP;
8268 else if (strcmp(origin_s, "igp") == 0)
8269 origin = BGP_ORIGIN_IGP;
8270 else if (strcmp(origin_s, "incomplete") == 0)
8271 origin = BGP_ORIGIN_INCOMPLETE;
8272 }
8273
8274 if (as_set_s)
8275 as_set = AGGREGATE_AS_SET;
8276
8277 /* Handle configuration removal, otherwise installation. */
554b3b10 8278 if (no)
585f1adc
IR
8279 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8280 SAFI_UNICAST);
554b3b10 8281
585f1adc
IR
8282 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8283 rmap_name, summary_only != NULL, as_set,
8284 origin, match_med != NULL, suppress_map);
718e3744 8285}
8286
718e3744 8287/* Redistribute route treatment. */
d62a17ae 8288void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8289 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8290 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8291 enum blackhole_type bhtype, uint32_t metric,
8292 uint8_t type, unsigned short instance,
8293 route_tag_t tag)
d62a17ae 8294{
4b7e6066 8295 struct bgp_path_info *new;
40381db7
DS
8296 struct bgp_path_info *bpi;
8297 struct bgp_path_info rmap_path;
9bcb3eef 8298 struct bgp_dest *bn;
d62a17ae 8299 struct attr attr;
8300 struct attr *new_attr;
8301 afi_t afi;
b68885f9 8302 route_map_result_t ret;
d62a17ae 8303 struct bgp_redist *red;
8304
8305 /* Make default attribute. */
8306 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8307 /*
8308 * This must not be NULL to satisfy Coverity SA
8309 */
8310 assert(attr.aspath);
9de1f7ff 8311
a4d82a8a 8312 switch (nhtype) {
9de1f7ff
DS
8313 case NEXTHOP_TYPE_IFINDEX:
8314 break;
8315 case NEXTHOP_TYPE_IPV4:
8316 case NEXTHOP_TYPE_IPV4_IFINDEX:
8317 attr.nexthop = nexthop->ipv4;
8318 break;
8319 case NEXTHOP_TYPE_IPV6:
8320 case NEXTHOP_TYPE_IPV6_IFINDEX:
8321 attr.mp_nexthop_global = nexthop->ipv6;
8322 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8323 break;
8324 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8325 switch (p->family) {
8326 case AF_INET:
9de1f7ff 8327 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8328 break;
8329 case AF_INET6:
9de1f7ff
DS
8330 memset(&attr.mp_nexthop_global, 0,
8331 sizeof(attr.mp_nexthop_global));
74489921 8332 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8333 break;
74489921 8334 }
0789eb69 8335 attr.bh_type = bhtype;
9de1f7ff 8336 break;
d62a17ae 8337 }
0789eb69 8338 attr.nh_type = nhtype;
74489921 8339 attr.nh_ifindex = ifindex;
f04a80a5 8340
d62a17ae 8341 attr.med = metric;
957f74c3 8342 attr.distance = distance;
d62a17ae 8343 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8344 attr.tag = tag;
718e3744 8345
d62a17ae 8346 afi = family2afi(p->family);
6aeb9e78 8347
d62a17ae 8348 red = bgp_redist_lookup(bgp, afi, type, instance);
8349 if (red) {
8350 struct attr attr_new;
718e3744 8351
d62a17ae 8352 /* Copy attribute for modification. */
6f4f49b2 8353 attr_new = attr;
718e3744 8354
d62a17ae 8355 if (red->redist_metric_flag)
8356 attr_new.med = red->redist_metric;
718e3744 8357
d62a17ae 8358 /* Apply route-map. */
8359 if (red->rmap.name) {
40381db7
DS
8360 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8361 rmap_path.peer = bgp->peer_self;
8362 rmap_path.attr = &attr_new;
718e3744 8363
d62a17ae 8364 SET_FLAG(bgp->peer_self->rmap_type,
8365 PEER_RMAP_TYPE_REDISTRIBUTE);
8366
1782514f 8367 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8368
8369 bgp->peer_self->rmap_type = 0;
8370
8371 if (ret == RMAP_DENYMATCH) {
8372 /* Free uninterned attribute. */
8373 bgp_attr_flush(&attr_new);
8374
8375 /* Unintern original. */
8376 aspath_unintern(&attr.aspath);
8377 bgp_redistribute_delete(bgp, p, type, instance);
8378 return;
8379 }
8380 }
8381
637e5ba4 8382 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8383 bgp_attr_add_gshut_community(&attr_new);
8384
d62a17ae 8385 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8386 SAFI_UNICAST, p, NULL);
8387
8388 new_attr = bgp_attr_intern(&attr_new);
8389
9bcb3eef 8390 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8391 if (bpi->peer == bgp->peer_self
8392 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8393 break;
8394
40381db7 8395 if (bpi) {
d62a17ae 8396 /* Ensure the (source route) type is updated. */
40381db7
DS
8397 bpi->type = type;
8398 if (attrhash_cmp(bpi->attr, new_attr)
8399 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8400 bgp_attr_unintern(&new_attr);
8401 aspath_unintern(&attr.aspath);
9bcb3eef 8402 bgp_dest_unlock_node(bn);
d62a17ae 8403 return;
8404 } else {
8405 /* The attribute is changed. */
40381db7 8406 bgp_path_info_set_flag(bn, bpi,
18ee8310 8407 BGP_PATH_ATTR_CHANGED);
d62a17ae 8408
8409 /* Rewrite BGP route information. */
40381db7
DS
8410 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8411 bgp_path_info_restore(bn, bpi);
d62a17ae 8412 else
40381db7
DS
8413 bgp_aggregate_decrement(
8414 bgp, p, bpi, afi, SAFI_UNICAST);
8415 bgp_attr_unintern(&bpi->attr);
8416 bpi->attr = new_attr;
8417 bpi->uptime = bgp_clock();
d62a17ae 8418
8419 /* Process change. */
40381db7 8420 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8421 SAFI_UNICAST);
8422 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8423 bgp_dest_unlock_node(bn);
d62a17ae 8424 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8425
8426 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8427 || (bgp->inst_type
8428 == BGP_INSTANCE_TYPE_DEFAULT)) {
8429
8430 vpn_leak_from_vrf_update(
40381db7 8431 bgp_get_default(), bgp, bpi);
ddb5b488 8432 }
d62a17ae 8433 return;
8434 }
8435 }
8436
8437 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8438 bgp->peer_self, new_attr, bn);
1defdda8 8439 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8440
8441 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8442 bgp_path_info_add(bn, new);
9bcb3eef 8443 bgp_dest_unlock_node(bn);
be785e35 8444 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8445 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8446
8447 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8448 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8449
8450 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8451 }
d62a17ae 8452 }
8453
8454 /* Unintern original. */
8455 aspath_unintern(&attr.aspath);
718e3744 8456}
8457
d7c0a89a
QY
8458void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8459 unsigned short instance)
718e3744 8460{
d62a17ae 8461 afi_t afi;
9bcb3eef 8462 struct bgp_dest *dest;
40381db7 8463 struct bgp_path_info *pi;
d62a17ae 8464 struct bgp_redist *red;
718e3744 8465
d62a17ae 8466 afi = family2afi(p->family);
718e3744 8467
d62a17ae 8468 red = bgp_redist_lookup(bgp, afi, type, instance);
8469 if (red) {
9bcb3eef
DS
8470 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8471 SAFI_UNICAST, p, NULL);
d62a17ae 8472
9bcb3eef 8473 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8474 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8475 break;
8476
40381db7 8477 if (pi) {
ddb5b488
PZ
8478 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8479 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8480
8481 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8482 bgp, pi);
ddb5b488 8483 }
40381db7 8484 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8485 bgp_path_info_delete(dest, pi);
8486 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8487 }
9bcb3eef 8488 bgp_dest_unlock_node(dest);
d62a17ae 8489 }
8490}
8491
8492/* Withdraw specified route type's route. */
8493void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8494 unsigned short instance)
d62a17ae 8495{
9bcb3eef 8496 struct bgp_dest *dest;
40381db7 8497 struct bgp_path_info *pi;
d62a17ae 8498 struct bgp_table *table;
8499
8500 table = bgp->rib[afi][SAFI_UNICAST];
8501
9bcb3eef
DS
8502 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8503 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8504 if (pi->peer == bgp->peer_self && pi->type == type
8505 && pi->instance == instance)
d62a17ae 8506 break;
8507
40381db7 8508 if (pi) {
ddb5b488
PZ
8509 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8510 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8511
8512 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8513 bgp, pi);
ddb5b488 8514 }
9bcb3eef 8515 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8516 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8517 bgp_path_info_delete(dest, pi);
8518 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8519 }
718e3744 8520 }
718e3744 8521}
6b0655a2 8522
718e3744 8523/* Static function to display route. */
7d3cae70
DA
8524static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8525 struct vty *vty, json_object *json, bool wide)
718e3744 8526{
be054588 8527 int len = 0;
d62a17ae 8528 char buf[BUFSIZ];
718e3744 8529
d62a17ae 8530 if (p->family == AF_INET) {
c6462ff4 8531 if (!json) {
8228a9a7 8532 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8533 } else {
8534 json_object_string_add(json, "prefix",
8535 inet_ntop(p->family,
8536 &p->u.prefix, buf,
8537 BUFSIZ));
8538 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8539 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8540 json_object_int_add(json, "version", dest->version);
c6462ff4 8541 }
d62a17ae 8542 } else if (p->family == AF_ETHERNET) {
8228a9a7 8543 len = vty_out(vty, "%pFX", p);
b03b8898 8544 } else if (p->family == AF_EVPN) {
57f7feb6 8545 if (!json)
2dbe669b 8546 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8547 else
60466a63 8548 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8549 } else if (p->family == AF_FLOWSPEC) {
8550 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8551 json ?
8552 NLRI_STRING_FORMAT_JSON_SIMPLE :
8553 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8554 } else {
c6462ff4 8555 if (!json)
8228a9a7 8556 len = vty_out(vty, "%pFX", p);
50e05855
AD
8557 else {
8558 json_object_string_add(json, "prefix",
8559 inet_ntop(p->family,
8560 &p->u.prefix, buf,
8561 BUFSIZ));
8562 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8563 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8564 json_object_int_add(json, "version", dest->version);
37d4e0df 8565 }
9c92b5f7 8566 }
d62a17ae 8567
9c92b5f7 8568 if (!json) {
ae248832 8569 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8570 if (len < 1)
8571 vty_out(vty, "\n%*s", 20, " ");
8572 else
8573 vty_out(vty, "%*s", len, " ");
8574 }
718e3744 8575}
8576
d62a17ae 8577enum bgp_display_type {
8578 normal_list,
718e3744 8579};
8580
1d7260a1 8581const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8582{
8583 switch (reason) {
8584 case bgp_path_selection_none:
8585 return "Nothing to Select";
8586 case bgp_path_selection_first:
8587 return "First path received";
8588 case bgp_path_selection_evpn_sticky_mac:
8589 return "EVPN Sticky Mac";
8590 case bgp_path_selection_evpn_seq:
8591 return "EVPN sequence number";
8592 case bgp_path_selection_evpn_lower_ip:
8593 return "EVPN lower IP";
8594 case bgp_path_selection_evpn_local_path:
8595 return "EVPN local ES path";
8596 case bgp_path_selection_evpn_non_proxy:
8597 return "EVPN non proxy";
8598 case bgp_path_selection_weight:
8599 return "Weight";
8600 case bgp_path_selection_local_pref:
8601 return "Local Pref";
8602 case bgp_path_selection_local_route:
8603 return "Local Route";
8604 case bgp_path_selection_confed_as_path:
8605 return "Confederation based AS Path";
8606 case bgp_path_selection_as_path:
8607 return "AS Path";
8608 case bgp_path_selection_origin:
8609 return "Origin";
8610 case bgp_path_selection_med:
8611 return "MED";
8612 case bgp_path_selection_peer:
8613 return "Peer Type";
8614 case bgp_path_selection_confed:
8615 return "Confed Peer Type";
8616 case bgp_path_selection_igp_metric:
8617 return "IGP Metric";
8618 case bgp_path_selection_older:
8619 return "Older Path";
8620 case bgp_path_selection_router_id:
8621 return "Router ID";
8622 case bgp_path_selection_cluster_length:
bcab253c 8623 return "Cluster length";
bbb46eb5
DA
8624 case bgp_path_selection_stale:
8625 return "Path Staleness";
8626 case bgp_path_selection_local_configured:
8627 return "Locally configured route";
8628 case bgp_path_selection_neighbor_ip:
8629 return "Neighbor IP";
8630 case bgp_path_selection_default:
8631 return "Nothing left to compare";
8632 }
8633 return "Invalid (internal error)";
8634}
8635
18ee8310 8636/* Print the short form route status for a bgp_path_info */
4b7e6066 8637static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8638 struct bgp_path_info *path,
82c298be 8639 const struct prefix *p,
d62a17ae 8640 json_object *json_path)
718e3744 8641{
82c298be
DA
8642 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8643
d62a17ae 8644 if (json_path) {
b05a1c8b 8645
d62a17ae 8646 /* Route status display. */
9b6d8fcf 8647 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8648 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8649
9b6d8fcf 8650 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8651 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8652
4056a5f6 8653 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8654 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8655
9b6d8fcf
DS
8656 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8657 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8658 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8659
d62a17ae 8660 /* Selected */
9b6d8fcf 8661 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8662 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8663
9b6d8fcf 8664 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8665 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8666
bbb46eb5 8667 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8668 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8669 json_object_string_add(json_path, "selectionReason",
8670 bgp_path_selection_reason2str(
8671 path->net->reason));
8672 }
b05a1c8b 8673
9b6d8fcf 8674 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8675 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8676
d62a17ae 8677 /* Internal route. */
9b6d8fcf
DS
8678 if ((path->peer->as)
8679 && (path->peer->as == path->peer->local_as))
d62a17ae 8680 json_object_string_add(json_path, "pathFrom",
8681 "internal");
8682 else
8683 json_object_string_add(json_path, "pathFrom",
8684 "external");
b05a1c8b 8685
d62a17ae 8686 return;
8687 }
b05a1c8b 8688
82c298be
DA
8689 /* RPKI validation state */
8690 rpki_state =
8691 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8692
8693 if (rpki_state == RPKI_VALID)
8694 vty_out(vty, "V");
8695 else if (rpki_state == RPKI_INVALID)
8696 vty_out(vty, "I");
8697 else if (rpki_state == RPKI_NOTFOUND)
8698 vty_out(vty, "N");
8699
d62a17ae 8700 /* Route status display. */
9b6d8fcf 8701 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8702 vty_out(vty, "R");
9b6d8fcf 8703 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8704 vty_out(vty, "S");
4056a5f6 8705 else if (bgp_path_suppressed(path))
d62a17ae 8706 vty_out(vty, "s");
9b6d8fcf
DS
8707 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8708 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8709 vty_out(vty, "*");
8710 else
8711 vty_out(vty, " ");
8712
8713 /* Selected */
9b6d8fcf 8714 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8715 vty_out(vty, "h");
9b6d8fcf 8716 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8717 vty_out(vty, "d");
9b6d8fcf 8718 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8719 vty_out(vty, ">");
9b6d8fcf 8720 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8721 vty_out(vty, "=");
8722 else
8723 vty_out(vty, " ");
718e3744 8724
d62a17ae 8725 /* Internal route. */
9b6d8fcf
DS
8726 if (path->peer && (path->peer->as)
8727 && (path->peer->as == path->peer->local_as))
d62a17ae 8728 vty_out(vty, "i");
8729 else
8730 vty_out(vty, " ");
b40d939b 8731}
8732
2ba93fd6
DA
8733static char *bgp_nexthop_hostname(struct peer *peer,
8734 struct bgp_nexthop_cache *bnc)
25b5da8d 8735{
892fedb6 8736 if (peer->hostname
aef999a2 8737 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8738 return peer->hostname;
8739 return NULL;
8740}
8741
b40d939b 8742/* called from terminal list command */
bd494ec5 8743void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8744 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8745 json_object *json_paths, bool wide)
d62a17ae 8746{
aef999a2 8747 int len;
515c2602 8748 struct attr *attr = path->attr;
d62a17ae 8749 json_object *json_path = NULL;
8750 json_object *json_nexthops = NULL;
8751 json_object *json_nexthop_global = NULL;
8752 json_object *json_nexthop_ll = NULL;
6f214dd3 8753 json_object *json_ext_community = NULL;
9df8b37c 8754 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8755 bool nexthop_self =
9b6d8fcf 8756 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8757 bool nexthop_othervrf = false;
43089216 8758 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8759 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8760 char *nexthop_hostname =
8761 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8762 char esi_buf[ESI_STR_LEN];
d62a17ae 8763
8764 if (json_paths)
8765 json_path = json_object_new_object();
8766
8767 /* short status lead text */
82c298be 8768 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8769
8770 if (!json_paths) {
8771 /* print prefix and mask */
8772 if (!display)
7d3cae70 8773 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8774 else
ae248832 8775 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8776 } else {
7d3cae70 8777 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8778 }
47fc97cc 8779
9df8b37c
PZ
8780 /*
8781 * If vrf id of nexthop is different from that of prefix,
8782 * set up printable string to append
8783 */
9b6d8fcf 8784 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8785 const char *self = "";
8786
8787 if (nexthop_self)
8788 self = "<";
8789
8790 nexthop_othervrf = true;
9b6d8fcf 8791 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8792
9b6d8fcf 8793 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8794 snprintf(vrf_id_str, sizeof(vrf_id_str),
8795 "@%s%s", VRFID_NONE_STR, self);
8796 else
8797 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8798 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8799
9b6d8fcf
DS
8800 if (path->extra->bgp_orig->inst_type
8801 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8802
9b6d8fcf 8803 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8804 } else {
8805 const char *self = "";
8806
8807 if (nexthop_self)
8808 self = "<";
8809
8810 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8811 }
8812
445c2480
DS
8813 /*
8814 * For ENCAP and EVPN routes, nexthop address family is not
8815 * neccessarily the same as the prefix address family.
8816 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8817 * EVPN routes are also exchanged with a MP nexthop. Currently,
8818 * this
8819 * is only IPv4, the value will be present in either
8820 * attr->nexthop or
8821 * attr->mp_nexthop_global_in
8822 */
8823 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8824 char buf[BUFSIZ];
8825 char nexthop[128];
8826 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8827
8828 switch (af) {
8829 case AF_INET:
772270f3
QY
8830 snprintf(nexthop, sizeof(nexthop), "%s",
8831 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8832 BUFSIZ));
445c2480
DS
8833 break;
8834 case AF_INET6:
772270f3
QY
8835 snprintf(nexthop, sizeof(nexthop), "%s",
8836 inet_ntop(af, &attr->mp_nexthop_global, buf,
8837 BUFSIZ));
445c2480
DS
8838 break;
8839 default:
772270f3 8840 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8841 break;
d62a17ae 8842 }
d62a17ae 8843
445c2480
DS
8844 if (json_paths) {
8845 json_nexthop_global = json_object_new_object();
8846
515c2602
DA
8847 json_object_string_add(json_nexthop_global, "ip",
8848 nexthop);
8849
939a97f4 8850 if (path->peer->hostname)
515c2602
DA
8851 json_object_string_add(json_nexthop_global,
8852 "hostname",
939a97f4 8853 path->peer->hostname);
515c2602
DA
8854
8855 json_object_string_add(json_nexthop_global, "afi",
8856 (af == AF_INET) ? "ipv4"
8857 : "ipv6");
445c2480
DS
8858 json_object_boolean_true_add(json_nexthop_global,
8859 "used");
aef999a2
DA
8860 } else {
8861 if (nexthop_hostname)
8862 len = vty_out(vty, "%s(%s)%s", nexthop,
8863 nexthop_hostname, vrf_id_str);
8864 else
8865 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8866
ae248832 8867 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8868 if (len < 1)
8869 vty_out(vty, "\n%*s", 36, " ");
8870 else
8871 vty_out(vty, "%*s", len, " ");
8872 }
445c2480
DS
8873 } else if (safi == SAFI_EVPN) {
8874 if (json_paths) {
8875 json_nexthop_global = json_object_new_object();
8876
c949c771
DA
8877 json_object_string_addf(json_nexthop_global, "ip",
8878 "%pI4", &attr->nexthop);
515c2602 8879
939a97f4 8880 if (path->peer->hostname)
515c2602
DA
8881 json_object_string_add(json_nexthop_global,
8882 "hostname",
939a97f4 8883 path->peer->hostname);
515c2602 8884
a4d82a8a
PZ
8885 json_object_string_add(json_nexthop_global, "afi",
8886 "ipv4");
445c2480
DS
8887 json_object_boolean_true_add(json_nexthop_global,
8888 "used");
aef999a2
DA
8889 } else {
8890 if (nexthop_hostname)
8891 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8892 nexthop_hostname, vrf_id_str);
8893 else
8894 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8895 vrf_id_str);
8896
ae248832 8897 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8898 if (len < 1)
8899 vty_out(vty, "\n%*s", 36, " ");
8900 else
8901 vty_out(vty, "%*s", len, " ");
8902 }
d33fc23b 8903 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8904 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8905 if (json_paths) {
8906 json_nexthop_global = json_object_new_object();
515c2602 8907
026b914a
PG
8908 json_object_string_add(json_nexthop_global,
8909 "afi", "ipv4");
c949c771
DA
8910 json_object_string_addf(json_nexthop_global,
8911 "ip", "%pI4",
8912 &attr->nexthop);
515c2602 8913
939a97f4 8914 if (path->peer->hostname)
515c2602
DA
8915 json_object_string_add(
8916 json_nexthop_global, "hostname",
939a97f4 8917 path->peer->hostname);
515c2602 8918
50e05855
AD
8919 json_object_boolean_true_add(
8920 json_nexthop_global,
026b914a
PG
8921 "used");
8922 } else {
aef999a2
DA
8923 if (nexthop_hostname)
8924 len = vty_out(vty, "%pI4(%s)%s",
8925 &attr->nexthop,
8926 nexthop_hostname,
8927 vrf_id_str);
8928 else
8929 len = vty_out(vty, "%pI4%s",
8930 &attr->nexthop,
8931 vrf_id_str);
8932
ae248832 8933 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8934 if (len < 1)
8935 vty_out(vty, "\n%*s", 36, " ");
8936 else
8937 vty_out(vty, "%*s", len, " ");
026b914a
PG
8938 }
8939 }
d33fc23b 8940 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8941 if (json_paths) {
8942 json_nexthop_global = json_object_new_object();
d62a17ae 8943
c949c771
DA
8944 json_object_string_addf(json_nexthop_global, "ip",
8945 "%pI4", &attr->nexthop);
515c2602 8946
939a97f4 8947 if (path->peer->hostname)
515c2602
DA
8948 json_object_string_add(json_nexthop_global,
8949 "hostname",
939a97f4 8950 path->peer->hostname);
445c2480 8951
a4d82a8a
PZ
8952 json_object_string_add(json_nexthop_global, "afi",
8953 "ipv4");
445c2480
DS
8954 json_object_boolean_true_add(json_nexthop_global,
8955 "used");
8956 } else {
aef999a2
DA
8957 if (nexthop_hostname)
8958 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8959 nexthop_hostname, vrf_id_str);
8960 else
8961 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8962 vrf_id_str);
9df8b37c 8963
ae248832 8964 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8965 if (len < 1)
8966 vty_out(vty, "\n%*s", 36, " ");
8967 else
8968 vty_out(vty, "%*s", len, " ");
d62a17ae 8969 }
445c2480 8970 }
b05a1c8b 8971
445c2480 8972 /* IPv6 Next Hop */
a4d82a8a 8973 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8974 if (json_paths) {
8975 json_nexthop_global = json_object_new_object();
c949c771
DA
8976 json_object_string_addf(json_nexthop_global, "ip",
8977 "%pI6",
8978 &attr->mp_nexthop_global);
515c2602 8979
939a97f4 8980 if (path->peer->hostname)
515c2602
DA
8981 json_object_string_add(json_nexthop_global,
8982 "hostname",
939a97f4 8983 path->peer->hostname);
515c2602 8984
a4d82a8a
PZ
8985 json_object_string_add(json_nexthop_global, "afi",
8986 "ipv6");
8987 json_object_string_add(json_nexthop_global, "scope",
8988 "global");
445c2480
DS
8989
8990 /* We display both LL & GL if both have been
8991 * received */
0606039c
DA
8992 if ((attr->mp_nexthop_len
8993 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8994 || (path->peer->conf_if)) {
a4d82a8a 8995 json_nexthop_ll = json_object_new_object();
c949c771
DA
8996 json_object_string_addf(
8997 json_nexthop_ll, "ip", "%pI6",
8998 &attr->mp_nexthop_local);
515c2602 8999
939a97f4 9000 if (path->peer->hostname)
515c2602
DA
9001 json_object_string_add(
9002 json_nexthop_ll, "hostname",
939a97f4 9003 path->peer->hostname);
515c2602 9004
a4d82a8a
PZ
9005 json_object_string_add(json_nexthop_ll, "afi",
9006 "ipv6");
9007 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9008 "link-local");
d62a17ae 9009
a4d82a8a
PZ
9010 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9011 &attr->mp_nexthop_local)
445c2480
DS
9012 != 0)
9013 && !attr->mp_nexthop_prefer_global)
d62a17ae 9014 json_object_boolean_true_add(
a4d82a8a 9015 json_nexthop_ll, "used");
445c2480
DS
9016 else
9017 json_object_boolean_true_add(
a4d82a8a 9018 json_nexthop_global, "used");
445c2480
DS
9019 } else
9020 json_object_boolean_true_add(
9021 json_nexthop_global, "used");
9022 } else {
9023 /* Display LL if LL/Global both in table unless
9024 * prefer-global is set */
0606039c
DA
9025 if (((attr->mp_nexthop_len
9026 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9027 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9028 || (path->peer->conf_if)) {
9029 if (path->peer->conf_if) {
a4d82a8a 9030 len = vty_out(vty, "%s",
9b6d8fcf 9031 path->peer->conf_if);
ae248832
MK
9032 /* len of IPv6 addr + max len of def
9033 * ifname */
9034 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9035
9036 if (len < 1)
a4d82a8a 9037 vty_out(vty, "\n%*s", 36, " ");
445c2480 9038 else
a4d82a8a 9039 vty_out(vty, "%*s", len, " ");
d62a17ae 9040 } else {
aef999a2
DA
9041 if (nexthop_hostname)
9042 len = vty_out(
9043 vty, "%pI6(%s)%s",
9044 &attr->mp_nexthop_local,
9045 nexthop_hostname,
9046 vrf_id_str);
9047 else
9048 len = vty_out(
9049 vty, "%pI6%s",
9050 &attr->mp_nexthop_local,
9051 vrf_id_str);
9052
ae248832 9053 len = wide ? (41 - len) : (16 - len);
d62a17ae 9054
9055 if (len < 1)
a4d82a8a 9056 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9057 else
a4d82a8a 9058 vty_out(vty, "%*s", len, " ");
d62a17ae 9059 }
445c2480 9060 } else {
aef999a2
DA
9061 if (nexthop_hostname)
9062 len = vty_out(vty, "%pI6(%s)%s",
9063 &attr->mp_nexthop_global,
9064 nexthop_hostname,
9065 vrf_id_str);
9066 else
9067 len = vty_out(vty, "%pI6%s",
9068 &attr->mp_nexthop_global,
9069 vrf_id_str);
9070
ae248832 9071 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9072
9073 if (len < 1)
9074 vty_out(vty, "\n%*s", 36, " ");
9075 else
9076 vty_out(vty, "%*s", len, " ");
d62a17ae 9077 }
9078 }
445c2480 9079 }
718e3744 9080
445c2480
DS
9081 /* MED/Metric */
9082 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9083 if (json_paths)
50e05855 9084 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9085 else if (wide)
9086 vty_out(vty, "%7u", attr->med);
0fbac0b4 9087 else
445c2480 9088 vty_out(vty, "%10u", attr->med);
ae248832
MK
9089 else if (!json_paths) {
9090 if (wide)
9091 vty_out(vty, "%*s", 7, " ");
9092 else
9093 vty_out(vty, "%*s", 10, " ");
9094 }
d62a17ae 9095
445c2480
DS
9096 /* Local Pref */
9097 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9098 if (json_paths)
50e05855 9099 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9100 attr->local_pref);
9101 else
445c2480
DS
9102 vty_out(vty, "%7u", attr->local_pref);
9103 else if (!json_paths)
9104 vty_out(vty, " ");
d62a17ae 9105
445c2480
DS
9106 if (json_paths)
9107 json_object_int_add(json_path, "weight", attr->weight);
9108 else
9109 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9110
445c2480
DS
9111 if (json_paths) {
9112 char buf[BUFSIZ];
a4d82a8a
PZ
9113 json_object_string_add(
9114 json_path, "peerId",
9b6d8fcf 9115 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 9116 }
b05a1c8b 9117
445c2480
DS
9118 /* Print aspath */
9119 if (attr->aspath) {
0fbac0b4 9120 if (json_paths)
50e05855 9121 json_object_string_add(json_path, "path",
0fbac0b4
DA
9122 attr->aspath->str);
9123 else
445c2480 9124 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9125 }
f1aa5d8a 9126
445c2480
DS
9127 /* Print origin */
9128 if (json_paths)
a4d82a8a
PZ
9129 json_object_string_add(json_path, "origin",
9130 bgp_origin_long_str[attr->origin]);
445c2480
DS
9131 else
9132 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9133
9df8b37c 9134 if (json_paths) {
d071f237 9135 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9136 json_object_string_add(json_path, "esi",
9137 esi_to_str(&attr->esi,
9138 esi_buf, sizeof(esi_buf)));
9139 }
6f214dd3
CS
9140 if (safi == SAFI_EVPN &&
9141 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9142 json_ext_community = json_object_new_object();
b53e67a3
DA
9143 json_object_string_add(
9144 json_ext_community, "string",
9145 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9146 json_object_object_add(json_path,
9147 "extendedCommunity",
9148 json_ext_community);
9149 }
9150
9df8b37c
PZ
9151 if (nexthop_self)
9152 json_object_boolean_true_add(json_path,
9153 "announceNexthopSelf");
9154 if (nexthop_othervrf) {
9155 json_object_string_add(json_path, "nhVrfName",
9156 nexthop_vrfname);
9157
9158 json_object_int_add(json_path, "nhVrfId",
9159 ((nexthop_vrfid == VRF_UNKNOWN)
9160 ? -1
9161 : (int)nexthop_vrfid));
9162 }
9163 }
9164
d62a17ae 9165 if (json_paths) {
9166 if (json_nexthop_global || json_nexthop_ll) {
9167 json_nexthops = json_object_new_array();
f1aa5d8a 9168
d62a17ae 9169 if (json_nexthop_global)
9170 json_object_array_add(json_nexthops,
9171 json_nexthop_global);
f1aa5d8a 9172
d62a17ae 9173 if (json_nexthop_ll)
9174 json_object_array_add(json_nexthops,
9175 json_nexthop_ll);
f1aa5d8a 9176
d62a17ae 9177 json_object_object_add(json_path, "nexthops",
9178 json_nexthops);
9179 }
9180
9181 json_object_array_add(json_paths, json_path);
9182 } else {
9183 vty_out(vty, "\n");
6f214dd3 9184
b5e140c8 9185 if (safi == SAFI_EVPN) {
d071f237 9186 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9187 /* XXX - add these params to the json out */
b5e140c8 9188 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9189 vty_out(vty, "ESI:%s",
9190 esi_to_str(&attr->esi, esi_buf,
9191 sizeof(esi_buf)));
60605cbc 9192
229587fb 9193 vty_out(vty, "\n");
b5e140c8
AK
9194 }
9195 if (attr->flag &
9196 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9197 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9198 vty_out(vty, "%s\n",
9199 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9200 }
6f214dd3
CS
9201 }
9202
49e5a4a0 9203#ifdef ENABLE_BGP_VNC
d62a17ae 9204 /* prints an additional line, indented, with VNC info, if
9205 * present */
9206 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9207 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9208#endif
d62a17ae 9209 }
9210}
718e3744 9211
9212/* called from terminal list command */
7d3cae70
DA
9213void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9214 const struct prefix *p, struct attr *attr, safi_t safi,
9215 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9216{
9217 json_object *json_status = NULL;
9218 json_object *json_net = NULL;
aef999a2 9219 int len;
d62a17ae 9220 char buff[BUFSIZ];
dc387b0f 9221
d62a17ae 9222 /* Route status display. */
9223 if (use_json) {
9224 json_status = json_object_new_object();
9225 json_net = json_object_new_object();
9226 } else {
9227 vty_out(vty, "*");
9228 vty_out(vty, ">");
9229 vty_out(vty, " ");
9230 }
718e3744 9231
d62a17ae 9232 /* print prefix and mask */
50e05855 9233 if (use_json) {
dc387b0f
LK
9234 if (safi == SAFI_EVPN)
9235 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9236 else if (p->family == AF_INET || p->family == AF_INET6) {
9237 json_object_string_add(
9238 json_net, "addrPrefix",
9239 inet_ntop(p->family, &p->u.prefix, buff,
9240 BUFSIZ));
9241 json_object_int_add(json_net, "prefixLen",
9242 p->prefixlen);
67d7e256 9243 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9244 }
50e05855 9245 } else
7d3cae70 9246 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9247
9248 /* Print attribute */
9249 if (attr) {
9250 if (use_json) {
9251 if (p->family == AF_INET
9252 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9253 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9254 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9255 json_object_string_addf(
9256 json_net, "nextHop", "%pI4",
9257 &attr->mp_nexthop_global_in);
d62a17ae 9258 else
c949c771
DA
9259 json_object_string_addf(
9260 json_net, "nextHop", "%pI4",
9261 &attr->nexthop);
d62a17ae 9262 } else if (p->family == AF_INET6
9263 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9264 json_object_string_addf(
9265 json_net, "nextHopGlobal", "%pI6",
9266 &attr->mp_nexthop_global);
23d0a753
DA
9267 } else if (p->family == AF_EVPN
9268 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9269 json_object_string_addf(
9270 json_net, "nextHop", "%pI4",
9271 &attr->mp_nexthop_global_in);
23d0a753 9272 }
d62a17ae 9273
9274 if (attr->flag
9275 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9276 json_object_int_add(json_net, "metric",
9277 attr->med);
9278
0fbac0b4 9279 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9280 json_object_int_add(json_net, "locPrf",
0fbac0b4 9281 attr->local_pref);
d62a17ae 9282
9283 json_object_int_add(json_net, "weight", attr->weight);
9284
9285 /* Print aspath */
0fbac0b4 9286 if (attr->aspath)
50e05855 9287 json_object_string_add(json_net, "path",
0fbac0b4 9288 attr->aspath->str);
d62a17ae 9289
9290 /* Print origin */
9291 json_object_string_add(json_net, "bgpOriginCode",
9292 bgp_origin_str[attr->origin]);
9293 } else {
9294 if (p->family == AF_INET
9295 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9296 || safi == SAFI_EVPN
9297 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9298 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9299 || safi == SAFI_EVPN)
23d0a753
DA
9300 vty_out(vty, "%-16pI4",
9301 &attr->mp_nexthop_global_in);
ae248832 9302 else if (wide)
23d0a753 9303 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9304 else
23d0a753 9305 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9306 } else if (p->family == AF_INET6
9307 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9308 char buf[BUFSIZ];
9309
9310 len = vty_out(
9311 vty, "%s",
9312 inet_ntop(AF_INET6,
9313 &attr->mp_nexthop_global, buf,
9314 BUFSIZ));
ae248832 9315 len = wide ? (41 - len) : (16 - len);
d62a17ae 9316 if (len < 1)
9317 vty_out(vty, "\n%*s", 36, " ");
9318 else
9319 vty_out(vty, "%*s", len, " ");
9320 }
9321 if (attr->flag
9322 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9323 if (wide)
9324 vty_out(vty, "%7u", attr->med);
9325 else
9326 vty_out(vty, "%10u", attr->med);
9327 else if (wide)
9328 vty_out(vty, " ");
d62a17ae 9329 else
9330 vty_out(vty, " ");
718e3744 9331
d62a17ae 9332 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9333 vty_out(vty, "%7u", attr->local_pref);
9334 else
9335 vty_out(vty, " ");
9336
9337 vty_out(vty, "%7u ", attr->weight);
9338
9339 /* Print aspath */
9340 if (attr->aspath)
9341 aspath_print_vty(vty, "%s", attr->aspath, " ");
9342
9343 /* Print origin */
9344 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9345 }
9346 }
9347 if (use_json) {
9348 json_object_boolean_true_add(json_status, "*");
9349 json_object_boolean_true_add(json_status, ">");
9350 json_object_object_add(json_net, "appliedStatusSymbols",
9351 json_status);
1608ff77 9352
dc387b0f
LK
9353 prefix2str(p, buff, PREFIX_STRLEN);
9354 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9355 } else
9356 vty_out(vty, "\n");
9357}
9358
bd494ec5 9359void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9360 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9361 json_object *json)
9362{
9363 json_object *json_out = NULL;
9364 struct attr *attr;
9365 mpls_label_t label = MPLS_INVALID_LABEL;
9366
9b6d8fcf 9367 if (!path->extra)
d62a17ae 9368 return;
9369
9370 if (json)
9371 json_out = json_object_new_object();
9372
9373 /* short status lead text */
82c298be 9374 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9375
9376 /* print prefix and mask */
9377 if (json == NULL) {
9378 if (!display)
7d3cae70 9379 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9380 else
9381 vty_out(vty, "%*s", 17, " ");
9382 }
9383
9384 /* Print attribute */
9b6d8fcf 9385 attr = path->attr;
05864da7
DS
9386 if (((p->family == AF_INET)
9387 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9388 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9389 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9390 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9391 || safi == SAFI_EVPN) {
9392 if (json)
c949c771
DA
9393 json_object_string_addf(
9394 json_out, "mpNexthopGlobalIn", "%pI4",
9395 &attr->mp_nexthop_global_in);
05864da7 9396 else
23d0a753
DA
9397 vty_out(vty, "%-16pI4",
9398 &attr->mp_nexthop_global_in);
05864da7
DS
9399 } else {
9400 if (json)
c949c771
DA
9401 json_object_string_addf(json_out, "nexthop",
9402 "%pI4", &attr->nexthop);
05864da7 9403 else
23d0a753 9404 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9405 }
9406 } else if (((p->family == AF_INET6)
9407 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9408 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9409 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9410 char buf_a[512];
9411
9412 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9413 if (json)
c949c771
DA
9414 json_object_string_addf(
9415 json_out, "mpNexthopGlobalIn", "%pI6",
9416 &attr->mp_nexthop_global);
05864da7
DS
9417 else
9418 vty_out(vty, "%s",
9419 inet_ntop(AF_INET6,
9420 &attr->mp_nexthop_global,
9421 buf_a, sizeof(buf_a)));
9422 } else if (attr->mp_nexthop_len
9423 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9424 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9425 &attr->mp_nexthop_global,
9426 &attr->mp_nexthop_local);
9427 if (json)
9428 json_object_string_add(json_out,
9429 "mpNexthopGlobalLocal",
9430 buf_a);
9431 else
9432 vty_out(vty, "%s", buf_a);
d62a17ae 9433 }
9434 }
9435
9b6d8fcf 9436 label = decode_label(&path->extra->label[0]);
d62a17ae 9437
9438 if (bgp_is_valid_label(&label)) {
9439 if (json) {
9440 json_object_int_add(json_out, "notag", label);
9441 json_object_array_add(json, json_out);
9442 } else {
9443 vty_out(vty, "notag/%d", label);
9444 vty_out(vty, "\n");
9445 }
700ddfed
PG
9446 } else if (!json)
9447 vty_out(vty, "\n");
d62a17ae 9448}
718e3744 9449
bd494ec5 9450void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9451 struct bgp_path_info *path, int display,
d62a17ae 9452 json_object *json_paths)
718e3744 9453{
d62a17ae 9454 struct attr *attr;
14f51eba 9455 char buf[BUFSIZ] = {0};
d62a17ae 9456 json_object *json_path = NULL;
14f51eba
LK
9457 json_object *json_nexthop = NULL;
9458 json_object *json_overlay = NULL;
856ca177 9459
9b6d8fcf 9460 if (!path->extra)
d62a17ae 9461 return;
718e3744 9462
14f51eba
LK
9463 if (json_paths) {
9464 json_path = json_object_new_object();
9465 json_overlay = json_object_new_object();
9466 json_nexthop = json_object_new_object();
9467 }
9468
d62a17ae 9469 /* short status lead text */
82c298be 9470 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9471
d62a17ae 9472 /* print prefix and mask */
9473 if (!display)
7d3cae70 9474 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9475 else
9476 vty_out(vty, "%*s", 17, " ");
9477
9478 /* Print attribute */
9b6d8fcf 9479 attr = path->attr;
05864da7
DS
9480 char buf1[BUFSIZ];
9481 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9482
05864da7
DS
9483 switch (af) {
9484 case AF_INET:
9485 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9486 if (!json_path) {
9487 vty_out(vty, "%-16s", buf);
9488 } else {
9489 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9490
05864da7 9491 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9492
05864da7
DS
9493 json_object_object_add(json_path, "nexthop",
9494 json_nexthop);
9495 }
9496 break;
9497 case AF_INET6:
9498 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9499 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9500 if (!json_path) {
9501 vty_out(vty, "%s(%s)", buf, buf1);
9502 } else {
9503 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9504
05864da7
DS
9505 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9506 buf1);
14f51eba 9507
05864da7 9508 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9509
05864da7
DS
9510 json_object_object_add(json_path, "nexthop",
9511 json_nexthop);
9512 }
9513 break;
9514 default:
9515 if (!json_path) {
9516 vty_out(vty, "?");
9517 } else {
9518 json_object_string_add(json_nexthop, "Error",
9519 "Unsupported address-family");
d62a17ae 9520 }
05864da7 9521 }
988258b4 9522
6c924775
DS
9523 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9524
860e740b 9525 ipaddr2str(&eo->gw_ip, buf, BUFSIZ);
14f51eba 9526
05864da7
DS
9527 if (!json_path)
9528 vty_out(vty, "/%s", buf);
9529 else
9530 json_object_string_add(json_overlay, "gw", buf);
9531
b53e67a3 9532 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9533 char *mac = NULL;
9534 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9535 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9536 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9537
9538 if (routermac)
9539 mac = ecom_mac2str((char *)routermac->val);
9540 if (mac) {
9541 if (!json_path) {
c4efd0f4 9542 vty_out(vty, "/%s", mac);
05864da7
DS
9543 } else {
9544 json_object_string_add(json_overlay, "rmac",
9545 mac);
988258b4 9546 }
05864da7 9547 XFREE(MTYPE_TMP, mac);
988258b4 9548 }
05864da7 9549 }
718e3744 9550
05864da7
DS
9551 if (!json_path) {
9552 vty_out(vty, "\n");
9553 } else {
9554 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9555
05864da7 9556 json_object_array_add(json_paths, json_path);
14f51eba 9557 }
d62a17ae 9558}
718e3744 9559
d62a17ae 9560/* dampening route */
5f040085
DS
9561static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9562 struct bgp_path_info *path, int display,
9563 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9564 json_object *json_paths)
d62a17ae 9565{
e5be8c1d 9566 struct attr *attr = path->attr;
d62a17ae 9567 int len;
9568 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9569 json_object *json_path = NULL;
9570
9571 if (use_json)
9572 json_path = json_object_new_object();
d62a17ae 9573
9574 /* short status lead text */
e5be8c1d 9575 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9576
9577 /* print prefix and mask */
9578 if (!use_json) {
9579 if (!display)
7d3cae70 9580 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9581 else
9582 vty_out(vty, "%*s", 17, " ");
d62a17ae 9583
e5be8c1d
DA
9584 len = vty_out(vty, "%s", path->peer->host);
9585 len = 17 - len;
9586
9587 if (len < 1)
d62a17ae 9588 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9589 else
9590 vty_out(vty, "%*s", len, " ");
d62a17ae 9591
9b6d8fcf
DS
9592 vty_out(vty, "%s ",
9593 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9594 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9595 use_json, NULL));
d62a17ae 9596
e5be8c1d 9597 if (attr->aspath)
05864da7 9598 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9599
05864da7
DS
9600 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9601
d62a17ae 9602 vty_out(vty, "\n");
e5be8c1d
DA
9603 } else {
9604 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9605 safi, use_json, json_path);
9606
9607 if (attr->aspath)
9608 json_object_string_add(json_path, "asPath",
9609 attr->aspath->str);
9610
9611 json_object_string_add(json_path, "origin",
9612 bgp_origin_str[attr->origin]);
9613 json_object_string_add(json_path, "peerHost", path->peer->host);
9614
9615 json_object_array_add(json_paths, json_path);
9616 }
d62a17ae 9617}
718e3744 9618
d62a17ae 9619/* flap route */
5f040085
DS
9620static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9621 struct bgp_path_info *path, int display,
9622 afi_t afi, safi_t safi, bool use_json,
31258046 9623 json_object *json_paths)
784d3a42 9624{
31258046 9625 struct attr *attr = path->attr;
d62a17ae 9626 struct bgp_damp_info *bdi;
9627 char timebuf[BGP_UPTIME_LEN];
9628 int len;
31258046 9629 json_object *json_path = NULL;
784d3a42 9630
9b6d8fcf 9631 if (!path->extra)
d62a17ae 9632 return;
784d3a42 9633
31258046
DA
9634 if (use_json)
9635 json_path = json_object_new_object();
9636
9b6d8fcf 9637 bdi = path->extra->damp_info;
784d3a42 9638
d62a17ae 9639 /* short status lead text */
31258046 9640 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9641
d62a17ae 9642 if (!use_json) {
9643 if (!display)
7d3cae70 9644 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9645 else
9646 vty_out(vty, "%*s", 17, " ");
784d3a42 9647
31258046
DA
9648 len = vty_out(vty, "%s", path->peer->host);
9649 len = 16 - len;
9650 if (len < 1)
d62a17ae 9651 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9652 else
9653 vty_out(vty, "%*s", len, " ");
784d3a42 9654
31258046
DA
9655 len = vty_out(vty, "%d", bdi->flap);
9656 len = 5 - len;
9657 if (len < 1)
d62a17ae 9658 vty_out(vty, " ");
d62a17ae 9659 else
9660 vty_out(vty, "%*s", len, " ");
d62a17ae 9661
996c9314
LB
9662 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9663 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9664
31258046
DA
9665 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9666 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9667 vty_out(vty, "%s ",
9b6d8fcf 9668 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9669 BGP_UPTIME_LEN, afi,
31258046
DA
9670 safi, use_json, NULL));
9671 else
d62a17ae 9672 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9673
31258046 9674 if (attr->aspath)
05864da7 9675 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9676
05864da7
DS
9677 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9678
d62a17ae 9679 vty_out(vty, "\n");
31258046
DA
9680 } else {
9681 json_object_string_add(json_path, "peerHost", path->peer->host);
9682 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9683
9684 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9685 json_path);
9686
9687 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9688 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9689 bgp_damp_reuse_time_vty(vty, path, timebuf,
9690 BGP_UPTIME_LEN, afi, safi,
9691 use_json, json_path);
9692
9693 if (attr->aspath)
9694 json_object_string_add(json_path, "asPath",
9695 attr->aspath->str);
9696
9697 json_object_string_add(json_path, "origin",
9698 bgp_origin_str[attr->origin]);
9699
9700 json_object_array_add(json_paths, json_path);
9701 }
d62a17ae 9702}
9703
9704static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9705 int *first, const char *header,
9706 json_object *json_adv_to)
9707{
9708 char buf1[INET6_ADDRSTRLEN];
9709 json_object *json_peer = NULL;
9710
9711 if (json_adv_to) {
9712 /* 'advertised-to' is a dictionary of peers we have advertised
9713 * this
9714 * prefix too. The key is the peer's IP or swpX, the value is
9715 * the
9716 * hostname if we know it and "" if not.
9717 */
9718 json_peer = json_object_new_object();
9719
9720 if (peer->hostname)
9721 json_object_string_add(json_peer, "hostname",
9722 peer->hostname);
9723
9724 if (peer->conf_if)
9725 json_object_object_add(json_adv_to, peer->conf_if,
9726 json_peer);
9727 else
9728 json_object_object_add(
9729 json_adv_to,
9730 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9731 json_peer);
9732 } else {
9733 if (*first) {
9734 vty_out(vty, "%s", header);
9735 *first = 0;
9736 }
9737
9738 if (peer->hostname
892fedb6 9739 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9740 if (peer->conf_if)
9741 vty_out(vty, " %s(%s)", peer->hostname,
9742 peer->conf_if);
9743 else
9744 vty_out(vty, " %s(%s)", peer->hostname,
9745 sockunion2str(&peer->su, buf1,
9746 SU_ADDRSTRLEN));
9747 } else {
9748 if (peer->conf_if)
9749 vty_out(vty, " %s", peer->conf_if);
9750 else
9751 vty_out(vty, " %s",
9752 sockunion2str(&peer->su, buf1,
9753 SU_ADDRSTRLEN));
9754 }
9755 }
784d3a42
PG
9756}
9757
dcc68b5e
MS
9758static void route_vty_out_tx_ids(struct vty *vty,
9759 struct bgp_addpath_info_data *d)
9760{
9761 int i;
9762
9763 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9764 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9765 d->addpath_tx_id[i],
9766 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9767 }
9768}
9769
5e4d4c8a 9770static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9771 struct bgp_path_info *pi,
9772 struct attr *attr,
9773 json_object *json_path)
5e4d4c8a
AK
9774{
9775 char esi_buf[ESI_STR_LEN];
9776 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9777 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9778 ATTR_ES_PEER_ROUTER);
9779 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9780 ATTR_ES_PEER_ACTIVE);
9781 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9782 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9783 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9784 if (json_path) {
9785 json_object *json_es_info = NULL;
9786
9787 json_object_string_add(
9788 json_path, "esi",
9789 esi_buf);
9790 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9791 json_es_info = json_object_new_object();
9792 if (es_local)
9793 json_object_boolean_true_add(
9794 json_es_info, "localEs");
9795 if (peer_active)
9796 json_object_boolean_true_add(
9797 json_es_info, "peerActive");
9798 if (peer_proxy)
9799 json_object_boolean_true_add(
9800 json_es_info, "peerProxy");
9801 if (peer_router)
9802 json_object_boolean_true_add(
9803 json_es_info, "peerRouter");
9804 if (attr->mm_sync_seqnum)
9805 json_object_int_add(
9806 json_es_info, "peerSeq",
9807 attr->mm_sync_seqnum);
9808 json_object_object_add(
9809 json_path, "es_info",
9810 json_es_info);
9811 }
9812 } else {
9813 if (bgp_evpn_attr_is_sync(attr))
9814 vty_out(vty,
9815 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9816 esi_buf,
9817 es_local ? "local-es":"",
9818 peer_proxy ? "proxy " : "",
9819 peer_active ? "active ":"",
9820 peer_router ? "router ":"",
9821 attr->mm_sync_seqnum);
9822 else
9823 vty_out(vty, " ESI %s %s\n",
9824 esi_buf,
9825 es_local ? "local-es":"");
9826 }
9827}
9828
4933eaaf
DS
9829void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9830 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9831 enum rpki_states rpki_curr_state,
9832 json_object *json_paths)
d62a17ae 9833{
9834 char buf[INET6_ADDRSTRLEN];
9835 char buf1[BUFSIZ];
515c2602 9836 struct attr *attr = path->attr;
d62a17ae 9837 int sockunion_vty_out(struct vty *, union sockunion *);
9838 time_t tbuf;
9839 json_object *json_bestpath = NULL;
9840 json_object *json_cluster_list = NULL;
9841 json_object *json_cluster_list_list = NULL;
9842 json_object *json_ext_community = NULL;
9843 json_object *json_last_update = NULL;
7fd077aa 9844 json_object *json_pmsi = NULL;
d62a17ae 9845 json_object *json_nexthop_global = NULL;
9846 json_object *json_nexthop_ll = NULL;
9847 json_object *json_nexthops = NULL;
9848 json_object *json_path = NULL;
9849 json_object *json_peer = NULL;
9850 json_object *json_string = NULL;
9851 json_object *json_adv_to = NULL;
9852 int first = 0;
9853 struct listnode *node, *nnode;
9854 struct peer *peer;
be92fc9f 9855 bool addpath_capable;
d62a17ae 9856 int has_adj;
9857 unsigned int first_as;
1defdda8 9858 bool nexthop_self =
9b6d8fcf 9859 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9860 int i;
2ba93fd6
DA
9861 char *nexthop_hostname =
9862 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9863
9864 if (json_paths) {
9865 json_path = json_object_new_object();
9866 json_peer = json_object_new_object();
9867 json_nexthop_global = json_object_new_object();
9868 }
9869
8304dabf
AD
9870 if (safi == SAFI_EVPN) {
9871 if (!json_paths)
9872 vty_out(vty, " Route %pRN", bn);
9873 }
9874
44c69747 9875 if (path->extra) {
b57ba6d2 9876 char tag_buf[30];
d62a17ae 9877
d62a17ae 9878 tag_buf[0] = '\0';
9b6d8fcf
DS
9879 if (path->extra && path->extra->num_labels) {
9880 bgp_evpn_label2str(path->extra->label,
9881 path->extra->num_labels, tag_buf,
a4d82a8a 9882 sizeof(tag_buf));
d62a17ae 9883 }
d7325ee7 9884 if (safi == SAFI_EVPN) {
44c69747 9885 if (!json_paths) {
44c69747
LK
9886 if (tag_buf[0] != '\0')
9887 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9888 } else {
9889 if (tag_buf[0])
9890 json_object_string_add(json_path, "VNI",
9891 tag_buf);
9892 }
d7325ee7
DD
9893 }
9894
44c69747 9895 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9896 struct bgp_path_info *parent_ri;
9bcb3eef 9897 struct bgp_dest *dest, *pdest;
d62a17ae 9898
9b6d8fcf 9899 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9900 dest = parent_ri->net;
9901 if (dest && dest->pdest) {
9902 pdest = dest->pdest;
9903 prefix_rd2str(
9904 (struct prefix_rd *)bgp_dest_get_prefix(
9905 pdest),
9906 buf1, sizeof(buf1));
d7325ee7 9907 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9908 vty_out(vty,
58bff4d1 9909 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9910 buf1,
9911 (struct prefix_evpn *)
9912 bgp_dest_get_prefix(
9913 dest),
9914 tag_buf);
58bff4d1
AK
9915 if (attr->es_flags & ATTR_ES_L3_NHG)
9916 vty_out(vty, ", L3NHG %s",
9917 (attr->es_flags
9918 & ATTR_ES_L3_NHG_ACTIVE)
9919 ? "active"
9920 : "inactive");
9921 vty_out(vty, "\n");
9922
d7325ee7 9923 } else
2dbe669b
DA
9924 vty_out(vty,
9925 " Imported from %s:%pFX\n",
9926 buf1,
9927 (struct prefix_evpn *)
9928 bgp_dest_get_prefix(
9929 dest));
d62a17ae 9930 }
9931 }
9932 }
d62a17ae 9933
8304dabf
AD
9934 if (safi == SAFI_EVPN
9935 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9936 char gwip_buf[INET6_ADDRSTRLEN];
9937
860e740b
IR
9938 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
9939 sizeof(gwip_buf));
8304dabf
AD
9940
9941 if (json_paths)
9942 json_object_string_add(json_path, "gatewayIP",
9943 gwip_buf);
9944 else
9945 vty_out(vty, " Gateway IP %s", gwip_buf);
9946 }
9947
9948 if (safi == SAFI_EVPN)
9949 vty_out(vty, "\n");
9950
05864da7
DS
9951 /* Line1 display AS-path, Aggregator */
9952 if (attr->aspath) {
9953 if (json_paths) {
9954 if (!attr->aspath->json)
9955 aspath_str_update(attr->aspath, true);
9956 json_object_lock(attr->aspath->json);
9957 json_object_object_add(json_path, "aspath",
9958 attr->aspath->json);
9959 } else {
9960 if (attr->aspath->segments)
9961 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9962 else
05864da7 9963 vty_out(vty, " Local");
d62a17ae 9964 }
05864da7 9965 }
d62a17ae 9966
05864da7
DS
9967 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9968 if (json_paths)
9969 json_object_boolean_true_add(json_path, "removed");
9970 else
9971 vty_out(vty, ", (removed)");
9972 }
d62a17ae 9973
05864da7
DS
9974 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9975 if (json_paths)
9976 json_object_boolean_true_add(json_path, "stale");
9977 else
9978 vty_out(vty, ", (stale)");
9979 }
d62a17ae 9980
05864da7
DS
9981 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9982 if (json_paths) {
9983 json_object_int_add(json_path, "aggregatorAs",
9984 attr->aggregator_as);
c949c771
DA
9985 json_object_string_addf(json_path, "aggregatorId",
9986 "%pI4", &attr->aggregator_addr);
05864da7 9987 } else {
88d495a9
DA
9988 vty_out(vty, ", (aggregated by %u %pI4)",
9989 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9990 }
05864da7 9991 }
d62a17ae 9992
05864da7
DS
9993 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9994 PEER_FLAG_REFLECTOR_CLIENT)) {
9995 if (json_paths)
9996 json_object_boolean_true_add(json_path,
9997 "rxedFromRrClient");
9998 else
9999 vty_out(vty, ", (Received from a RR-client)");
10000 }
d62a17ae 10001
05864da7
DS
10002 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10003 PEER_FLAG_RSERVER_CLIENT)) {
10004 if (json_paths)
10005 json_object_boolean_true_add(json_path,
10006 "rxedFromRsClient");
10007 else
10008 vty_out(vty, ", (Received from a RS-client)");
10009 }
d62a17ae 10010
05864da7
DS
10011 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10012 if (json_paths)
10013 json_object_boolean_true_add(json_path,
10014 "dampeningHistoryEntry");
10015 else
10016 vty_out(vty, ", (history entry)");
10017 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10018 if (json_paths)
10019 json_object_boolean_true_add(json_path,
10020 "dampeningSuppressed");
10021 else
10022 vty_out(vty, ", (suppressed due to dampening)");
10023 }
d62a17ae 10024
05864da7
DS
10025 if (!json_paths)
10026 vty_out(vty, "\n");
d62a17ae 10027
05864da7
DS
10028 /* Line2 display Next-hop, Neighbor, Router-id */
10029 /* Display the nexthop */
9bcb3eef 10030 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10031
10032 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10033 || bn_p->family == AF_EVPN)
05864da7
DS
10034 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10035 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10036 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10037 || safi == SAFI_EVPN) {
515c2602 10038 if (json_paths) {
c949c771
DA
10039 json_object_string_addf(
10040 json_nexthop_global, "ip", "%pI4",
10041 &attr->mp_nexthop_global_in);
515c2602 10042
939a97f4 10043 if (path->peer->hostname)
515c2602
DA
10044 json_object_string_add(
10045 json_nexthop_global, "hostname",
939a97f4 10046 path->peer->hostname);
aef999a2
DA
10047 } else {
10048 if (nexthop_hostname)
10049 vty_out(vty, " %pI4(%s)",
10050 &attr->mp_nexthop_global_in,
10051 nexthop_hostname);
10052 else
10053 vty_out(vty, " %pI4",
10054 &attr->mp_nexthop_global_in);
10055 }
d62a17ae 10056 } else {
515c2602 10057 if (json_paths) {
c949c771
DA
10058 json_object_string_addf(json_nexthop_global,
10059 "ip", "%pI4",
10060 &attr->nexthop);
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->nexthop,
10070 nexthop_hostname);
10071 else
10072 vty_out(vty, " %pI4",
10073 &attr->nexthop);
10074 }
d62a17ae 10075 }
10076
05864da7
DS
10077 if (json_paths)
10078 json_object_string_add(json_nexthop_global, "afi",
10079 "ipv4");
10080 } else {
10081 if (json_paths) {
c949c771
DA
10082 json_object_string_addf(json_nexthop_global, "ip",
10083 "%pI6",
10084 &attr->mp_nexthop_global);
515c2602 10085
939a97f4 10086 if (path->peer->hostname)
515c2602
DA
10087 json_object_string_add(json_nexthop_global,
10088 "hostname",
939a97f4 10089 path->peer->hostname);
515c2602 10090
05864da7
DS
10091 json_object_string_add(json_nexthop_global, "afi",
10092 "ipv6");
10093 json_object_string_add(json_nexthop_global, "scope",
10094 "global");
10095 } else {
aef999a2
DA
10096 if (nexthop_hostname)
10097 vty_out(vty, " %pI6(%s)",
10098 &attr->mp_nexthop_global,
10099 nexthop_hostname);
10100 else
10101 vty_out(vty, " %pI6",
10102 &attr->mp_nexthop_global);
d62a17ae 10103 }
05864da7 10104 }
d62a17ae 10105
05864da7
DS
10106 /* Display the IGP cost or 'inaccessible' */
10107 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10108 if (json_paths)
10109 json_object_boolean_false_add(json_nexthop_global,
10110 "accessible");
10111 else
10112 vty_out(vty, " (inaccessible)");
10113 } else {
10114 if (path->extra && path->extra->igpmetric) {
d62a17ae 10115 if (json_paths)
05864da7
DS
10116 json_object_int_add(json_nexthop_global,
10117 "metric",
10118 path->extra->igpmetric);
d62a17ae 10119 else
05864da7
DS
10120 vty_out(vty, " (metric %u)",
10121 path->extra->igpmetric);
d62a17ae 10122 }
10123
05864da7 10124 /* IGP cost is 0, display this only for json */
d62a17ae 10125 else {
d62a17ae 10126 if (json_paths)
05864da7
DS
10127 json_object_int_add(json_nexthop_global,
10128 "metric", 0);
d62a17ae 10129 }
d62a17ae 10130
05864da7
DS
10131 if (json_paths)
10132 json_object_boolean_true_add(json_nexthop_global,
10133 "accessible");
10134 }
d62a17ae 10135
05864da7
DS
10136 /* Display peer "from" output */
10137 /* This path was originated locally */
10138 if (path->peer == bgp->peer_self) {
d62a17ae 10139
05864da7 10140 if (safi == SAFI_EVPN
b54892e0 10141 || (bn_p->family == AF_INET
05864da7 10142 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10143 if (json_paths)
05864da7
DS
10144 json_object_string_add(json_peer, "peerId",
10145 "0.0.0.0");
d62a17ae 10146 else
05864da7
DS
10147 vty_out(vty, " from 0.0.0.0 ");
10148 } else {
d62a17ae 10149 if (json_paths)
05864da7
DS
10150 json_object_string_add(json_peer, "peerId",
10151 "::");
d62a17ae 10152 else
05864da7 10153 vty_out(vty, " from :: ");
d62a17ae 10154 }
d62a17ae 10155
4e9a9863 10156 if (json_paths)
c949c771
DA
10157 json_object_string_addf(json_peer, "routerId", "%pI4",
10158 &bgp->router_id);
4e9a9863 10159 else
23d0a753 10160 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10161 }
d62a17ae 10162
05864da7
DS
10163 /* We RXed this path from one of our peers */
10164 else {
10165
10166 if (json_paths) {
10167 json_object_string_add(json_peer, "peerId",
10168 sockunion2str(&path->peer->su,
10169 buf,
10170 SU_ADDRSTRLEN));
c949c771
DA
10171 json_object_string_addf(json_peer, "routerId", "%pI4",
10172 &path->peer->remote_id);
05864da7
DS
10173
10174 if (path->peer->hostname)
10175 json_object_string_add(json_peer, "hostname",
10176 path->peer->hostname);
10177
10178 if (path->peer->domainname)
10179 json_object_string_add(json_peer, "domainname",
10180 path->peer->domainname);
10181
10182 if (path->peer->conf_if)
10183 json_object_string_add(json_peer, "interface",
10184 path->peer->conf_if);
10185 } else {
10186 if (path->peer->conf_if) {
10187 if (path->peer->hostname
892fedb6
DA
10188 && CHECK_FLAG(path->peer->bgp->flags,
10189 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10190 vty_out(vty, " from %s(%s)",
10191 path->peer->hostname,
10192 path->peer->conf_if);
d62a17ae 10193 else
05864da7 10194 vty_out(vty, " from %s",
9b6d8fcf 10195 path->peer->conf_if);
d62a17ae 10196 } else {
05864da7 10197 if (path->peer->hostname
892fedb6
DA
10198 && CHECK_FLAG(path->peer->bgp->flags,
10199 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10200 vty_out(vty, " from %s(%s)",
10201 path->peer->hostname,
10202 path->peer->host);
d62a17ae 10203 else
05864da7
DS
10204 vty_out(vty, " from %s",
10205 sockunion2str(&path->peer->su,
10206 buf,
10207 SU_ADDRSTRLEN));
d62a17ae 10208 }
d62a17ae 10209
05864da7 10210 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10211 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10212 else
10213 vty_out(vty, " (%s)",
10214 inet_ntop(AF_INET,
10215 &path->peer->remote_id, buf1,
10216 sizeof(buf1)));
d62a17ae 10217 }
05864da7 10218 }
9df8b37c 10219
05864da7
DS
10220 /*
10221 * Note when vrfid of nexthop is different from that of prefix
10222 */
10223 if (path->extra && path->extra->bgp_orig) {
10224 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10225
05864da7
DS
10226 if (json_paths) {
10227 const char *vn;
9df8b37c 10228
05864da7
DS
10229 if (path->extra->bgp_orig->inst_type
10230 == BGP_INSTANCE_TYPE_DEFAULT)
10231 vn = VRF_DEFAULT_NAME;
10232 else
10233 vn = path->extra->bgp_orig->name;
9df8b37c 10234
05864da7 10235 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10236
05864da7
DS
10237 if (nexthop_vrfid == VRF_UNKNOWN) {
10238 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10239 } else {
05864da7
DS
10240 json_object_int_add(json_path, "nhVrfId",
10241 (int)nexthop_vrfid);
9df8b37c 10242 }
05864da7
DS
10243 } else {
10244 if (nexthop_vrfid == VRF_UNKNOWN)
10245 vty_out(vty, " vrf ?");
137147c6
DS
10246 else {
10247 struct vrf *vrf;
10248
10249 vrf = vrf_lookup_by_id(nexthop_vrfid);
10250 vty_out(vty, " vrf %s(%u)",
10251 VRF_LOGNAME(vrf), nexthop_vrfid);
10252 }
9df8b37c 10253 }
05864da7 10254 }
9df8b37c 10255
05864da7
DS
10256 if (nexthop_self) {
10257 if (json_paths) {
10258 json_object_boolean_true_add(json_path,
10259 "announceNexthopSelf");
10260 } else {
10261 vty_out(vty, " announce-nh-self");
9df8b37c 10262 }
05864da7 10263 }
9df8b37c 10264
05864da7
DS
10265 if (!json_paths)
10266 vty_out(vty, "\n");
d62a17ae 10267
05864da7
DS
10268 /* display the link-local nexthop */
10269 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10270 if (json_paths) {
10271 json_nexthop_ll = json_object_new_object();
c949c771
DA
10272 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10273 &attr->mp_nexthop_local);
515c2602 10274
939a97f4 10275 if (path->peer->hostname)
515c2602
DA
10276 json_object_string_add(json_nexthop_ll,
10277 "hostname",
939a97f4 10278 path->peer->hostname);
515c2602 10279
05864da7
DS
10280 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10281 json_object_string_add(json_nexthop_ll, "scope",
10282 "link-local");
d62a17ae 10283
05864da7
DS
10284 json_object_boolean_true_add(json_nexthop_ll,
10285 "accessible");
d62a17ae 10286
05864da7 10287 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10288 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10289 "used");
10290 else
10291 json_object_boolean_true_add(
10292 json_nexthop_global, "used");
10293 } else {
10294 vty_out(vty, " (%s) %s\n",
10295 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10296 buf, INET6_ADDRSTRLEN),
10297 attr->mp_nexthop_prefer_global
10298 ? "(prefer-global)"
10299 : "(used)");
d62a17ae 10300 }
05864da7
DS
10301 }
10302 /* If we do not have a link-local nexthop then we must flag the
10303 global as "used" */
10304 else {
10305 if (json_paths)
10306 json_object_boolean_true_add(json_nexthop_global,
10307 "used");
10308 }
d62a17ae 10309
b5e140c8 10310 if (safi == SAFI_EVPN &&
5e4d4c8a 10311 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10312 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10313 }
10314
05864da7
DS
10315 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10316 * Int/Ext/Local, Atomic, best */
10317 if (json_paths)
10318 json_object_string_add(json_path, "origin",
10319 bgp_origin_long_str[attr->origin]);
10320 else
10321 vty_out(vty, " Origin %s",
10322 bgp_origin_long_str[attr->origin]);
9df8b37c 10323
05864da7 10324 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10325 if (json_paths)
05864da7 10326 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10327 else
05864da7
DS
10328 vty_out(vty, ", metric %u", attr->med);
10329 }
9df8b37c 10330
05864da7
DS
10331 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10332 if (json_paths)
0fbac0b4 10333 json_object_int_add(json_path, "locPrf",
05864da7
DS
10334 attr->local_pref);
10335 else
10336 vty_out(vty, ", localpref %u", attr->local_pref);
10337 }
9df8b37c 10338
05864da7
DS
10339 if (attr->weight != 0) {
10340 if (json_paths)
10341 json_object_int_add(json_path, "weight", attr->weight);
10342 else
10343 vty_out(vty, ", weight %u", attr->weight);
10344 }
9df8b37c 10345
05864da7
DS
10346 if (attr->tag != 0) {
10347 if (json_paths)
10348 json_object_int_add(json_path, "tag", attr->tag);
10349 else
10350 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10351 }
9df8b37c 10352
05864da7
DS
10353 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10354 if (json_paths)
10355 json_object_boolean_false_add(json_path, "valid");
10356 else
10357 vty_out(vty, ", invalid");
10358 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10359 if (json_paths)
10360 json_object_boolean_true_add(json_path, "valid");
10361 else
10362 vty_out(vty, ", valid");
10363 }
9df8b37c 10364
7d3cae70
DA
10365 if (json_paths)
10366 json_object_int_add(json_path, "version", bn->version);
10367
05864da7
DS
10368 if (path->peer != bgp->peer_self) {
10369 if (path->peer->as == path->peer->local_as) {
10370 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10371 if (json_paths)
10372 json_object_string_add(
10373 json_peer, "type",
10374 "confed-internal");
d62a17ae 10375 else
05864da7 10376 vty_out(vty, ", confed-internal");
d62a17ae 10377 } else {
05864da7
DS
10378 if (json_paths)
10379 json_object_string_add(
10380 json_peer, "type", "internal");
10381 else
10382 vty_out(vty, ", internal");
9df8b37c 10383 }
05864da7
DS
10384 } else {
10385 if (bgp_confederation_peers_check(bgp,
10386 path->peer->as)) {
10387 if (json_paths)
10388 json_object_string_add(
10389 json_peer, "type",
10390 "confed-external");
d62a17ae 10391 else
05864da7 10392 vty_out(vty, ", confed-external");
d62a17ae 10393 } else {
05864da7
DS
10394 if (json_paths)
10395 json_object_string_add(
10396 json_peer, "type", "external");
10397 else
10398 vty_out(vty, ", external");
d62a17ae 10399 }
10400 }
05864da7
DS
10401 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10402 if (json_paths) {
10403 json_object_boolean_true_add(json_path, "aggregated");
10404 json_object_boolean_true_add(json_path, "local");
10405 } else {
10406 vty_out(vty, ", aggregated, local");
10407 }
10408 } else if (path->type != ZEBRA_ROUTE_BGP) {
10409 if (json_paths)
10410 json_object_boolean_true_add(json_path, "sourced");
10411 else
10412 vty_out(vty, ", sourced");
10413 } else {
10414 if (json_paths) {
10415 json_object_boolean_true_add(json_path, "sourced");
10416 json_object_boolean_true_add(json_path, "local");
10417 } else {
10418 vty_out(vty, ", sourced, local");
d62a17ae 10419 }
05864da7 10420 }
718e3744 10421
05864da7 10422 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10423 if (json_paths)
05864da7
DS
10424 json_object_boolean_true_add(json_path,
10425 "atomicAggregate");
d62a17ae 10426 else
05864da7
DS
10427 vty_out(vty, ", atomic-aggregate");
10428 }
d62a17ae 10429
05864da7
DS
10430 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10431 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10432 && bgp_path_info_mpath_count(path))) {
10433 if (json_paths)
10434 json_object_boolean_true_add(json_path, "multipath");
10435 else
10436 vty_out(vty, ", multipath");
10437 }
50e05855 10438
05864da7
DS
10439 // Mark the bestpath(s)
10440 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10441 first_as = aspath_get_first_as(attr->aspath);
718e3744 10442
05864da7
DS
10443 if (json_paths) {
10444 if (!json_bestpath)
10445 json_bestpath = json_object_new_object();
10446 json_object_int_add(json_bestpath, "bestpathFromAs",
10447 first_as);
10448 } else {
10449 if (first_as)
10450 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10451 else
05864da7 10452 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10453 }
05864da7 10454 }
718e3744 10455
05864da7
DS
10456 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10457 if (json_paths) {
10458 if (!json_bestpath)
10459 json_bestpath = json_object_new_object();
10460 json_object_boolean_true_add(json_bestpath, "overall");
10461 json_object_string_add(
10462 json_bestpath, "selectionReason",
10463 bgp_path_selection_reason2str(bn->reason));
10464 } else {
10465 vty_out(vty, ", best");
10466 vty_out(vty, " (%s)",
10467 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10468 }
05864da7 10469 }
718e3744 10470
4027d19b 10471 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10472 if (json_paths)
10473 json_object_string_add(
10474 json_path, "rpkiValidationState",
4027d19b 10475 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10476 else
1d327209 10477 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10478 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10479 }
10480
05864da7
DS
10481 if (json_bestpath)
10482 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10483
05864da7
DS
10484 if (!json_paths)
10485 vty_out(vty, "\n");
10486
10487 /* Line 4 display Community */
29e72930 10488 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10489 if (json_paths) {
10490 if (!attr->community->json)
10491 community_str(attr->community, true);
10492 json_object_lock(attr->community->json);
10493 json_object_object_add(json_path, "community",
10494 attr->community->json);
10495 } else {
10496 vty_out(vty, " Community: %s\n",
10497 attr->community->str);
d62a17ae 10498 }
05864da7 10499 }
718e3744 10500
05864da7
DS
10501 /* Line 5 display Extended-community */
10502 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10503 if (json_paths) {
10504 json_ext_community = json_object_new_object();
b53e67a3
DA
10505 json_object_string_add(
10506 json_ext_community, "string",
10507 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10508 json_object_object_add(json_path, "extendedCommunity",
10509 json_ext_community);
d62a17ae 10510 } else {
05864da7 10511 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10512 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10513 }
05864da7 10514 }
718e3744 10515
05864da7
DS
10516 /* Line 6 display Large community */
10517 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10518 if (json_paths) {
10519 if (!attr->lcommunity->json)
10520 lcommunity_str(attr->lcommunity, true);
10521 json_object_lock(attr->lcommunity->json);
10522 json_object_object_add(json_path, "largeCommunity",
10523 attr->lcommunity->json);
10524 } else {
10525 vty_out(vty, " Large Community: %s\n",
10526 attr->lcommunity->str);
d62a17ae 10527 }
05864da7 10528 }
718e3744 10529
05864da7
DS
10530 /* Line 7 display Originator, Cluster-id */
10531 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10532 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10533 char buf[BUFSIZ] = {0};
10534
05864da7 10535 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10536 if (json_paths)
c949c771
DA
10537 json_object_string_addf(json_path,
10538 "originatorId", "%pI4",
10539 &attr->originator_id);
d62a17ae 10540 else
23d0a753
DA
10541 vty_out(vty, " Originator: %pI4",
10542 &attr->originator_id);
d62a17ae 10543 }
856ca177 10544
05864da7 10545 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10546 struct cluster_list *cluster =
10547 bgp_attr_get_cluster(attr);
05864da7 10548 int i;
d62a17ae 10549
10550 if (json_paths) {
05864da7
DS
10551 json_cluster_list = json_object_new_object();
10552 json_cluster_list_list =
10553 json_object_new_array();
10554
779fee93 10555 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10556 json_string = json_object_new_string(
779fee93
DS
10557 inet_ntop(AF_INET,
10558 &cluster->list[i],
10559 buf, sizeof(buf)));
05864da7
DS
10560 json_object_array_add(
10561 json_cluster_list_list,
10562 json_string);
10563 }
718e3744 10564
05864da7
DS
10565 /*
10566 * struct cluster_list does not have
10567 * "str" variable like aspath and community
10568 * do. Add this someday if someone asks
10569 * for it.
10570 * json_object_string_add(json_cluster_list,
779fee93 10571 * "string", cluster->str);
05864da7
DS
10572 */
10573 json_object_object_add(json_cluster_list,
10574 "list",
10575 json_cluster_list_list);
10576 json_object_object_add(json_path, "clusterList",
10577 json_cluster_list);
0dc8ee70 10578 } else {
05864da7
DS
10579 vty_out(vty, ", Cluster list: ");
10580
779fee93 10581 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10582 vty_out(vty, "%pI4 ",
779fee93 10583 &cluster->list[i]);
05864da7 10584 }
0dc8ee70 10585 }
d62a17ae 10586 }
718e3744 10587
d62a17ae 10588 if (!json_paths)
10589 vty_out(vty, "\n");
05864da7 10590 }
d62a17ae 10591
05864da7 10592 if (path->extra && path->extra->damp_info)
b4f7f45b 10593 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10594
05864da7
DS
10595 /* Remote Label */
10596 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10597 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10598 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10599
05864da7
DS
10600 if (json_paths)
10601 json_object_int_add(json_path, "remoteLabel", label);
10602 else
10603 vty_out(vty, " Remote label: %d\n", label);
10604 }
d62a17ae 10605
e496b420
HS
10606 /* Remote SID */
10607 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10608 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10609 if (json_paths)
10610 json_object_string_add(json_path, "remoteSid", buf);
10611 else
10612 vty_out(vty, " Remote SID: %s\n", buf);
10613 }
10614
05864da7
DS
10615 /* Label Index */
10616 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10617 if (json_paths)
10618 json_object_int_add(json_path, "labelIndex",
10619 attr->label_index);
10620 else
10621 vty_out(vty, " Label Index: %d\n",
10622 attr->label_index);
10623 }
d62a17ae 10624
05864da7
DS
10625 /* Line 8 display Addpath IDs */
10626 if (path->addpath_rx_id
10627 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10628 if (json_paths) {
10629 json_object_int_add(json_path, "addpathRxId",
10630 path->addpath_rx_id);
d62a17ae 10631
05864da7
DS
10632 /* Keep backwards compatibility with the old API
10633 * by putting TX All's ID in the old field
10634 */
10635 json_object_int_add(
10636 json_path, "addpathTxId",
10637 path->tx_addpath
10638 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10639
05864da7
DS
10640 /* ... but create a specific field for each
10641 * strategy
10642 */
10643 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10644 json_object_int_add(
10645 json_path,
10646 bgp_addpath_names(i)->id_json_name,
10647 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10648 }
05864da7
DS
10649 } else {
10650 vty_out(vty, " AddPath ID: RX %u, ",
10651 path->addpath_rx_id);
d62a17ae 10652
05864da7 10653 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10654 }
05864da7 10655 }
520d5d76 10656
05864da7
DS
10657 /* If we used addpath to TX a non-bestpath we need to display
10658 * "Advertised to" on a path-by-path basis
10659 */
10660 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10661 first = 1;
dcc68b5e 10662
05864da7
DS
10663 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10664 addpath_capable =
10665 bgp_addpath_encode_tx(peer, afi, safi);
10666 has_adj = bgp_adj_out_lookup(
10667 peer, path->net,
10668 bgp_addpath_id_for_peer(peer, afi, safi,
10669 &path->tx_addpath));
10670
10671 if ((addpath_capable && has_adj)
10672 || (!addpath_capable && has_adj
10673 && CHECK_FLAG(path->flags,
10674 BGP_PATH_SELECTED))) {
10675 if (json_path && !json_adv_to)
10676 json_adv_to = json_object_new_object();
dcc68b5e 10677
05864da7
DS
10678 route_vty_out_advertised_to(
10679 vty, peer, &first,
10680 " Advertised to:", json_adv_to);
d62a17ae 10681 }
10682 }
718e3744 10683
05864da7
DS
10684 if (json_path) {
10685 if (json_adv_to) {
10686 json_object_object_add(
10687 json_path, "advertisedTo", json_adv_to);
d62a17ae 10688 }
05864da7
DS
10689 } else {
10690 if (!first) {
10691 vty_out(vty, "\n");
d62a17ae 10692 }
10693 }
05864da7 10694 }
b05a1c8b 10695
05864da7
DS
10696 /* Line 9 display Uptime */
10697 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10698 if (json_paths) {
10699 json_last_update = json_object_new_object();
10700 json_object_int_add(json_last_update, "epoch", tbuf);
10701 json_object_string_add(json_last_update, "string",
10702 ctime(&tbuf));
10703 json_object_object_add(json_path, "lastUpdate",
10704 json_last_update);
10705 } else
10706 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10707
05864da7
DS
10708 /* Line 10 display PMSI tunnel attribute, if present */
10709 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10710 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10711 bgp_attr_get_pmsi_tnl_type(attr),
10712 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10713
05864da7
DS
10714 if (json_paths) {
10715 json_pmsi = json_object_new_object();
10716 json_object_string_add(json_pmsi, "tunnelType", str);
10717 json_object_int_add(json_pmsi, "label",
10718 label2vni(&attr->label));
10719 json_object_object_add(json_path, "pmsi", json_pmsi);
10720 } else
10721 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10722 str, label2vni(&attr->label));
d62a17ae 10723 }
f1aa5d8a 10724
848e8cf6
DA
10725 if (path->peer->t_gr_restart &&
10726 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10727 unsigned long gr_remaining =
10728 thread_timer_remain_second(path->peer->t_gr_restart);
10729
10730 if (json_paths) {
10731 json_object_int_add(json_path,
10732 "gracefulRestartSecondsRemaining",
10733 gr_remaining);
10734 } else
10735 vty_out(vty,
10736 " Time until Graceful Restart stale route deleted: %lu\n",
10737 gr_remaining);
10738 }
10739
48ebba04
DA
10740 if (path->peer->t_llgr_stale[afi][safi] && attr->community &&
10741 community_include(attr->community, COMMUNITY_LLGR_STALE)) {
10742 unsigned long llgr_remaining = thread_timer_remain_second(
10743 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10744
48ebba04
DA
10745 if (json_paths) {
10746 json_object_int_add(json_path, "llgrSecondsRemaining",
10747 llgr_remaining);
10748 } else
10749 vty_out(vty,
10750 " Time until Long-lived stale route deleted: %lu\n",
10751 llgr_remaining);
10752 }
10753
92269aa2
DS
10754 /* Output some debug about internal state of the dest flags */
10755 if (json_paths) {
10756 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10757 json_object_boolean_true_add(json_path, "processScheduled");
10758 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10759 json_object_boolean_true_add(json_path, "userCleared");
10760 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10761 json_object_boolean_true_add(json_path, "labelChanged");
10762 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10763 json_object_boolean_true_add(json_path, "registeredForLabel");
10764 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10765 json_object_boolean_true_add(json_path, "selectDefered");
10766 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10767 json_object_boolean_true_add(json_path, "fibInstalled");
10768 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10769 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10770
d62a17ae 10771 if (json_nexthop_global || json_nexthop_ll) {
10772 json_nexthops = json_object_new_array();
f1aa5d8a 10773
d62a17ae 10774 if (json_nexthop_global)
10775 json_object_array_add(json_nexthops,
10776 json_nexthop_global);
f1aa5d8a 10777
d62a17ae 10778 if (json_nexthop_ll)
10779 json_object_array_add(json_nexthops,
10780 json_nexthop_ll);
f1aa5d8a 10781
d62a17ae 10782 json_object_object_add(json_path, "nexthops",
10783 json_nexthops);
10784 }
10785
10786 json_object_object_add(json_path, "peer", json_peer);
10787 json_object_array_add(json_paths, json_path);
05864da7 10788 }
b366b518
BB
10789}
10790
96ade3ed 10791#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10792#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10793#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10794
a4d82a8a 10795static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10796 afi_t afi, safi_t safi, enum bgp_show_type type,
10797 bool use_json);
7f323236
DW
10798static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10799 const char *comstr, int exact, afi_t afi,
96c81f66 10800 safi_t safi, uint16_t show_flags);
d62a17ae 10801
1ae44dfc 10802static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10803 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10804 void *output_arg, const char *rd, int is_last,
96f3485c 10805 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10806 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10807 enum rpki_states rpki_target_state)
d62a17ae 10808{
40381db7 10809 struct bgp_path_info *pi;
9bcb3eef 10810 struct bgp_dest *dest;
2aad8c42
MS
10811 bool header = true;
10812 bool json_detail_header = false;
d62a17ae 10813 int display;
1ae44dfc
LB
10814 unsigned long output_count = 0;
10815 unsigned long total_count = 0;
d62a17ae 10816 struct prefix *p;
d62a17ae 10817 json_object *json_paths = NULL;
10818 int first = 1;
96f3485c
MK
10819 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10820 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10821 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10822
1ae44dfc 10823 if (output_cum && *output_cum != 0)
2aad8c42 10824 header = false;
1ae44dfc 10825
9386b588 10826 if (use_json && !*json_header_depth) {
96f3485c
MK
10827 if (all)
10828 *json_header_depth = 1;
10829 else {
10830 vty_out(vty, "{\n");
10831 *json_header_depth = 2;
10832 }
10833
d62a17ae 10834 vty_out(vty,
23d0a753
DA
10835 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10836 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10837 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10838 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10839 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10840 ? VRF_DEFAULT_NAME
10841 : bgp->name,
10842 table->version, &bgp->router_id,
01eced22 10843 bgp->default_local_pref, bgp->as);
9386b588 10844 if (rd) {
445c2480 10845 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10846 ++*json_header_depth;
10847 }
d62a17ae 10848 }
718e3744 10849
445c2480
DS
10850 if (use_json && rd) {
10851 vty_out(vty, " \"%s\" : { ", rd);
10852 }
10853
2aad8c42
MS
10854 /* Check for 'json detail', where we need header output once per dest */
10855 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10856 type != bgp_show_type_dampend_paths &&
10857 type != bgp_show_type_damp_neighbor &&
10858 type != bgp_show_type_flap_statistics &&
10859 type != bgp_show_type_flap_neighbor)
10860 json_detail_header = true;
10861
d62a17ae 10862 /* Start processing of routes. */
9bcb3eef
DS
10863 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10864 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10865 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10866 bool json_detail = json_detail_header;
b54892e0 10867
9bcb3eef 10868 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10869 if (pi == NULL)
98ce9a06 10870 continue;
d62a17ae 10871
98ce9a06 10872 display = 0;
98ce9a06
DS
10873 if (use_json)
10874 json_paths = json_object_new_array();
10875 else
10876 json_paths = NULL;
d62a17ae 10877
6f94b685 10878 for (; pi; pi = pi->next) {
98ce9a06 10879 total_count++;
1e2ce4f1 10880
7d3cae70
DA
10881 if (type == bgp_show_type_prefix_version) {
10882 uint32_t version =
10883 strtoul(output_arg, NULL, 10);
10884 if (dest->version < version)
10885 continue;
10886 }
10887
a70a28a5
DA
10888 if (type == bgp_show_type_community_alias) {
10889 char *alias = output_arg;
10890 char **communities;
10891 int num;
10892 bool found = false;
10893
10894 if (pi->attr->community) {
10895 frrstr_split(pi->attr->community->str,
10896 " ", &communities, &num);
10897 for (int i = 0; i < num; i++) {
10898 const char *com2alias =
10899 bgp_community2alias(
10900 communities[i]);
cd9cc0e6
IR
10901 if (!found
10902 && strcmp(alias, com2alias)
10903 == 0)
a70a28a5 10904 found = true;
cd9cc0e6
IR
10905 XFREE(MTYPE_TMP,
10906 communities[i]);
a70a28a5 10907 }
cd9cc0e6 10908 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10909 }
10910
10911 if (!found && pi->attr->lcommunity) {
10912 frrstr_split(pi->attr->lcommunity->str,
10913 " ", &communities, &num);
10914 for (int i = 0; i < num; i++) {
10915 const char *com2alias =
10916 bgp_community2alias(
10917 communities[i]);
cd9cc0e6
IR
10918 if (!found
10919 && strcmp(alias, com2alias)
10920 == 0)
a70a28a5 10921 found = true;
cd9cc0e6
IR
10922 XFREE(MTYPE_TMP,
10923 communities[i]);
a70a28a5 10924 }
cd9cc0e6 10925 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10926 }
10927
10928 if (!found)
10929 continue;
10930 }
10931
1e2ce4f1
DS
10932 if (type == bgp_show_type_rpki) {
10933 if (dest_p->family == AF_INET
10934 || dest_p->family == AF_INET6)
4027d19b 10935 rpki_curr_state = hook_call(
1e2ce4f1
DS
10936 bgp_rpki_prefix_status,
10937 pi->peer, pi->attr, dest_p);
4027d19b
DS
10938 if (rpki_target_state != RPKI_NOT_BEING_USED
10939 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10940 continue;
10941 }
10942
98ce9a06
DS
10943 if (type == bgp_show_type_flap_statistics
10944 || type == bgp_show_type_flap_neighbor
10945 || type == bgp_show_type_dampend_paths
10946 || type == bgp_show_type_damp_neighbor) {
40381db7 10947 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10948 continue;
10949 }
10950 if (type == bgp_show_type_regexp) {
10951 regex_t *regex = output_arg;
d62a17ae 10952
40381db7 10953 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10954 == REG_NOMATCH)
10955 continue;
10956 }
10957 if (type == bgp_show_type_prefix_list) {
10958 struct prefix_list *plist = output_arg;
d62a17ae 10959
9bcb3eef 10960 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10961 != PREFIX_PERMIT)
10962 continue;
10963 }
10964 if (type == bgp_show_type_filter_list) {
10965 struct as_list *as_list = output_arg;
d62a17ae 10966
40381db7 10967 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10968 != AS_FILTER_PERMIT)
10969 continue;
10970 }
10971 if (type == bgp_show_type_route_map) {
10972 struct route_map *rmap = output_arg;
9b6d8fcf 10973 struct bgp_path_info path;
98ce9a06 10974 struct attr dummy_attr;
b68885f9 10975 route_map_result_t ret;
d62a17ae 10976
6f4f49b2 10977 dummy_attr = *pi->attr;
d62a17ae 10978
40381db7 10979 path.peer = pi->peer;
9b6d8fcf 10980 path.attr = &dummy_attr;
d62a17ae 10981
1782514f 10982 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 10983 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
10984 if (ret == RMAP_DENYMATCH)
10985 continue;
10986 }
10987 if (type == bgp_show_type_neighbor
10988 || type == bgp_show_type_flap_neighbor
10989 || type == bgp_show_type_damp_neighbor) {
10990 union sockunion *su = output_arg;
10991
40381db7
DS
10992 if (pi->peer == NULL
10993 || pi->peer->su_remote == NULL
10994 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10995 continue;
10996 }
10997 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10998 uint32_t destination;
d62a17ae 10999
9bcb3eef 11000 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11001 if (IN_CLASSC(destination)
9bcb3eef 11002 && dest_p->prefixlen == 24)
98ce9a06
DS
11003 continue;
11004 if (IN_CLASSB(destination)
9bcb3eef 11005 && dest_p->prefixlen == 16)
98ce9a06
DS
11006 continue;
11007 if (IN_CLASSA(destination)
9bcb3eef 11008 && dest_p->prefixlen == 8)
98ce9a06
DS
11009 continue;
11010 }
11011 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11012 p = output_arg;
9bcb3eef 11013 if (!prefix_match(p, dest_p))
98ce9a06
DS
11014 continue;
11015 }
11016 if (type == bgp_show_type_community_all) {
40381db7 11017 if (!pi->attr->community)
98ce9a06
DS
11018 continue;
11019 }
11020 if (type == bgp_show_type_community) {
11021 struct community *com = output_arg;
d62a17ae 11022
40381db7
DS
11023 if (!pi->attr->community
11024 || !community_match(pi->attr->community,
98ce9a06
DS
11025 com))
11026 continue;
11027 }
11028 if (type == bgp_show_type_community_exact) {
11029 struct community *com = output_arg;
d62a17ae 11030
40381db7
DS
11031 if (!pi->attr->community
11032 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
11033 continue;
11034 }
11035 if (type == bgp_show_type_community_list) {
11036 struct community_list *list = output_arg;
d62a17ae 11037
40381db7 11038 if (!community_list_match(pi->attr->community,
a4d82a8a 11039 list))
98ce9a06
DS
11040 continue;
11041 }
a4d82a8a 11042 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11043 struct community_list *list = output_arg;
d62a17ae 11044
98ce9a06 11045 if (!community_list_exact_match(
40381db7 11046 pi->attr->community, list))
98ce9a06
DS
11047 continue;
11048 }
11049 if (type == bgp_show_type_lcommunity) {
11050 struct lcommunity *lcom = output_arg;
d62a17ae 11051
40381db7
DS
11052 if (!pi->attr->lcommunity
11053 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
11054 lcom))
11055 continue;
11056 }
36a206db 11057
11058 if (type == bgp_show_type_lcommunity_exact) {
11059 struct lcommunity *lcom = output_arg;
11060
11061 if (!pi->attr->lcommunity
11062 || !lcommunity_cmp(pi->attr->lcommunity,
11063 lcom))
11064 continue;
11065 }
98ce9a06
DS
11066 if (type == bgp_show_type_lcommunity_list) {
11067 struct community_list *list = output_arg;
d62a17ae 11068
40381db7 11069 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 11070 list))
98ce9a06
DS
11071 continue;
11072 }
36a206db 11073 if (type
11074 == bgp_show_type_lcommunity_list_exact) {
11075 struct community_list *list = output_arg;
11076
11077 if (!lcommunity_list_exact_match(
11078 pi->attr->lcommunity, list))
11079 continue;
11080 }
98ce9a06 11081 if (type == bgp_show_type_lcommunity_all) {
40381db7 11082 if (!pi->attr->lcommunity)
98ce9a06
DS
11083 continue;
11084 }
11085 if (type == bgp_show_type_dampend_paths
11086 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11087 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11088 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11089 continue;
11090 }
11091
11092 if (!use_json && header) {
23d0a753
DA
11093 vty_out(vty,
11094 "BGP table version is %" PRIu64
11095 ", local router ID is %pI4, vrf id ",
11096 table->version, &bgp->router_id);
9df8b37c
PZ
11097 if (bgp->vrf_id == VRF_UNKNOWN)
11098 vty_out(vty, "%s", VRFID_NONE_STR);
11099 else
11100 vty_out(vty, "%u", bgp->vrf_id);
11101 vty_out(vty, "\n");
01eced22
AD
11102 vty_out(vty, "Default local pref %u, ",
11103 bgp->default_local_pref);
11104 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11105 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11106 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11107 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11108 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11109 if (type == bgp_show_type_dampend_paths
11110 || type == bgp_show_type_damp_neighbor)
98ce9a06 11111 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11112 else if (type == bgp_show_type_flap_statistics
11113 || type == bgp_show_type_flap_neighbor)
98ce9a06 11114 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11115 else
ae248832
MK
11116 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11117 : BGP_SHOW_HEADER));
2aad8c42
MS
11118 header = false;
11119
11120 } else if (json_detail && json_paths != NULL) {
11121 const struct prefix_rd *prd;
11122 json_object *jtemp;
11123
11124 /* Use common detail header, for most types;
11125 * need a json 'object'.
11126 */
11127
11128 jtemp = json_object_new_object();
11129 prd = bgp_rd_from_dest(dest, safi);
11130
11131 route_vty_out_detail_header(
11132 vty, bgp, dest, prd, table->afi,
11133 safi, jtemp);
11134
11135 json_object_array_add(json_paths, jtemp);
11136
11137 json_detail = false;
d62a17ae 11138 }
2aad8c42 11139
98ce9a06
DS
11140 if (rd != NULL && !display && !output_count) {
11141 if (!use_json)
11142 vty_out(vty,
11143 "Route Distinguisher: %s\n",
11144 rd);
d62a17ae 11145 }
98ce9a06
DS
11146 if (type == bgp_show_type_dampend_paths
11147 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11148 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11149 AFI_IP, safi, use_json,
11150 json_paths);
98ce9a06
DS
11151 else if (type == bgp_show_type_flap_statistics
11152 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11153 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11154 AFI_IP, safi, use_json,
11155 json_paths);
f280c93b
DA
11156 else {
11157 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11158 route_vty_out_detail(
11159 vty, bgp, dest, pi,
11160 family2afi(dest_p->family),
11161 safi, RPKI_NOT_BEING_USED,
11162 json_paths);
11163 else
11164 route_vty_out(vty, dest_p, pi, display,
11165 safi, json_paths, wide);
11166 }
98ce9a06 11167 display++;
d62a17ae 11168 }
11169
98ce9a06
DS
11170 if (display) {
11171 output_count++;
11172 if (!use_json)
11173 continue;
11174
625d2931 11175 /* encode prefix */
9bcb3eef 11176 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11177 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11178
1840384b 11179
b54892e0
DS
11180 bgp_fs_nlri_get_string(
11181 (unsigned char *)
9bcb3eef
DS
11182 dest_p->u.prefix_flowspec.ptr,
11183 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11184 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11185 family2afi(dest_p->u
11186 .prefix_flowspec.family));
625d2931 11187 if (first)
b54892e0 11188 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11189 dest_p->u.prefix_flowspec
b54892e0 11190 .prefixlen);
625d2931 11191 else
b54892e0 11192 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11193 dest_p->u.prefix_flowspec
b54892e0 11194 .prefixlen);
625d2931 11195 } else {
625d2931 11196 if (first)
1b78780b 11197 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11198 else
1b78780b 11199 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11200 }
3757f964 11201 vty_json(vty, json_paths);
449feb8e 11202 json_paths = NULL;
98ce9a06 11203 first = 0;
1f83ed02
DS
11204 } else
11205 json_object_free(json_paths);
98ce9a06
DS
11206 }
11207
1ae44dfc
LB
11208 if (output_cum) {
11209 output_count += *output_cum;
11210 *output_cum = output_count;
11211 }
11212 if (total_cum) {
11213 total_count += *total_cum;
11214 *total_cum = total_count;
11215 }
d62a17ae 11216 if (use_json) {
9386b588 11217 if (rd) {
a4d82a8a 11218 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11219 }
11220 if (is_last) {
a4d82a8a
PZ
11221 unsigned long i;
11222 for (i = 0; i < *json_header_depth; ++i)
11223 vty_out(vty, " } ");
96f3485c
MK
11224 if (!all)
11225 vty_out(vty, "\n");
9386b588 11226 }
d62a17ae 11227 } else {
1ae44dfc
LB
11228 if (is_last) {
11229 /* No route is displayed */
11230 if (output_count == 0) {
11231 if (type == bgp_show_type_normal)
11232 vty_out(vty,
11233 "No BGP prefixes displayed, %ld exist\n",
11234 total_count);
11235 } else
d62a17ae 11236 vty_out(vty,
1ae44dfc
LB
11237 "\nDisplayed %ld routes and %ld total paths\n",
11238 output_count, total_count);
11239 }
d62a17ae 11240 }
718e3744 11241
d62a17ae 11242 return CMD_SUCCESS;
718e3744 11243}
11244
1ae44dfc
LB
11245int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11246 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11247 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11248{
9bcb3eef 11249 struct bgp_dest *dest, *next;
1ae44dfc
LB
11250 unsigned long output_cum = 0;
11251 unsigned long total_cum = 0;
9386b588 11252 unsigned long json_header_depth = 0;
67009e22 11253 struct bgp_table *itable;
0136788c 11254 bool show_msg;
96c81f66 11255 uint16_t show_flags = 0;
0136788c
LB
11256
11257 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11258
96f3485c
MK
11259 if (use_json)
11260 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11261
9bcb3eef
DS
11262 for (dest = bgp_table_top(table); dest; dest = next) {
11263 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11264
9bcb3eef
DS
11265 next = bgp_route_next(dest);
11266 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11267 continue;
67009e22 11268
9bcb3eef 11269 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11270 if (itable != NULL) {
1ae44dfc 11271 struct prefix_rd prd;
06b9f471 11272 char rd[RD_ADDRSTRLEN];
1ae44dfc 11273
9bcb3eef 11274 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11275 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11276 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11277 rd, next == NULL, &output_cum,
11278 &total_cum, &json_header_depth,
1e2ce4f1 11279 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11280 if (next == NULL)
11281 show_msg = false;
1ae44dfc
LB
11282 }
11283 }
0136788c
LB
11284 if (show_msg) {
11285 if (output_cum == 0)
11286 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11287 total_cum);
11288 else
11289 vty_out(vty,
11290 "\nDisplayed %ld routes and %ld total paths\n",
11291 output_cum, total_cum);
11292 }
1ae44dfc
LB
11293 return CMD_SUCCESS;
11294}
2aad8c42 11295
d62a17ae 11296static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11297 enum bgp_show_type type, void *output_arg,
96c81f66 11298 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11299{
d62a17ae 11300 struct bgp_table *table;
9386b588 11301 unsigned long json_header_depth = 0;
96f3485c 11302 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11303
d62a17ae 11304 if (bgp == NULL) {
11305 bgp = bgp_get_default();
11306 }
fee0f4c6 11307
d62a17ae 11308 if (bgp == NULL) {
11309 if (!use_json)
11310 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11311 else
11312 vty_out(vty, "{}\n");
d62a17ae 11313 return CMD_WARNING;
11314 }
4dd6177e 11315
cd8c2a27
MS
11316 /* Labeled-unicast routes live in the unicast table. */
11317 if (safi == SAFI_LABELED_UNICAST)
11318 safi = SAFI_UNICAST;
11319
1ae44dfc 11320 table = bgp->rib[afi][safi];
d62a17ae 11321 /* use MPLS and ENCAP specific shows until they are merged */
11322 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11323 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11324 output_arg, use_json);
d62a17ae 11325 }
dba3c1d3
PG
11326
11327 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11328 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11329 output_arg, use_json,
11330 1, NULL, NULL);
11331 }
fee0f4c6 11332
96f3485c 11333 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11334 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11335 rpki_target_state);
fee0f4c6 11336}
11337
d62a17ae 11338static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11339 safi_t safi, uint16_t show_flags)
f186de26 11340{
d62a17ae 11341 struct listnode *node, *nnode;
11342 struct bgp *bgp;
11343 int is_first = 1;
9f049418 11344 bool route_output = false;
96f3485c 11345 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11346
d62a17ae 11347 if (use_json)
11348 vty_out(vty, "{\n");
9f689658 11349
d62a17ae 11350 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11351 route_output = true;
d62a17ae 11352 if (use_json) {
11353 if (!is_first)
11354 vty_out(vty, ",\n");
11355 else
11356 is_first = 0;
11357
11358 vty_out(vty, "\"%s\":",
11359 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11360 ? VRF_DEFAULT_NAME
d62a17ae 11361 : bgp->name);
11362 } else {
11363 vty_out(vty, "\nInstance %s:\n",
11364 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11365 ? VRF_DEFAULT_NAME
d62a17ae 11366 : bgp->name);
11367 }
11368 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11369 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11370 }
9f689658 11371
d62a17ae 11372 if (use_json)
11373 vty_out(vty, "}\n");
9f049418
DS
11374 else if (!route_output)
11375 vty_out(vty, "%% BGP instance not found\n");
f186de26 11376}
11377
718e3744 11378/* Header of detailed BGP route information */
d62a17ae 11379void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11380 struct bgp_dest *dest,
11381 const struct prefix_rd *prd,
d62a17ae 11382 afi_t afi, safi_t safi, json_object *json)
11383{
40381db7 11384 struct bgp_path_info *pi;
b54892e0 11385 const struct prefix *p;
d62a17ae 11386 struct peer *peer;
11387 struct listnode *node, *nnode;
06b9f471 11388 char buf1[RD_ADDRSTRLEN];
d62a17ae 11389 int count = 0;
11390 int best = 0;
11391 int suppress = 0;
c5f1e1b2
C
11392 int accept_own = 0;
11393 int route_filter_translated_v4 = 0;
11394 int route_filter_v4 = 0;
11395 int route_filter_translated_v6 = 0;
11396 int route_filter_v6 = 0;
11397 int llgr_stale = 0;
11398 int no_llgr = 0;
11399 int accept_own_nexthop = 0;
11400 int blackhole = 0;
d62a17ae 11401 int no_export = 0;
11402 int no_advertise = 0;
11403 int local_as = 0;
c5f1e1b2 11404 int no_peer = 0;
d62a17ae 11405 int first = 1;
11406 int has_valid_label = 0;
11407 mpls_label_t label = 0;
11408 json_object *json_adv_to = NULL;
9bedbb1e 11409
9bcb3eef
DS
11410 p = bgp_dest_get_prefix(dest);
11411 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11412
11413 if (has_valid_label)
9bcb3eef 11414 label = label_pton(&dest->local_label);
d62a17ae 11415
44c69747 11416 if (safi == SAFI_EVPN) {
d62a17ae 11417
44c69747 11418 if (!json) {
2dbe669b 11419 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11420 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11421 : "",
2dbe669b 11422 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11423 } else {
11424 json_object_string_add(json, "rd",
11425 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11426 "");
11427 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11428 }
11429 } else {
11430 if (!json) {
9119ef3a
DA
11431 vty_out(vty,
11432 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11433 "\n",
d62a17ae 11434 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11435 ? prefix_rd2str(prd, buf1,
11436 sizeof(buf1))
11437 : ""),
9119ef3a
DA
11438 safi == SAFI_MPLS_VPN ? ":" : "", p,
11439 dest->version);
cd1964ff 11440
9119ef3a 11441 } else {
67d7e256 11442 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11443 json_object_int_add(json, "version", dest->version);
11444
11445 }
44c69747
LK
11446 }
11447
11448 if (has_valid_label) {
11449 if (json)
11450 json_object_int_add(json, "localLabel", label);
11451 else
d62a17ae 11452 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11453 }
11454
11455 if (!json)
d62a17ae 11456 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11457 vty_out(vty, "not allocated\n");
718e3744 11458
9bcb3eef 11459 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11460 count++;
40381db7 11461 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11462 best = count;
4056a5f6 11463 if (bgp_path_suppressed(pi))
d62a17ae 11464 suppress = 1;
cee9c031 11465
40381db7 11466 if (pi->attr->community == NULL)
cee9c031
QY
11467 continue;
11468
11469 no_advertise += community_include(
40381db7
DS
11470 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11471 no_export += community_include(pi->attr->community,
cee9c031 11472 COMMUNITY_NO_EXPORT);
40381db7 11473 local_as += community_include(pi->attr->community,
cee9c031 11474 COMMUNITY_LOCAL_AS);
40381db7 11475 accept_own += community_include(pi->attr->community,
cee9c031
QY
11476 COMMUNITY_ACCEPT_OWN);
11477 route_filter_translated_v4 += community_include(
40381db7 11478 pi->attr->community,
cee9c031
QY
11479 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11480 route_filter_translated_v6 += community_include(
40381db7 11481 pi->attr->community,
cee9c031
QY
11482 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11483 route_filter_v4 += community_include(
40381db7 11484 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11485 route_filter_v6 += community_include(
40381db7
DS
11486 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11487 llgr_stale += community_include(pi->attr->community,
cee9c031 11488 COMMUNITY_LLGR_STALE);
40381db7 11489 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11490 COMMUNITY_NO_LLGR);
11491 accept_own_nexthop +=
40381db7 11492 community_include(pi->attr->community,
cee9c031 11493 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11494 blackhole += community_include(pi->attr->community,
cee9c031 11495 COMMUNITY_BLACKHOLE);
40381db7 11496 no_peer += community_include(pi->attr->community,
cee9c031 11497 COMMUNITY_NO_PEER);
d62a17ae 11498 }
718e3744 11499 }
718e3744 11500
d62a17ae 11501 if (!json) {
11502 vty_out(vty, "Paths: (%d available", count);
11503 if (best) {
11504 vty_out(vty, ", best #%d", best);
b84060bb
PG
11505 if (safi == SAFI_UNICAST) {
11506 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11507 vty_out(vty, ", table %s",
11508 VRF_DEFAULT_NAME);
11509 else
11510 vty_out(vty, ", vrf %s",
11511 bgp->name);
11512 }
d62a17ae 11513 } else
11514 vty_out(vty, ", no best path");
11515
c5f1e1b2
C
11516 if (accept_own)
11517 vty_out(vty,
11518 ", accept own local route exported and imported in different VRF");
11519 else if (route_filter_translated_v4)
11520 vty_out(vty,
11521 ", mark translated RTs for VPNv4 route filtering");
11522 else if (route_filter_v4)
11523 vty_out(vty,
11524 ", attach RT as-is for VPNv4 route filtering");
11525 else if (route_filter_translated_v6)
11526 vty_out(vty,
11527 ", mark translated RTs for VPNv6 route filtering");
11528 else if (route_filter_v6)
11529 vty_out(vty,
11530 ", attach RT as-is for VPNv6 route filtering");
11531 else if (llgr_stale)
11532 vty_out(vty,
1479ed2f 11533 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11534 else if (no_llgr)
11535 vty_out(vty,
11536 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11537 else if (accept_own_nexthop)
11538 vty_out(vty,
11539 ", accept local nexthop");
11540 else if (blackhole)
11541 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11542 else if (no_export)
11543 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11544 else if (no_advertise)
11545 vty_out(vty, ", not advertised to any peer");
d62a17ae 11546 else if (local_as)
11547 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11548 else if (no_peer)
11549 vty_out(vty,
11550 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11551
11552 if (suppress)
11553 vty_out(vty,
11554 ", Advertisements suppressed by an aggregate.");
11555 vty_out(vty, ")\n");
11556 }
718e3744 11557
d62a17ae 11558 /* If we are not using addpath then we can display Advertised to and
11559 * that will
11560 * show what peers we advertised the bestpath to. If we are using
11561 * addpath
11562 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11563 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11564 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11565 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11566 if (json && !json_adv_to)
11567 json_adv_to = json_object_new_object();
11568
11569 route_vty_out_advertised_to(
11570 vty, peer, &first,
11571 " Advertised to non peer-group peers:\n ",
11572 json_adv_to);
11573 }
11574 }
11575
11576 if (json) {
11577 if (json_adv_to) {
11578 json_object_object_add(json, "advertisedTo",
11579 json_adv_to);
11580 }
11581 } else {
11582 if (first)
11583 vty_out(vty, " Not advertised to any peer");
11584 vty_out(vty, "\n");
11585 }
11586 }
718e3744 11587}
11588
edfee30d 11589static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11590 struct bgp_dest *bgp_node, struct vty *vty,
11591 struct bgp *bgp, afi_t afi, safi_t safi,
11592 json_object *json, enum bgp_path_type pathtype,
4027d19b 11593 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11594{
11595 struct bgp_path_info *pi;
11596 int header = 1;
11597 char rdbuf[RD_ADDRSTRLEN];
11598 json_object *json_header = NULL;
11599 json_object *json_paths = NULL;
4933eaaf 11600 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11601
9bcb3eef 11602 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11603 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11604
11605 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11606 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11607 pi->peer, pi->attr, p);
4933eaaf 11608
4027d19b
DS
11609 if (rpki_target_state != RPKI_NOT_BEING_USED
11610 && rpki_curr_state != rpki_target_state)
4933eaaf 11611 continue;
44c69747
LK
11612
11613 if (json && !json_paths) {
11614 /* Instantiate json_paths only if path is valid */
11615 json_paths = json_object_new_array();
11616 if (pfx_rd) {
11617 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11618 json_header = json_object_new_object();
11619 } else
11620 json_header = json;
11621 }
11622
11623 if (header) {
11624 route_vty_out_detail_header(
11625 vty, bgp, bgp_node, pfx_rd,
11626 AFI_IP, safi, json_header);
11627 header = 0;
11628 }
11629 (*display)++;
11630
11631 if (pathtype == BGP_PATH_SHOW_ALL
11632 || (pathtype == BGP_PATH_SHOW_BESTPATH
11633 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11634 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11635 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11636 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11637 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11638 safi, rpki_curr_state, json_paths);
44c69747
LK
11639 }
11640
11641 if (json && json_paths) {
11642 json_object_object_add(json_header, "paths", json_paths);
11643
11644 if (pfx_rd)
11645 json_object_object_add(json, rdbuf, json_header);
11646 }
11647}
11648
2aad8c42
MS
11649/*
11650 * Return rd based on safi
11651 */
11652static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11653 safi_t safi)
11654{
11655 switch (safi) {
11656 case SAFI_MPLS_VPN:
11657 case SAFI_ENCAP:
11658 case SAFI_EVPN:
11659 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11660 default:
11661 return NULL;
11662
11663 }
11664}
11665
718e3744 11666/* Display specified route of BGP table. */
d62a17ae 11667static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11668 struct bgp_table *rib, const char *ip_str,
11669 afi_t afi, safi_t safi,
4027d19b 11670 enum rpki_states rpki_target_state,
d62a17ae 11671 struct prefix_rd *prd, int prefix_check,
9f049418 11672 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11673{
11674 int ret;
d62a17ae 11675 int display = 0;
11676 struct prefix match;
9bcb3eef
DS
11677 struct bgp_dest *dest;
11678 struct bgp_dest *rm;
d62a17ae 11679 struct bgp_table *table;
11680 json_object *json = NULL;
11681 json_object *json_paths = NULL;
11682
11683 /* Check IP address argument. */
11684 ret = str2prefix(ip_str, &match);
11685 if (!ret) {
11686 vty_out(vty, "address is malformed\n");
11687 return CMD_WARNING;
11688 }
718e3744 11689
d62a17ae 11690 match.family = afi2family(afi);
b05a1c8b 11691
44c69747 11692 if (use_json)
d62a17ae 11693 json = json_object_new_object();
718e3744 11694
44c69747 11695 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11696 for (dest = bgp_table_top(rib); dest;
11697 dest = bgp_route_next(dest)) {
11698 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11699
9bcb3eef 11700 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11701 continue;
9bcb3eef 11702 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11703 if (!table)
ea47320b 11704 continue;
d62a17ae 11705
4953391b
DA
11706 rm = bgp_node_match(table, &match);
11707 if (rm == NULL)
ea47320b 11708 continue;
d62a17ae 11709
9bcb3eef 11710 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11711 if (prefix_check
b54892e0 11712 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11713 bgp_dest_unlock_node(rm);
ea47320b
DL
11714 continue;
11715 }
d62a17ae 11716
9bcb3eef 11717 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11718 bgp, afi, safi, json, pathtype,
4027d19b 11719 &display, rpki_target_state);
44c69747 11720
9bcb3eef 11721 bgp_dest_unlock_node(rm);
44c69747
LK
11722 }
11723 } else if (safi == SAFI_EVPN) {
9bcb3eef 11724 struct bgp_dest *longest_pfx;
cded3b72 11725 bool is_exact_pfxlen_match = false;
44c69747 11726
9bcb3eef
DS
11727 for (dest = bgp_table_top(rib); dest;
11728 dest = bgp_route_next(dest)) {
11729 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11730
9bcb3eef 11731 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11732 continue;
9bcb3eef 11733 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11734 if (!table)
11735 continue;
11736
11737 longest_pfx = NULL;
cded3b72 11738 is_exact_pfxlen_match = false;
44c69747
LK
11739 /*
11740 * Search through all the prefixes for a match. The
11741 * pfx's are enumerated in ascending order of pfxlens.
11742 * So, the last pfx match is the longest match. Set
11743 * is_exact_pfxlen_match when we get exact pfxlen match
11744 */
11745 for (rm = bgp_table_top(table); rm;
11746 rm = bgp_route_next(rm)) {
b54892e0 11747 const struct prefix *rm_p =
9bcb3eef 11748 bgp_dest_get_prefix(rm);
44c69747
LK
11749 /*
11750 * Get prefixlen of the ip-prefix within type5
11751 * evpn route
11752 */
b54892e0
DS
11753 if (evpn_type5_prefix_match(rm_p, &match)
11754 && rm->info) {
44c69747
LK
11755 longest_pfx = rm;
11756 int type5_pfxlen =
b54892e0
DS
11757 bgp_evpn_get_type5_prefixlen(
11758 rm_p);
44c69747 11759 if (type5_pfxlen == match.prefixlen) {
cded3b72 11760 is_exact_pfxlen_match = true;
9bcb3eef 11761 bgp_dest_unlock_node(rm);
44c69747
LK
11762 break;
11763 }
d62a17ae 11764 }
11765 }
ea47320b 11766
44c69747
LK
11767 if (!longest_pfx)
11768 continue;
11769
11770 if (prefix_check && !is_exact_pfxlen_match)
11771 continue;
11772
11773 rm = longest_pfx;
9bcb3eef 11774 bgp_dest_lock_node(rm);
44c69747 11775
9bcb3eef 11776 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11777 bgp, afi, safi, json, pathtype,
4027d19b 11778 &display, rpki_target_state);
44c69747 11779
9bcb3eef 11780 bgp_dest_unlock_node(rm);
d62a17ae 11781 }
98a9dbc7 11782 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11783 if (use_json)
11784 json_paths = json_object_new_array();
11785
63a0b7a9
PG
11786 display = bgp_flowspec_display_match_per_ip(afi, rib,
11787 &match, prefix_check,
11788 vty,
11789 use_json,
11790 json_paths);
d5f20468
SP
11791 if (use_json) {
11792 if (display)
11793 json_object_object_add(json, "paths",
11794 json_paths);
11795 else
11796 json_object_free(json_paths);
11797 }
d62a17ae 11798 } else {
4953391b
DA
11799 dest = bgp_node_match(rib, &match);
11800 if (dest != NULL) {
9bcb3eef 11801 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11802 if (!prefix_check
9bcb3eef
DS
11803 || dest_p->prefixlen == match.prefixlen) {
11804 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11805 safi, json, pathtype,
4027d19b 11806 &display, rpki_target_state);
d62a17ae 11807 }
11808
9bcb3eef 11809 bgp_dest_unlock_node(dest);
d62a17ae 11810 }
11811 }
e5eee9af 11812
d62a17ae 11813 if (use_json) {
75eeda93 11814 vty_json(vty, json);
d62a17ae 11815 } else {
11816 if (!display) {
11817 vty_out(vty, "%% Network not in table\n");
11818 return CMD_WARNING;
11819 }
11820 }
b05a1c8b 11821
d62a17ae 11822 return CMD_SUCCESS;
718e3744 11823}
11824
fee0f4c6 11825/* Display specified route of Main RIB */
d62a17ae 11826static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11827 afi_t afi, safi_t safi, struct prefix_rd *prd,
11828 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11829 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11830{
9b86009a 11831 if (!bgp) {
d62a17ae 11832 bgp = bgp_get_default();
9b86009a
RW
11833 if (!bgp) {
11834 if (!use_json)
11835 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11836 else
11837 vty_out(vty, "{}\n");
9b86009a
RW
11838 return CMD_WARNING;
11839 }
11840 }
d62a17ae 11841
11842 /* labeled-unicast routes live in the unicast table */
11843 if (safi == SAFI_LABELED_UNICAST)
11844 safi = SAFI_UNICAST;
11845
11846 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11847 afi, safi, rpki_target_state, prd,
8aa22bbb 11848 prefix_check, pathtype, use_json);
d62a17ae 11849}
11850
11851static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11852 struct cmd_token **argv, bool exact, afi_t afi,
11853 safi_t safi, bool uj)
d62a17ae 11854{
11855 struct lcommunity *lcom;
11856 struct buffer *b;
11857 int i;
11858 char *str;
11859 int first = 0;
96c81f66 11860 uint16_t show_flags = 0;
4f28b2b5 11861 int ret;
96f3485c
MK
11862
11863 if (uj)
11864 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11865
11866 b = buffer_new(1024);
11867 for (i = 0; i < argc; i++) {
11868 if (first)
11869 buffer_putc(b, ' ');
11870 else {
11871 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11872 first = 1;
11873 buffer_putstr(b, argv[i]->arg);
11874 }
11875 }
11876 }
11877 buffer_putc(b, '\0');
57d187bc 11878
d62a17ae 11879 str = buffer_getstr(b);
11880 buffer_free(b);
57d187bc 11881
d62a17ae 11882 lcom = lcommunity_str2com(str);
11883 XFREE(MTYPE_TMP, str);
11884 if (!lcom) {
11885 vty_out(vty, "%% Large-community malformed\n");
11886 return CMD_WARNING;
11887 }
57d187bc 11888
4f28b2b5 11889 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11890 (exact ? bgp_show_type_lcommunity_exact
11891 : bgp_show_type_lcommunity),
11892 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11893
11894 lcommunity_free(&lcom);
11895 return ret;
57d187bc
JS
11896}
11897
d62a17ae 11898static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11899 const char *lcom, bool exact, afi_t afi,
11900 safi_t safi, bool uj)
57d187bc 11901{
d62a17ae 11902 struct community_list *list;
96c81f66 11903 uint16_t show_flags = 0;
96f3485c
MK
11904
11905 if (uj)
11906 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11907
57d187bc 11908
e237b0d2 11909 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11910 LARGE_COMMUNITY_LIST_MASTER);
11911 if (list == NULL) {
11912 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11913 lcom);
11914 return CMD_WARNING;
11915 }
57d187bc 11916
36a206db 11917 return bgp_show(vty, bgp, afi, safi,
11918 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11919 : bgp_show_type_lcommunity_list),
1e2ce4f1 11920 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11921}
11922
52951b63
DS
11923DEFUN (show_ip_bgp_large_community_list,
11924 show_ip_bgp_large_community_list_cmd,
77a3a95e 11925 "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
11926 SHOW_STR
11927 IP_STR
11928 BGP_STR
11929 BGP_INSTANCE_HELP_STR
9bedbb1e 11930 BGP_AFI_HELP_STR
4dd6177e 11931 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11932 "Display routes matching the large-community-list\n"
11933 "large-community-list number\n"
11934 "large-community-list name\n"
36a206db 11935 "Exact match of the large-communities\n"
52951b63
DS
11936 JSON_STR)
11937{
d62a17ae 11938 afi_t afi = AFI_IP6;
11939 safi_t safi = SAFI_UNICAST;
11940 int idx = 0;
36a206db 11941 bool exact_match = 0;
4d678463 11942 struct bgp *bgp = NULL;
9f049418 11943 bool uj = use_json(argc, argv);
d62a17ae 11944
ef3364f0
DA
11945 if (uj)
11946 argc--;
4d678463 11947
ef3364f0
DA
11948 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11949 &bgp, uj);
11950 if (!idx)
11951 return CMD_WARNING;
d62a17ae 11952
11953 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11954
11955 const char *clist_number_or_name = argv[++idx]->arg;
11956
11957 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11958 exact_match = 1;
11959
11960 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11961 exact_match, afi, safi, uj);
52951b63
DS
11962}
11963DEFUN (show_ip_bgp_large_community,
11964 show_ip_bgp_large_community_cmd,
36a206db 11965 "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
11966 SHOW_STR
11967 IP_STR
11968 BGP_STR
11969 BGP_INSTANCE_HELP_STR
9bedbb1e 11970 BGP_AFI_HELP_STR
4dd6177e 11971 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11972 "Display routes matching the large-communities\n"
11973 "List of large-community numbers\n"
36a206db 11974 "Exact match of the large-communities\n"
52951b63
DS
11975 JSON_STR)
11976{
d62a17ae 11977 afi_t afi = AFI_IP6;
11978 safi_t safi = SAFI_UNICAST;
11979 int idx = 0;
36a206db 11980 bool exact_match = 0;
4d678463 11981 struct bgp *bgp = NULL;
9f049418 11982 bool uj = use_json(argc, argv);
96c81f66 11983 uint16_t show_flags = 0;
d62a17ae 11984
96f3485c
MK
11985 if (uj) {
11986 argc--;
11987 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11988 }
4d678463 11989
96f3485c
MK
11990 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11991 &bgp, uj);
11992 if (!idx)
11993 return CMD_WARNING;
d62a17ae 11994
36a206db 11995 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11996 if (argv_find(argv, argc, "exact-match", &idx))
11997 exact_match = 1;
11998 return bgp_show_lcommunity(vty, bgp, argc, argv,
11999 exact_match, afi, safi, uj);
12000 } else
d62a17ae 12001 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12002 bgp_show_type_lcommunity_all, NULL, show_flags,
12003 RPKI_NOT_BEING_USED);
52951b63
DS
12004}
12005
71f1613a
DA
12006static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12007 safi_t safi, struct json_object *json_array);
d62a17ae 12008static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12009 safi_t safi, struct json_object *json);
e01ca200 12010
7b2ff250 12011
9ab0cf58
PG
12012DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12013 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12014 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12015 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12016{
12017 bool uj = use_json(argc, argv);
12018 struct bgp *bgp = NULL;
ec76a1d1
DA
12019 safi_t safi = SAFI_UNICAST;
12020 afi_t afi = AFI_IP6;
4265b261 12021 int idx = 0;
6c9d22e2
PG
12022 struct json_object *json_all = NULL;
12023 struct json_object *json_afi_safi = NULL;
4265b261
PG
12024
12025 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12026 &bgp, false);
71f1613a 12027 if (!idx)
4265b261 12028 return CMD_WARNING;
6c9d22e2 12029
4265b261 12030 if (uj)
6c9d22e2 12031 json_all = json_object_new_object();
4265b261 12032
9ab0cf58
PG
12033 FOREACH_AFI_SAFI (afi, safi) {
12034 /*
12035 * So limit output to those afi/safi pairs that
12036 * actually have something interesting in them
12037 */
12038 if (strmatch(get_afi_safi_str(afi, safi, true),
12039 "Unknown")) {
12040 continue;
12041 }
12042 if (uj) {
12043 json_afi_safi = json_object_new_array();
12044 json_object_object_add(
12045 json_all,
12046 get_afi_safi_str(afi, safi, true),
12047 json_afi_safi);
12048 } else {
12049 json_afi_safi = NULL;
6c9d22e2 12050 }
9ab0cf58
PG
12051
12052 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12053 }
6c9d22e2 12054
3757f964
DA
12055 if (uj)
12056 vty_json(vty, json_all);
6c9d22e2 12057
4265b261
PG
12058 return CMD_SUCCESS;
12059}
12060
7b2ff250 12061/* BGP route print out function without JSON */
14718643
PG
12062DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12063 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12064 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12065 SHOW_STR
12066 IP_STR
12067 BGP_STR
12068 BGP_INSTANCE_HELP_STR
12069 L2VPN_HELP_STR
12070 EVPN_HELP_STR
12071 "BGP RIB advertisement statistics\n"
12072 JSON_STR)
12073{
ec76a1d1
DA
12074 afi_t afi = AFI_IP6;
12075 safi_t safi = SAFI_UNICAST;
14718643
PG
12076 struct bgp *bgp = NULL;
12077 int idx = 0, ret;
12078 bool uj = use_json(argc, argv);
12079 struct json_object *json_afi_safi = NULL, *json = NULL;
12080
12081 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12082 &bgp, false);
12083 if (!idx)
12084 return CMD_WARNING;
12085
12086 if (uj)
12087 json_afi_safi = json_object_new_array();
12088 else
12089 json_afi_safi = NULL;
12090
12091 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12092
12093 if (uj) {
12094 json = json_object_new_object();
12095 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12096 json_afi_safi);
3757f964 12097 vty_json(vty, json);
14718643
PG
12098 }
12099 return ret;
12100}
12101
893cccd0 12102/* BGP route print out function without JSON */
9ab0cf58
PG
12103DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12104 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12105 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12106 "]]\
893cccd0 12107 statistics [json]",
9ab0cf58
PG
12108 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12109 BGP_SAFI_WITH_LABEL_HELP_STR
12110 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12111{
ec76a1d1
DA
12112 afi_t afi = AFI_IP6;
12113 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12114 struct bgp *bgp = NULL;
12115 int idx = 0, ret;
12116 bool uj = use_json(argc, argv);
6c9d22e2 12117 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12118
12119 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12120 &bgp, false);
12121 if (!idx)
12122 return CMD_WARNING;
6c9d22e2 12123
893cccd0 12124 if (uj)
6c9d22e2
PG
12125 json_afi_safi = json_object_new_array();
12126 else
12127 json_afi_safi = NULL;
12128
12129 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12130
12131 if (uj) {
12132 json = json_object_new_object();
12133 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12134 json_afi_safi);
3757f964 12135 vty_json(vty, json);
893cccd0
PG
12136 }
12137 return ret;
893cccd0 12138}
7b2ff250 12139
fe0f234d 12140DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12141 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12142 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12143 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12144 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12145 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12146 "Display the entries for all address families\n"
9ab0cf58
PG
12147 "Display detailed information about dampening\n"
12148 "Display detail of configured dampening parameters\n"
fe0f234d 12149 JSON_STR)
718e3744 12150{
d62a17ae 12151 afi_t afi = AFI_IP6;
12152 safi_t safi = SAFI_UNICAST;
d62a17ae 12153 struct bgp *bgp = NULL;
12154 int idx = 0;
96c81f66 12155 uint16_t show_flags = 0;
fe0f234d
RW
12156 bool uj = use_json(argc, argv);
12157
12158 if (uj) {
12159 argc--;
12160 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12161 }
96f3485c
MK
12162
12163 /* [<ipv4|ipv6> [all]] */
12164 if (all) {
12165 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12166 if (argv_find(argv, argc, "ipv4", &idx))
12167 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12168
12169 if (argv_find(argv, argc, "ipv6", &idx))
12170 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12171 }
d62a17ae 12172
12173 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12174 &bgp, false);
d62a17ae 12175 if (!idx)
12176 return CMD_WARNING;
12177
fe0f234d 12178 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12179}
12180
fe0f234d
RW
12181/* BGP route print out function */
12182DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12183 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12184 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12185 "]]\
96f3485c 12186 [all$all]\
cf4898bc
QY
12187 [cidr-only\
12188 |dampening <flap-statistics|dampened-paths>\
12189 |community [AA:NN|local-AS|no-advertise|no-export\
12190 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12191 |accept-own|accept-own-nexthop|route-filter-v6\
12192 |route-filter-v4|route-filter-translated-v6\
12193 |route-filter-translated-v4] [exact-match]\
70799983 12194 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12195 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12196 |prefix-list WORD\
bf1a944a 12197 |route-map WORD\
1e2ce4f1 12198 |rpki <invalid|valid|notfound>\
7d3cae70 12199 |version (1-4294967295)\
b4ad2fae 12200 |alias ALIAS_NAME\
39c3c736
RW
12201 |A.B.C.D/M longer-prefixes\
12202 |X:X::X:X/M longer-prefixes\
f280c93b 12203 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12204 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12205 BGP_SAFI_WITH_LABEL_HELP_STR
12206 "Display the entries for all address families\n"
12207 "Display only routes with non-natural netmasks\n"
12208 "Display detailed information about dampening\n"
12209 "Display flap statistics of routes\n"
12210 "Display paths suppressed due to dampening\n"
12211 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12212 "Do not send outside local AS (well-known community)\n"
12213 "Do not advertise to any peer (well-known community)\n"
12214 "Do not export to next AS (well-known community)\n"
12215 "Graceful shutdown (well-known community)\n"
12216 "Do not export to any peer (well-known community)\n"
12217 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12218 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12219 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12220 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12221 "Should accept VPN route with local nexthop (well-known community)\n"
12222 "RT VPNv6 route filtering (well-known community)\n"
12223 "RT VPNv4 route filtering (well-known community)\n"
12224 "RT translated VPNv6 route filtering (well-known community)\n"
12225 "RT translated VPNv4 route filtering (well-known community)\n"
12226 "Exact match of the communities\n"
70799983
RW
12227 "Community-list number\n"
12228 "Community-list name\n"
12229 "Display routes matching the community-list\n"
12230 "Exact match of the communities\n"
a7129347
RW
12231 "Display routes conforming to the filter-list\n"
12232 "Regular expression access list name\n"
6deaf579
RW
12233 "Display routes conforming to the prefix-list\n"
12234 "Prefix-list name\n"
bf1a944a
RW
12235 "Display routes matching the route-map\n"
12236 "A route-map to match on\n"
a70a28a5
DA
12237 "RPKI route types\n"
12238 "A valid path as determined by rpki\n"
12239 "A invalid path as determined by rpki\n"
12240 "A path that has no rpki data\n"
12241 "Display prefixes with matching version numbers\n"
12242 "Version number and above\n"
12243 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12244 "BGP community alias\n"
12245 "IPv4 prefix\n"
12246 "Display route and more specific routes\n"
12247 "IPv6 prefix\n"
12248 "Display route and more specific routes\n"
12249 JSON_STR
a70a28a5
DA
12250 "Display detailed version of JSON output\n"
12251 "Increase table width for longer prefixes\n")
7b2ff250
DW
12252{
12253 afi_t afi = AFI_IP6;
12254 safi_t safi = SAFI_UNICAST;
12255 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12256 void *output_arg = NULL;
7b2ff250
DW
12257 struct bgp *bgp = NULL;
12258 int idx = 0;
d0086e8e 12259 int exact_match = 0;
96f3485c
MK
12260 char *community = NULL;
12261 bool first = true;
96c81f66 12262 uint16_t show_flags = 0;
4027d19b 12263 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12264 struct prefix p;
96f3485c
MK
12265
12266 if (uj) {
9f049418 12267 argc--;
96f3485c
MK
12268 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12269 }
12270
f280c93b
DA
12271 if (detail)
12272 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12273
96f3485c
MK
12274 /* [<ipv4|ipv6> [all]] */
12275 if (all) {
12276 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12277
12278 if (argv_find(argv, argc, "ipv4", &idx))
12279 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12280
12281 if (argv_find(argv, argc, "ipv6", &idx))
12282 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12283 }
12284
12285 if (wide)
12286 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12287
12288 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12289 &bgp, uj);
7b2ff250
DW
12290 if (!idx)
12291 return CMD_WARNING;
12292
7b2ff250 12293 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12294 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12295
12296 if (argv_find(argv, argc, "dampening", &idx)) {
12297 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12298 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12299 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12300 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12301 }
12302
12303 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12304 char *maybecomm = NULL;
d0086e8e 12305
79bc257a
RW
12306 if (idx + 1 < argc) {
12307 if (argv[idx + 1]->type == VARIABLE_TKN)
12308 maybecomm = argv[idx + 1]->arg;
12309 else
12310 maybecomm = argv[idx + 1]->text;
12311 }
12312
cf4898bc
QY
12313 if (maybecomm && !strmatch(maybecomm, "json")
12314 && !strmatch(maybecomm, "exact-match"))
12315 community = maybecomm;
d0086e8e 12316
cf4898bc
QY
12317 if (argv_find(argv, argc, "exact-match", &idx))
12318 exact_match = 1;
d0086e8e 12319
96f3485c
MK
12320 if (!community)
12321 sh_type = bgp_show_type_community_all;
12322 }
12323
70799983
RW
12324 if (argv_find(argv, argc, "community-list", &idx)) {
12325 const char *clist_number_or_name = argv[++idx]->arg;
12326 struct community_list *list;
12327
12328 if (argv_find(argv, argc, "exact-match", &idx))
12329 exact_match = 1;
12330
12331 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12332 COMMUNITY_LIST_MASTER);
12333 if (list == NULL) {
12334 vty_out(vty,
12335 "%% %s is not a valid community-list name\n",
12336 clist_number_or_name);
12337 return CMD_WARNING;
12338 }
12339
12340 if (exact_match)
12341 sh_type = bgp_show_type_community_list_exact;
12342 else
12343 sh_type = bgp_show_type_community_list;
12344 output_arg = list;
12345 }
12346
a7129347
RW
12347 if (argv_find(argv, argc, "filter-list", &idx)) {
12348 const char *filter = argv[++idx]->arg;
12349 struct as_list *as_list;
12350
12351 as_list = as_list_lookup(filter);
12352 if (as_list == NULL) {
12353 vty_out(vty,
12354 "%% %s is not a valid AS-path access-list name\n",
12355 filter);
12356 return CMD_WARNING;
12357 }
12358
12359 sh_type = bgp_show_type_filter_list;
12360 output_arg = as_list;
12361 }
12362
6deaf579
RW
12363 if (argv_find(argv, argc, "prefix-list", &idx)) {
12364 const char *prefix_list_str = argv[++idx]->arg;
12365 struct prefix_list *plist;
12366
12367 plist = prefix_list_lookup(afi, prefix_list_str);
12368 if (plist == NULL) {
12369 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12370 prefix_list_str);
12371 return CMD_WARNING;
12372 }
12373
12374 sh_type = bgp_show_type_prefix_list;
12375 output_arg = plist;
12376 }
12377
bf1a944a
RW
12378 if (argv_find(argv, argc, "route-map", &idx)) {
12379 const char *rmap_str = argv[++idx]->arg;
12380 struct route_map *rmap;
12381
12382 rmap = route_map_lookup_by_name(rmap_str);
12383 if (!rmap) {
12384 vty_out(vty, "%% %s is not a valid route-map name\n",
12385 rmap_str);
12386 return CMD_WARNING;
12387 }
12388
12389 sh_type = bgp_show_type_route_map;
12390 output_arg = rmap;
12391 }
12392
1e2ce4f1
DS
12393 if (argv_find(argv, argc, "rpki", &idx)) {
12394 sh_type = bgp_show_type_rpki;
12395 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12396 rpki_target_state = RPKI_VALID;
1e2ce4f1 12397 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12398 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12399 }
12400
7d3cae70
DA
12401 /* Display prefixes with matching version numbers */
12402 if (argv_find(argv, argc, "version", &idx)) {
12403 sh_type = bgp_show_type_prefix_version;
2391833e 12404 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12405 }
12406
a70a28a5
DA
12407 /* Display prefixes with matching BGP community alias */
12408 if (argv_find(argv, argc, "alias", &idx)) {
12409 sh_type = bgp_show_type_community_alias;
2391833e 12410 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12411 }
12412
39c3c736
RW
12413 /* prefix-longer */
12414 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12415 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12416 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12417
12418 if (!str2prefix(prefix_str, &p)) {
12419 vty_out(vty, "%% Malformed Prefix\n");
12420 return CMD_WARNING;
12421 }
12422
12423 sh_type = bgp_show_type_prefix_longer;
12424 output_arg = &p;
a70a28a5
DA
12425 }
12426
96f3485c
MK
12427 if (!all) {
12428 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12429 if (community)
12430 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12431 exact_match, afi, safi,
12432 show_flags);
2391833e 12433 else
a70a28a5 12434 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12435 output_arg, show_flags,
a70a28a5 12436 rpki_target_state);
96f3485c
MK
12437 } else {
12438 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12439 * AFI_IP6 */
12440
12441 if (uj)
12442 vty_out(vty, "{\n");
12443
12444 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12445 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12446 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12447 ? AFI_IP
12448 : AFI_IP6;
12449 FOREACH_SAFI (safi) {
96f3485c
MK
12450 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12451 continue;
12452
12453 if (uj) {
12454 if (first)
12455 first = false;
12456 else
12457 vty_out(vty, ",\n");
12458 vty_out(vty, "\"%s\":{\n",
12459 get_afi_safi_str(afi, safi,
12460 true));
12461 } else
12462 vty_out(vty,
12463 "\nFor address family: %s\n",
12464 get_afi_safi_str(afi, safi,
12465 false));
12466
12467 if (community)
12468 bgp_show_community(vty, bgp, community,
12469 exact_match, afi,
12470 safi, show_flags);
12471 else
12472 bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12473 output_arg, show_flags,
4027d19b 12474 rpki_target_state);
96f3485c
MK
12475 if (uj)
12476 vty_out(vty, "}\n");
12477 }
12478 } else {
12479 /* show <ip> bgp all: for each AFI and SAFI*/
12480 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12481 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12482 continue;
12483
12484 if (uj) {
12485 if (first)
12486 first = false;
12487 else
12488 vty_out(vty, ",\n");
d0086e8e 12489
96f3485c
MK
12490 vty_out(vty, "\"%s\":{\n",
12491 get_afi_safi_str(afi, safi,
12492 true));
12493 } else
12494 vty_out(vty,
12495 "\nFor address family: %s\n",
12496 get_afi_safi_str(afi, safi,
12497 false));
12498
12499 if (community)
12500 bgp_show_community(vty, bgp, community,
12501 exact_match, afi,
12502 safi, show_flags);
12503 else
12504 bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12505 output_arg, show_flags,
4027d19b 12506 rpki_target_state);
96f3485c
MK
12507 if (uj)
12508 vty_out(vty, "}\n");
12509 }
12510 }
12511 if (uj)
12512 vty_out(vty, "}\n");
12513 }
12514 return CMD_SUCCESS;
a636c635 12515}
47fc97cc 12516
718e3744 12517DEFUN (show_ip_bgp_route,
12518 show_ip_bgp_route_cmd,
8aa22bbb 12519 "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 12520 SHOW_STR
12521 IP_STR
12522 BGP_STR
a636c635 12523 BGP_INSTANCE_HELP_STR
4f280b15 12524 BGP_AFI_HELP_STR
4dd6177e 12525 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12526 "Network in the BGP routing table to display\n"
0c7b1b01 12527 "IPv4 prefix\n"
8c3deaae 12528 "Network in the BGP routing table to display\n"
0c7b1b01 12529 "IPv6 prefix\n"
4092b06c 12530 "Display only the bestpath\n"
b05a1c8b 12531 "Display only multipaths\n"
8aa22bbb
DS
12532 "Display only paths that match the specified rpki state\n"
12533 "A valid path as determined by rpki\n"
12534 "A invalid path as determined by rpki\n"
12535 "A path that has no rpki data\n"
9973d184 12536 JSON_STR)
4092b06c 12537{
d62a17ae 12538 int prefix_check = 0;
ae19d7dd 12539
d62a17ae 12540 afi_t afi = AFI_IP6;
12541 safi_t safi = SAFI_UNICAST;
12542 char *prefix = NULL;
12543 struct bgp *bgp = NULL;
12544 enum bgp_path_type path_type;
9f049418 12545 bool uj = use_json(argc, argv);
b05a1c8b 12546
d62a17ae 12547 int idx = 0;
ae19d7dd 12548
d62a17ae 12549 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12550 &bgp, uj);
d62a17ae 12551 if (!idx)
12552 return CMD_WARNING;
c41247f5 12553
d62a17ae 12554 if (!bgp) {
12555 vty_out(vty,
12556 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12557 return CMD_WARNING;
12558 }
a636c635 12559
d62a17ae 12560 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12561 if (argv_find(argv, argc, "A.B.C.D", &idx)
12562 || argv_find(argv, argc, "X:X::X:X", &idx))
12563 prefix_check = 0;
12564 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12565 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12566 prefix_check = 1;
12567
12568 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12569 && afi != AFI_IP6) {
12570 vty_out(vty,
12571 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12572 return CMD_WARNING;
12573 }
12574 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12575 && afi != AFI_IP) {
12576 vty_out(vty,
12577 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12578 return CMD_WARNING;
12579 }
12580
12581 prefix = argv[idx]->arg;
12582
12583 /* [<bestpath|multipath>] */
12584 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12585 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12586 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12587 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12588 else
360660c6 12589 path_type = BGP_PATH_SHOW_ALL;
a636c635 12590
d62a17ae 12591 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12592 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12593}
12594
8c3deaae
QY
12595DEFUN (show_ip_bgp_regexp,
12596 show_ip_bgp_regexp_cmd,
3e5b31b3 12597 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12598 SHOW_STR
12599 IP_STR
12600 BGP_STR
b00b230a 12601 BGP_INSTANCE_HELP_STR
4f280b15 12602 BGP_AFI_HELP_STR
4dd6177e 12603 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12604 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12605 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12606 JSON_STR)
8c3deaae 12607{
d62a17ae 12608 afi_t afi = AFI_IP6;
12609 safi_t safi = SAFI_UNICAST;
12610 struct bgp *bgp = NULL;
3e5b31b3
DA
12611 bool uj = use_json(argc, argv);
12612 char *regstr = NULL;
8c3deaae 12613
d62a17ae 12614 int idx = 0;
12615 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12616 &bgp, false);
d62a17ae 12617 if (!idx)
12618 return CMD_WARNING;
8c3deaae 12619
d62a17ae 12620 // get index of regex
3e5b31b3
DA
12621 if (argv_find(argv, argc, "REGEX", &idx))
12622 regstr = argv[idx]->arg;
8c3deaae 12623
5f71d11c 12624 assert(regstr);
3e5b31b3
DA
12625 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12626 bgp_show_type_regexp, uj);
8c3deaae
QY
12627}
12628
ae248832 12629DEFPY (show_ip_bgp_instance_all,
a636c635 12630 show_ip_bgp_instance_all_cmd,
ae248832 12631 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12632 SHOW_STR
a636c635 12633 IP_STR
4092b06c 12634 BGP_STR
a636c635 12635 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12636 BGP_AFI_HELP_STR
4dd6177e 12637 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12638 JSON_STR
12639 "Increase table width for longer prefixes\n")
4092b06c 12640{
54d05dea 12641 afi_t afi = AFI_IP6;
d62a17ae 12642 safi_t safi = SAFI_UNICAST;
12643 struct bgp *bgp = NULL;
d62a17ae 12644 int idx = 0;
96c81f66 12645 uint16_t show_flags = 0;
ae19d7dd 12646
96f3485c 12647 if (uj) {
d62a17ae 12648 argc--;
96f3485c
MK
12649 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12650 }
12651
12652 if (wide)
12653 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12654
9f049418
DS
12655 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12656 &bgp, uj);
12657 if (!idx)
12658 return CMD_WARNING;
12659
96f3485c 12660 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12661 return CMD_SUCCESS;
e3e29b32
LB
12662}
12663
a4d82a8a 12664static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12665 afi_t afi, safi_t safi, enum bgp_show_type type,
12666 bool use_json)
718e3744 12667{
d62a17ae 12668 regex_t *regex;
12669 int rc;
96c81f66 12670 uint16_t show_flags = 0;
96f3485c
MK
12671
12672 if (use_json)
12673 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12674
c3900853 12675 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12676 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12677 regstr);
12678 return CMD_WARNING_CONFIG_FAILED;
12679 }
12680
d62a17ae 12681 regex = bgp_regcomp(regstr);
12682 if (!regex) {
12683 vty_out(vty, "Can't compile regexp %s\n", regstr);
12684 return CMD_WARNING;
12685 }
a636c635 12686
1e2ce4f1
DS
12687 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12688 RPKI_NOT_BEING_USED);
d62a17ae 12689 bgp_regex_free(regex);
12690 return rc;
e3e29b32
LB
12691}
12692
7f323236
DW
12693static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12694 const char *comstr, int exact, afi_t afi,
96c81f66 12695 safi_t safi, uint16_t show_flags)
d62a17ae 12696{
12697 struct community *com;
d62a17ae 12698 int ret = 0;
12699
7f323236 12700 com = community_str2com(comstr);
d62a17ae 12701 if (!com) {
7f323236 12702 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12703 return CMD_WARNING;
12704 }
12705
12706 ret = bgp_show(vty, bgp, afi, safi,
12707 (exact ? bgp_show_type_community_exact
12708 : bgp_show_type_community),
1e2ce4f1 12709 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12710 community_free(&com);
46c3ce83 12711
d62a17ae 12712 return ret;
718e3744 12713}
12714
d62a17ae 12715enum bgp_stats {
12716 BGP_STATS_MAXBITLEN = 0,
12717 BGP_STATS_RIB,
12718 BGP_STATS_PREFIXES,
12719 BGP_STATS_TOTPLEN,
12720 BGP_STATS_UNAGGREGATEABLE,
12721 BGP_STATS_MAX_AGGREGATEABLE,
12722 BGP_STATS_AGGREGATES,
12723 BGP_STATS_SPACE,
12724 BGP_STATS_ASPATH_COUNT,
12725 BGP_STATS_ASPATH_MAXHOPS,
12726 BGP_STATS_ASPATH_TOTHOPS,
12727 BGP_STATS_ASPATH_MAXSIZE,
12728 BGP_STATS_ASPATH_TOTSIZE,
12729 BGP_STATS_ASN_HIGHEST,
12730 BGP_STATS_MAX,
a636c635 12731};
2815e61f 12732
9ab0cf58 12733#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12734#define TABLE_STATS_IDX_JSON 1
12735
12736static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12737 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12738 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12739 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12740 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12741 "unaggregateablePrefixes"},
12742 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12743 "maximumAggregateablePrefixes"},
12744 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12745 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12746 [BGP_STATS_SPACE] = {"Address space advertised",
12747 "addressSpaceAdvertised"},
9ab0cf58
PG
12748 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12749 "advertisementsWithPaths"},
12750 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12751 "longestAsPath"},
12752 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12753 "largestAsPath"},
12754 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12755 "averageAsPathLengthHops"},
12756 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12757 "averageAsPathSizeBytes"},
12758 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12759 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12760};
2815e61f 12761
d62a17ae 12762struct bgp_table_stats {
12763 struct bgp_table *table;
12764 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12765 double total_space;
ff7924f6
PJ
12766};
12767
9bcb3eef 12768static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12769 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12770{
9bcb3eef 12771 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12772 struct bgp_path_info *pi;
b54892e0 12773 const struct prefix *rn_p;
d62a17ae 12774
9bcb3eef 12775 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12776 return;
d62a17ae 12777
9bcb3eef 12778 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12779 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12780 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12781
9c14ec72 12782 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12783 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12784 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12785
9bcb3eef 12786 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12787 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12788 /* announced address space */
12789 if (space)
b54892e0 12790 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12791 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12792 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12793
9c14ec72 12794
9bcb3eef 12795 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12796 ts->counts[BGP_STATS_RIB]++;
12797
05864da7
DS
12798 if (CHECK_FLAG(pi->attr->flag,
12799 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12800 ts->counts[BGP_STATS_AGGREGATES]++;
12801
12802 /* as-path stats */
05864da7 12803 if (pi->attr->aspath) {
9c14ec72
RW
12804 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12805 unsigned int size = aspath_size(pi->attr->aspath);
12806 as_t highest = aspath_highest(pi->attr->aspath);
12807
12808 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12809
12810 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12811 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12812
12813 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12814 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12815
12816 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12817 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12818 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12819 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12820 }
12821 }
12822}
12823
12824static int bgp_table_stats_walker(struct thread *t)
12825{
9bcb3eef
DS
12826 struct bgp_dest *dest, *ndest;
12827 struct bgp_dest *top;
9c14ec72
RW
12828 struct bgp_table_stats *ts = THREAD_ARG(t);
12829 unsigned int space = 0;
12830
12831 if (!(top = bgp_table_top(ts->table)))
12832 return 0;
12833
12834 switch (ts->table->afi) {
12835 case AFI_IP:
12836 space = IPV4_MAX_BITLEN;
12837 break;
12838 case AFI_IP6:
12839 space = IPV6_MAX_BITLEN;
12840 break;
3ba7b4af
TA
12841 case AFI_L2VPN:
12842 space = EVPN_ROUTE_PREFIXLEN;
12843 break;
9c14ec72
RW
12844 default:
12845 return 0;
12846 }
12847
12848 ts->counts[BGP_STATS_MAXBITLEN] = space;
12849
9bcb3eef 12850 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12851 if (ts->table->safi == SAFI_MPLS_VPN
12852 || ts->table->safi == SAFI_ENCAP
12853 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12854 struct bgp_table *table;
12855
9bcb3eef 12856 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12857 if (!table)
12858 continue;
12859
12860 top = bgp_table_top(table);
9bcb3eef
DS
12861 for (ndest = bgp_table_top(table); ndest;
12862 ndest = bgp_route_next(ndest))
12863 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12864 } else {
9bcb3eef 12865 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12866 }
12867 }
9c14ec72 12868
d62a17ae 12869 return 0;
2815e61f 12870}
ff7924f6 12871
71f1613a
DA
12872static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12873 struct json_object *json_array)
12874{
12875 struct listnode *node, *nnode;
12876 struct bgp *bgp;
12877
12878 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12879 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12880}
12881
12882static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12883 safi_t safi, struct json_object *json_array)
2815e61f 12884{
d62a17ae 12885 struct bgp_table_stats ts;
12886 unsigned int i;
893cccd0
PG
12887 int ret = CMD_SUCCESS;
12888 char temp_buf[20];
6c9d22e2
PG
12889 struct json_object *json = NULL;
12890
12891 if (json_array)
12892 json = json_object_new_object();
019386c2 12893
d62a17ae 12894 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12895 char warning_msg[50];
12896
12897 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12898 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12899 safi);
6c9d22e2
PG
12900
12901 if (!json)
893cccd0
PG
12902 vty_out(vty, "%s\n", warning_msg);
12903 else
9ab0cf58 12904 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12905
893cccd0
PG
12906 ret = CMD_WARNING;
12907 goto end_table_stats;
d62a17ae 12908 }
019386c2 12909
893cccd0 12910 if (!json)
5290ceab
DA
12911 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12912 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12913 else
12914 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12915
d62a17ae 12916 /* labeled-unicast routes live in the unicast table */
12917 if (safi == SAFI_LABELED_UNICAST)
12918 safi = SAFI_UNICAST;
019386c2 12919
d62a17ae 12920 memset(&ts, 0, sizeof(ts));
12921 ts.table = bgp->rib[afi][safi];
12922 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12923
d62a17ae 12924 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12925 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12926 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12927 continue;
12928
12929 switch (i) {
d62a17ae 12930 case BGP_STATS_ASPATH_TOTHOPS:
12931 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12932 if (!json) {
9ab0cf58
PG
12933 snprintf(
12934 temp_buf, sizeof(temp_buf), "%12.2f",
12935 ts.counts[i]
12936 ? (float)ts.counts[i]
12937 / (float)ts.counts
12938 [BGP_STATS_ASPATH_COUNT]
12939 : 0);
893cccd0 12940 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12941 table_stats_strs[i]
12942 [TABLE_STATS_IDX_VTY],
893cccd0 12943 temp_buf);
9ab0cf58
PG
12944 } else {
12945 json_object_double_add(
12946 json,
12947 table_stats_strs[i]
12948 [TABLE_STATS_IDX_JSON],
12949 ts.counts[i]
12950 ? (double)ts.counts[i]
12951 / (double)ts.counts
d62a17ae 12952 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12953 : 0);
12954 }
d62a17ae 12955 break;
12956 case BGP_STATS_TOTPLEN:
6c9d22e2 12957 if (!json) {
9ab0cf58
PG
12958 snprintf(
12959 temp_buf, sizeof(temp_buf), "%12.2f",
12960 ts.counts[i]
12961 ? (float)ts.counts[i]
12962 / (float)ts.counts
12963 [BGP_STATS_PREFIXES]
12964 : 0);
893cccd0 12965 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12966 table_stats_strs[i]
12967 [TABLE_STATS_IDX_VTY],
893cccd0 12968 temp_buf);
9ab0cf58
PG
12969 } else {
12970 json_object_double_add(
12971 json,
12972 table_stats_strs[i]
12973 [TABLE_STATS_IDX_JSON],
12974 ts.counts[i]
12975 ? (double)ts.counts[i]
12976 / (double)ts.counts
d62a17ae 12977 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12978 : 0);
12979 }
d62a17ae 12980 break;
12981 case BGP_STATS_SPACE:
6c9d22e2
PG
12982 if (!json) {
12983 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12984 ts.total_space);
893cccd0 12985 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12986 table_stats_strs[i]
12987 [TABLE_STATS_IDX_VTY],
893cccd0 12988 temp_buf);
9ab0cf58
PG
12989 } else {
12990 json_object_double_add(
12991 json,
12992 table_stats_strs[i]
12993 [TABLE_STATS_IDX_JSON],
12994 (double)ts.total_space);
12995 }
8d0ab76d 12996 if (afi == AFI_IP6) {
6c9d22e2
PG
12997 if (!json) {
12998 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12999 "%12g",
13000 ts.total_space
13001 * pow(2.0, -128 + 32));
6c9d22e2
PG
13002 vty_out(vty, "%30s: %s\n",
13003 "/32 equivalent %s\n",
13004 temp_buf);
9ab0cf58
PG
13005 } else {
13006 json_object_double_add(
13007 json, "/32equivalent",
13008 (double)(ts.total_space
13009 * pow(2.0,
13010 -128 + 32)));
13011 }
6c9d22e2
PG
13012 if (!json) {
13013 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13014 "%12g",
13015 ts.total_space
13016 * pow(2.0, -128 + 48));
6c9d22e2
PG
13017 vty_out(vty, "%30s: %s\n",
13018 "/48 equivalent %s\n",
13019 temp_buf);
9ab0cf58
PG
13020 } else {
13021 json_object_double_add(
13022 json, "/48equivalent",
13023 (double)(ts.total_space
13024 * pow(2.0,
13025 -128 + 48)));
13026 }
8d0ab76d 13027 } else {
6c9d22e2
PG
13028 if (!json) {
13029 snprintf(temp_buf, sizeof(temp_buf),
13030 "%12.2f",
9ab0cf58
PG
13031 ts.total_space * 100.
13032 * pow(2.0, -32));
6c9d22e2 13033 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13034 "% announced ", temp_buf);
13035 } else {
13036 json_object_double_add(
13037 json, "%announced",
13038 (double)(ts.total_space * 100.
13039 * pow(2.0, -32)));
13040 }
6c9d22e2
PG
13041 if (!json) {
13042 snprintf(temp_buf, sizeof(temp_buf),
13043 "%12.2f",
9ab0cf58
PG
13044 ts.total_space
13045 * pow(2.0, -32 + 8));
6c9d22e2
PG
13046 vty_out(vty, "%30s: %s\n",
13047 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13048 } else {
13049 json_object_double_add(
13050 json, "/8equivalent",
13051 (double)(ts.total_space
13052 * pow(2.0, -32 + 8)));
13053 }
6c9d22e2
PG
13054 if (!json) {
13055 snprintf(temp_buf, sizeof(temp_buf),
13056 "%12.2f",
9ab0cf58
PG
13057 ts.total_space
13058 * pow(2.0, -32 + 24));
6c9d22e2 13059 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13060 "/24 equivalent ", temp_buf);
13061 } else {
13062 json_object_double_add(
13063 json, "/24equivalent",
13064 (double)(ts.total_space
13065 * pow(2.0, -32 + 24)));
13066 }
8d0ab76d 13067 }
d62a17ae 13068 break;
13069 default:
6c9d22e2
PG
13070 if (!json) {
13071 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13072 ts.counts[i]);
893cccd0 13073 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13074 table_stats_strs[i]
13075 [TABLE_STATS_IDX_VTY],
13076 temp_buf);
13077 } else {
13078 json_object_int_add(
13079 json,
13080 table_stats_strs[i]
13081 [TABLE_STATS_IDX_JSON],
13082 ts.counts[i]);
13083 }
d62a17ae 13084 }
893cccd0
PG
13085 if (!json)
13086 vty_out(vty, "\n");
d62a17ae 13087 }
9ab0cf58 13088end_table_stats:
6c9d22e2
PG
13089 if (json)
13090 json_object_array_add(json_array, json);
893cccd0 13091 return ret;
d62a17ae 13092}
13093
71f1613a
DA
13094static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13095 safi_t safi, struct json_object *json_array)
13096{
13097 if (!bgp) {
13098 bgp_table_stats_all(vty, afi, safi, json_array);
13099 return CMD_SUCCESS;
13100 }
13101
13102 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13103}
13104
d62a17ae 13105enum bgp_pcounts {
13106 PCOUNT_ADJ_IN = 0,
13107 PCOUNT_DAMPED,
13108 PCOUNT_REMOVED,
13109 PCOUNT_HISTORY,
13110 PCOUNT_STALE,
13111 PCOUNT_VALID,
13112 PCOUNT_ALL,
13113 PCOUNT_COUNTED,
7e3d9632 13114 PCOUNT_BPATH_SELECTED,
d62a17ae 13115 PCOUNT_PFCNT, /* the figure we display to users */
13116 PCOUNT_MAX,
a636c635 13117};
718e3744 13118
2b64873d 13119static const char *const pcount_strs[] = {
9d303b37
DL
13120 [PCOUNT_ADJ_IN] = "Adj-in",
13121 [PCOUNT_DAMPED] = "Damped",
13122 [PCOUNT_REMOVED] = "Removed",
13123 [PCOUNT_HISTORY] = "History",
13124 [PCOUNT_STALE] = "Stale",
13125 [PCOUNT_VALID] = "Valid",
13126 [PCOUNT_ALL] = "All RIB",
13127 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13128 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13129 [PCOUNT_PFCNT] = "Useable",
13130 [PCOUNT_MAX] = NULL,
a636c635 13131};
718e3744 13132
d62a17ae 13133struct peer_pcounts {
13134 unsigned int count[PCOUNT_MAX];
13135 const struct peer *peer;
13136 const struct bgp_table *table;
54317cba 13137 safi_t safi;
a636c635 13138};
47fc97cc 13139
9bcb3eef 13140static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13141{
54317cba
JW
13142 const struct bgp_adj_in *ain;
13143 const struct bgp_path_info *pi;
d62a17ae 13144 const struct peer *peer = pc->peer;
13145
54317cba
JW
13146 for (ain = rn->adj_in; ain; ain = ain->next)
13147 if (ain->peer == peer)
13148 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13149
9bcb3eef 13150 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13151
54317cba
JW
13152 if (pi->peer != peer)
13153 continue;
d62a17ae 13154
54317cba 13155 pc->count[PCOUNT_ALL]++;
d62a17ae 13156
54317cba
JW
13157 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13158 pc->count[PCOUNT_DAMPED]++;
13159 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13160 pc->count[PCOUNT_HISTORY]++;
13161 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13162 pc->count[PCOUNT_REMOVED]++;
13163 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13164 pc->count[PCOUNT_STALE]++;
13165 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13166 pc->count[PCOUNT_VALID]++;
13167 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13168 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13169 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13170 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13171
13172 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13173 pc->count[PCOUNT_COUNTED]++;
13174 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13175 flog_err(
13176 EC_LIB_DEVELOPMENT,
13177 "Attempting to count but flags say it is unusable");
13178 } else {
40381db7 13179 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13180 flog_err(
13181 EC_LIB_DEVELOPMENT,
13182 "Not counted but flags say we should");
d62a17ae 13183 }
13184 }
54317cba
JW
13185}
13186
13187static int bgp_peer_count_walker(struct thread *t)
13188{
9bcb3eef 13189 struct bgp_dest *rn, *rm;
54317cba
JW
13190 const struct bgp_table *table;
13191 struct peer_pcounts *pc = THREAD_ARG(t);
13192
13193 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13194 || pc->safi == SAFI_EVPN) {
13195 /* Special handling for 2-level routing tables. */
13196 for (rn = bgp_table_top(pc->table); rn;
13197 rn = bgp_route_next(rn)) {
9bcb3eef 13198 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13199 if (table != NULL)
13200 for (rm = bgp_table_top(table); rm;
13201 rm = bgp_route_next(rm))
13202 bgp_peer_count_proc(rm, pc);
13203 }
13204 } else
13205 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13206 bgp_peer_count_proc(rn, pc);
13207
d62a17ae 13208 return 0;
718e3744 13209}
13210
d62a17ae 13211static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13212 safi_t safi, bool use_json)
856ca177 13213{
d62a17ae 13214 struct peer_pcounts pcounts = {.peer = peer};
13215 unsigned int i;
13216 json_object *json = NULL;
13217 json_object *json_loop = NULL;
856ca177 13218
d62a17ae 13219 if (use_json) {
13220 json = json_object_new_object();
13221 json_loop = json_object_new_object();
13222 }
718e3744 13223
d62a17ae 13224 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13225 || !peer->bgp->rib[afi][safi]) {
13226 if (use_json) {
13227 json_object_string_add(
13228 json, "warning",
13229 "No such neighbor or address family");
13230 vty_out(vty, "%s\n", json_object_to_json_string(json));
13231 json_object_free(json);
d5f20468 13232 json_object_free(json_loop);
d62a17ae 13233 } else
13234 vty_out(vty, "%% No such neighbor or address family\n");
13235
13236 return CMD_WARNING;
13237 }
2a71e9ce 13238
d62a17ae 13239 memset(&pcounts, 0, sizeof(pcounts));
13240 pcounts.peer = peer;
13241 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13242 pcounts.safi = safi;
d62a17ae 13243
13244 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13245 * stats for the thread-walk (i.e. ensure this can't be blamed on
13246 * on just vty_read()).
13247 */
d62a17ae 13248 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13249
13250 if (use_json) {
13251 json_object_string_add(json, "prefixCountsFor", peer->host);
13252 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13253 get_afi_safi_str(afi, safi, true));
d62a17ae 13254 json_object_int_add(json, "pfxCounter",
13255 peer->pcount[afi][safi]);
13256
13257 for (i = 0; i < PCOUNT_MAX; i++)
13258 json_object_int_add(json_loop, pcount_strs[i],
13259 pcounts.count[i]);
13260
13261 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13262
13263 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13264 json_object_string_add(json, "pfxctDriftFor",
13265 peer->host);
13266 json_object_string_add(
13267 json, "recommended",
13268 "Please report this bug, with the above command output");
13269 }
75eeda93 13270 vty_json(vty, json);
d62a17ae 13271 } else {
13272
13273 if (peer->hostname
892fedb6 13274 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13275 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13276 peer->hostname, peer->host,
5cb5f4d0 13277 get_afi_safi_str(afi, safi, false));
d62a17ae 13278 } else {
13279 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13280 get_afi_safi_str(afi, safi, false));
d62a17ae 13281 }
13282
6cde4b45 13283 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13284 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13285
13286 for (i = 0; i < PCOUNT_MAX; i++)
13287 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13288 pcounts.count[i]);
13289
13290 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13291 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13292 vty_out(vty,
13293 "Please report this bug, with the above command output\n");
13294 }
13295 }
13296
13297 return CMD_SUCCESS;
718e3744 13298}
13299
a636c635
DW
13300DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13301 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13302 "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 13303 SHOW_STR
13304 IP_STR
13305 BGP_STR
8386ac43 13306 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13307 BGP_AFI_HELP_STR
13308 BGP_SAFI_HELP_STR
0b16f239
DS
13309 "Detailed information on TCP and BGP neighbor connections\n"
13310 "Neighbor to display information about\n"
13311 "Neighbor to display information about\n"
91d37724 13312 "Neighbor on BGP configured interface\n"
a636c635 13313 "Display detailed prefix count information\n"
9973d184 13314 JSON_STR)
0b16f239 13315{
d62a17ae 13316 afi_t afi = AFI_IP6;
13317 safi_t safi = SAFI_UNICAST;
13318 struct peer *peer;
13319 int idx = 0;
13320 struct bgp *bgp = NULL;
9f049418
DS
13321 bool uj = use_json(argc, argv);
13322
13323 if (uj)
13324 argc--;
856ca177 13325
d62a17ae 13326 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13327 &bgp, uj);
d62a17ae 13328 if (!idx)
13329 return CMD_WARNING;
0b16f239 13330
d62a17ae 13331 argv_find(argv, argc, "neighbors", &idx);
13332 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13333 if (!peer)
13334 return CMD_WARNING;
bb46e94f 13335
29c8d9da 13336 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13337}
0b16f239 13338
d6902373
PG
13339#ifdef KEEP_OLD_VPN_COMMANDS
13340DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13341 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13342 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13343 SHOW_STR
13344 IP_STR
13345 BGP_STR
d6902373 13346 BGP_VPNVX_HELP_STR
91d37724 13347 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13348 "Detailed information on TCP and BGP neighbor connections\n"
13349 "Neighbor to display information about\n"
13350 "Neighbor to display information about\n"
91d37724 13351 "Neighbor on BGP configured interface\n"
a636c635 13352 "Display detailed prefix count information\n"
9973d184 13353 JSON_STR)
a636c635 13354{
d62a17ae 13355 int idx_peer = 6;
13356 struct peer *peer;
9f049418 13357 bool uj = use_json(argc, argv);
a636c635 13358
d62a17ae 13359 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13360 if (!peer)
13361 return CMD_WARNING;
13362
13363 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13364}
13365
d6902373
PG
13366DEFUN (show_ip_bgp_vpn_all_route_prefix,
13367 show_ip_bgp_vpn_all_route_prefix_cmd,
13368 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13369 SHOW_STR
13370 IP_STR
13371 BGP_STR
d6902373 13372 BGP_VPNVX_HELP_STR
91d37724
QY
13373 "Display information about all VPNv4 NLRIs\n"
13374 "Network in the BGP routing table to display\n"
3a2d747c 13375 "Network in the BGP routing table to display\n"
9973d184 13376 JSON_STR)
91d37724 13377{
d62a17ae 13378 int idx = 0;
13379 char *network = NULL;
13380 struct bgp *bgp = bgp_get_default();
13381 if (!bgp) {
13382 vty_out(vty, "Can't find default instance\n");
13383 return CMD_WARNING;
13384 }
87e34b58 13385
d62a17ae 13386 if (argv_find(argv, argc, "A.B.C.D", &idx))
13387 network = argv[idx]->arg;
13388 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13389 network = argv[idx]->arg;
13390 else {
13391 vty_out(vty, "Unable to figure out Network\n");
13392 return CMD_WARNING;
13393 }
87e34b58 13394
d62a17ae 13395 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13396 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13397 use_json(argc, argv));
91d37724 13398}
d6902373 13399#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13400
44c69747
LK
13401DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13402 show_bgp_l2vpn_evpn_route_prefix_cmd,
13403 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13404 SHOW_STR
4c63a661
PG
13405 BGP_STR
13406 L2VPN_HELP_STR
13407 EVPN_HELP_STR
44c69747
LK
13408 "Network in the BGP routing table to display\n"
13409 "Network in the BGP routing table to display\n"
4c63a661
PG
13410 "Network in the BGP routing table to display\n"
13411 "Network in the BGP routing table to display\n"
13412 JSON_STR)
13413{
d62a17ae 13414 int idx = 0;
13415 char *network = NULL;
44c69747 13416 int prefix_check = 0;
a636c635 13417
44c69747
LK
13418 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13419 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13420 network = argv[idx]->arg;
44c69747 13421 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13422 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13423 network = argv[idx]->arg;
44c69747
LK
13424 prefix_check = 1;
13425 } else {
d62a17ae 13426 vty_out(vty, "Unable to figure out Network\n");
13427 return CMD_WARNING;
13428 }
44c69747
LK
13429 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13430 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13431 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13432}
13433
2f9bc755
DS
13434static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13435 struct bgp_table *table, int *header1,
13436 int *header2, json_object *json,
13437 json_object *json_scode,
13438 json_object *json_ocode, bool wide)
13439{
13440 uint64_t version = table ? table->version : 0;
13441
13442 if (*header1) {
13443 if (json) {
13444 json_object_int_add(json, "bgpTableVersion", version);
c949c771
DA
13445 json_object_string_addf(json, "bgpLocalRouterId",
13446 "%pI4", &bgp->router_id);
2f9bc755
DS
13447 json_object_int_add(json, "defaultLocPrf",
13448 bgp->default_local_pref);
13449 json_object_int_add(json, "localAS", bgp->as);
13450 json_object_object_add(json, "bgpStatusCodes",
13451 json_scode);
13452 json_object_object_add(json, "bgpOriginCodes",
13453 json_ocode);
13454 } else {
13455 vty_out(vty,
23d0a753
DA
13456 "BGP table version is %" PRIu64
13457 ", local router ID is %pI4, vrf id ",
13458 version, &bgp->router_id);
2f9bc755
DS
13459 if (bgp->vrf_id == VRF_UNKNOWN)
13460 vty_out(vty, "%s", VRFID_NONE_STR);
13461 else
13462 vty_out(vty, "%u", bgp->vrf_id);
13463 vty_out(vty, "\n");
13464 vty_out(vty, "Default local pref %u, ",
13465 bgp->default_local_pref);
13466 vty_out(vty, "local AS %u\n", bgp->as);
13467 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13468 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13469 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13470 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13471 }
13472 *header1 = 0;
13473 }
13474 if (*header2) {
13475 if (!json)
13476 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13477 : BGP_SHOW_HEADER));
13478 *header2 = 0;
13479 }
13480}
13481
d9478df0
TA
13482static void
13483show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13484 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13485 const char *rmap_name, json_object *json, json_object *json_ar,
13486 json_object *json_scode, json_object *json_ocode,
96c81f66 13487 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13488 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13489{
d62a17ae 13490 struct bgp_adj_in *ain;
13491 struct bgp_adj_out *adj;
9bcb3eef 13492 struct bgp_dest *dest;
d62a17ae 13493 struct bgp *bgp;
d62a17ae 13494 struct attr attr;
13495 int ret;
13496 struct update_subgroup *subgrp;
d62a17ae 13497 struct peer_af *paf;
f99def61 13498 bool route_filtered;
96f3485c
MK
13499 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13500 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13501 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13502 || (safi == SAFI_EVPN))
13503 ? true
13504 : false;
a636c635 13505
d62a17ae 13506 bgp = peer->bgp;
a636c635 13507
d62a17ae 13508 subgrp = peer_subgroup(peer, afi, safi);
13509
6392aaa6 13510 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13511 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13512 if (use_json) {
13513 json_object_int_add(json, "bgpTableVersion",
13514 table->version);
c949c771
DA
13515 json_object_string_addf(json, "bgpLocalRouterId",
13516 "%pI4", &bgp->router_id);
01eced22
AD
13517 json_object_int_add(json, "defaultLocPrf",
13518 bgp->default_local_pref);
13519 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13520 json_object_object_add(json, "bgpStatusCodes",
13521 json_scode);
13522 json_object_object_add(json, "bgpOriginCodes",
13523 json_ocode);
07d0c4ed
DA
13524 json_object_string_add(
13525 json, "bgpOriginatingDefaultNetwork",
13526 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13527 } else {
23d0a753
DA
13528 vty_out(vty,
13529 "BGP table version is %" PRIu64
13530 ", local router ID is %pI4, vrf id ",
13531 table->version, &bgp->router_id);
9df8b37c
PZ
13532 if (bgp->vrf_id == VRF_UNKNOWN)
13533 vty_out(vty, "%s", VRFID_NONE_STR);
13534 else
13535 vty_out(vty, "%u", bgp->vrf_id);
13536 vty_out(vty, "\n");
01eced22
AD
13537 vty_out(vty, "Default local pref %u, ",
13538 bgp->default_local_pref);
13539 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13540 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13541 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13542 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13543 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13544
07d0c4ed
DA
13545 vty_out(vty, "Originating default network %s\n\n",
13546 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13547 }
d9478df0 13548 *header1 = 0;
d62a17ae 13549 }
a636c635 13550
9bcb3eef 13551 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13552 if (type == bgp_show_adj_route_received
13553 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13554 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13555 if (ain->peer != peer)
ea47320b 13556 continue;
6392aaa6 13557
d9478df0
TA
13558 show_adj_route_header(vty, bgp, table, header1,
13559 header2, json, json_scode,
13560 json_ocode, wide);
13561
13562 if ((safi == SAFI_MPLS_VPN)
13563 || (safi == SAFI_ENCAP)
13564 || (safi == SAFI_EVPN)) {
13565 if (use_json)
13566 json_object_string_add(
13567 json_ar, "rd", rd_str);
13568 else if (show_rd && rd_str) {
13569 vty_out(vty,
13570 "Route Distinguisher: %s\n",
13571 rd_str);
13572 show_rd = false;
13573 }
13574 }
6392aaa6 13575
6f4f49b2 13576 attr = *ain->attr;
f99def61
AD
13577 route_filtered = false;
13578
13579 /* Filter prefix using distribute list,
13580 * filter list or prefix list
13581 */
b54892e0 13582 const struct prefix *rn_p =
9bcb3eef 13583 bgp_dest_get_prefix(dest);
b54892e0
DS
13584 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13585 safi))
13586 == FILTER_DENY)
f99def61
AD
13587 route_filtered = true;
13588
13589 /* Filter prefix using route-map */
b54892e0
DS
13590 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13591 safi, rmap_name, NULL,
13592 0, NULL);
6392aaa6 13593
13c8e163
AD
13594 if (type == bgp_show_adj_route_filtered &&
13595 !route_filtered && ret != RMAP_DENY) {
b755861b 13596 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13597 continue;
d62a17ae 13598 }
6392aaa6 13599
d9478df0
TA
13600 if (type == bgp_show_adj_route_received
13601 && (route_filtered || ret == RMAP_DENY))
13602 (*filtered_count)++;
6392aaa6 13603
7d3cae70 13604 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13605 use_json, json_ar, wide);
b755861b 13606 bgp_attr_undup(&attr, ain->attr);
d9478df0 13607 (*output_count)++;
d62a17ae 13608 }
6392aaa6 13609 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13610 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13611 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13612 if (paf->peer != peer || !adj->attr)
924c3f6a 13613 continue;
d62a17ae 13614
d9478df0
TA
13615 show_adj_route_header(vty, bgp, table,
13616 header1, header2,
13617 json, json_scode,
13618 json_ocode, wide);
d62a17ae 13619
b54892e0 13620 const struct prefix *rn_p =
9bcb3eef 13621 bgp_dest_get_prefix(dest);
b54892e0 13622
6f4f49b2 13623 attr = *adj->attr;
b755861b 13624 ret = bgp_output_modifier(
b54892e0 13625 peer, rn_p, &attr, afi, safi,
b755861b 13626 rmap_name);
f46d8e1e 13627
b755861b 13628 if (ret != RMAP_DENY) {
d9478df0
TA
13629 if ((safi == SAFI_MPLS_VPN)
13630 || (safi == SAFI_ENCAP)
13631 || (safi == SAFI_EVPN)) {
13632 if (use_json)
13633 json_object_string_add(
13634 json_ar,
13635 "rd",
13636 rd_str);
13637 else if (show_rd
13638 && rd_str) {
13639 vty_out(vty,
13640 "Route Distinguisher: %s\n",
13641 rd_str);
13642 show_rd = false;
13643 }
13644 }
b54892e0 13645 route_vty_out_tmp(
7d3cae70
DA
13646 vty, dest, rn_p, &attr,
13647 safi, use_json, json_ar,
ae248832 13648 wide);
d9478df0 13649 (*output_count)++;
b755861b 13650 } else {
d9478df0 13651 (*filtered_count)++;
a2addae8 13652 }
b755861b
PM
13653
13654 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13655 }
f20ce998
DS
13656 } else if (type == bgp_show_adj_route_bestpath) {
13657 struct bgp_path_info *pi;
13658
d9478df0
TA
13659 show_adj_route_header(vty, bgp, table, header1, header2,
13660 json, json_scode, json_ocode,
13661 wide);
f20ce998
DS
13662
13663 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13664 pi = pi->next) {
13665 if (pi->peer != peer)
13666 continue;
13667
13668 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13669 continue;
13670
7d3cae70 13671 route_vty_out_tmp(vty, dest,
f20ce998
DS
13672 bgp_dest_get_prefix(dest),
13673 pi->attr, safi, use_json,
13674 json_ar, wide);
d9478df0 13675 (*output_count)++;
f20ce998 13676 }
d62a17ae 13677 }
13678 }
a636c635 13679}
2a71e9ce 13680
d62a17ae 13681static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13682 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13683 const char *rmap_name, uint16_t show_flags)
0b16f239 13684{
d9478df0
TA
13685 struct bgp *bgp;
13686 struct bgp_table *table;
d62a17ae 13687 json_object *json = NULL;
d9478df0
TA
13688 json_object *json_scode = NULL;
13689 json_object *json_ocode = NULL;
13690 json_object *json_ar = NULL;
96f3485c 13691 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13692
d9478df0
TA
13693 /* Init BGP headers here so they're only displayed once
13694 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13695 */
13696 int header1 = 1;
13697 int header2 = 1;
13698
13699 /*
13700 * Initialize variables for each RD
13701 * All prefixes under an RD is aggregated within "json_routes"
13702 */
13703 char rd_str[BUFSIZ] = {0};
13704 json_object *json_routes = NULL;
13705
13706
13707 /* For 2-tier tables, prefix counts need to be
13708 * maintained across multiple runs of show_adj_route()
13709 */
13710 unsigned long output_count_per_rd;
13711 unsigned long filtered_count_per_rd;
13712 unsigned long output_count = 0;
13713 unsigned long filtered_count = 0;
13714
13715 if (use_json) {
d62a17ae 13716 json = json_object_new_object();
d9478df0
TA
13717 json_ar = json_object_new_object();
13718 json_scode = json_object_new_object();
13719 json_ocode = json_object_new_object();
13720
13721 json_object_string_add(json_scode, "suppressed", "s");
13722 json_object_string_add(json_scode, "damped", "d");
13723 json_object_string_add(json_scode, "history", "h");
13724 json_object_string_add(json_scode, "valid", "*");
13725 json_object_string_add(json_scode, "best", ">");
13726 json_object_string_add(json_scode, "multipath", "=");
13727 json_object_string_add(json_scode, "internal", "i");
13728 json_object_string_add(json_scode, "ribFailure", "r");
13729 json_object_string_add(json_scode, "stale", "S");
13730 json_object_string_add(json_scode, "removed", "R");
13731
13732 json_object_string_add(json_ocode, "igp", "i");
13733 json_object_string_add(json_ocode, "egp", "e");
13734 json_object_string_add(json_ocode, "incomplete", "?");
13735 }
0b16f239 13736
d62a17ae 13737 if (!peer || !peer->afc[afi][safi]) {
13738 if (use_json) {
13739 json_object_string_add(
13740 json, "warning",
13741 "No such neighbor or address family");
13742 vty_out(vty, "%s\n", json_object_to_json_string(json));
13743 json_object_free(json);
690c3134
MW
13744 json_object_free(json_ar);
13745 json_object_free(json_scode);
13746 json_object_free(json_ocode);
d62a17ae 13747 } else
13748 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13749
d62a17ae 13750 return CMD_WARNING;
13751 }
13752
6392aaa6
PM
13753 if ((type == bgp_show_adj_route_received
13754 || type == bgp_show_adj_route_filtered)
d62a17ae 13755 && !CHECK_FLAG(peer->af_flags[afi][safi],
13756 PEER_FLAG_SOFT_RECONFIG)) {
13757 if (use_json) {
13758 json_object_string_add(
13759 json, "warning",
13760 "Inbound soft reconfiguration not enabled");
13761 vty_out(vty, "%s\n", json_object_to_json_string(json));
13762 json_object_free(json);
690c3134
MW
13763 json_object_free(json_ar);
13764 json_object_free(json_scode);
13765 json_object_free(json_ocode);
d62a17ae 13766 } else
13767 vty_out(vty,
13768 "%% Inbound soft reconfiguration not enabled\n");
13769
13770 return CMD_WARNING;
13771 }
0b16f239 13772
d9478df0
TA
13773 bgp = peer->bgp;
13774
13775 /* labeled-unicast routes live in the unicast table */
13776 if (safi == SAFI_LABELED_UNICAST)
13777 table = bgp->rib[afi][SAFI_UNICAST];
13778 else
13779 table = bgp->rib[afi][safi];
13780
13781 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13782 || (safi == SAFI_EVPN)) {
13783
13784 struct bgp_dest *dest;
13785
13786 for (dest = bgp_table_top(table); dest;
13787 dest = bgp_route_next(dest)) {
13788 table = bgp_dest_get_bgp_table_info(dest);
13789 if (!table)
13790 continue;
13791
13792 output_count_per_rd = 0;
13793 filtered_count_per_rd = 0;
13794
13795 if (use_json)
13796 json_routes = json_object_new_object();
13797
13798 const struct prefix_rd *prd;
13799 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13800 dest);
13801
13802 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13803
13804 show_adj_route(vty, peer, table, afi, safi, type,
13805 rmap_name, json, json_routes, json_scode,
13806 json_ocode, show_flags, &header1,
13807 &header2, rd_str, &output_count_per_rd,
13808 &filtered_count_per_rd);
13809
13810 /* Don't include an empty RD in the output! */
13811 if (json_routes && (output_count_per_rd > 0))
13812 json_object_object_add(json_ar, rd_str,
13813 json_routes);
13814
13815 output_count += output_count_per_rd;
13816 filtered_count += filtered_count_per_rd;
13817 }
13818 } else
13819 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13820 json, json_ar, json_scode, json_ocode,
13821 show_flags, &header1, &header2, rd_str,
13822 &output_count, &filtered_count);
13823
13824 if (use_json) {
c1984955
TA
13825 if (type == bgp_show_adj_route_advertised)
13826 json_object_object_add(json, "advertisedRoutes",
13827 json_ar);
13828 else
13829 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
13830 json_object_int_add(json, "totalPrefixCounter", output_count);
13831 json_object_int_add(json, "filteredPrefixCounter",
13832 filtered_count);
13833
690c3134
MW
13834 /*
13835 * These fields only give up ownership to `json` when `header1`
13836 * is used (set to zero). See code in `show_adj_route` and
13837 * `show_adj_route_header`.
13838 */
13839 if (header1 == 1) {
d9478df0
TA
13840 json_object_free(json_scode);
13841 json_object_free(json_ocode);
13842 }
13843
75eeda93 13844 vty_json(vty, json);
d9478df0
TA
13845 } else if (output_count > 0) {
13846 if (filtered_count > 0)
13847 vty_out(vty,
13848 "\nTotal number of prefixes %ld (%ld filtered)\n",
13849 output_count, filtered_count);
13850 else
13851 vty_out(vty, "\nTotal number of prefixes %ld\n",
13852 output_count);
13853 }
0b16f239 13854
d62a17ae 13855 return CMD_SUCCESS;
a636c635 13856}
50ef26d4 13857
f20ce998
DS
13858DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13859 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13860 "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]",
13861 SHOW_STR
13862 IP_STR
13863 BGP_STR
13864 BGP_INSTANCE_HELP_STR
13865 BGP_AFI_HELP_STR
13866 BGP_SAFI_WITH_LABEL_HELP_STR
13867 "Detailed information on TCP and BGP neighbor connections\n"
13868 "Neighbor to display information about\n"
13869 "Neighbor to display information about\n"
13870 "Neighbor on BGP configured interface\n"
13871 "Display the routes selected by best path\n"
13872 JSON_STR
13873 "Increase table width for longer prefixes\n")
13874{
13875 afi_t afi = AFI_IP6;
13876 safi_t safi = SAFI_UNICAST;
13877 char *rmap_name = NULL;
13878 char *peerstr = NULL;
13879 struct bgp *bgp = NULL;
13880 struct peer *peer;
13881 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13882 int idx = 0;
96c81f66 13883 uint16_t show_flags = 0;
96f3485c
MK
13884
13885 if (uj)
13886 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13887
13888 if (wide)
13889 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13890
13891 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13892 &bgp, uj);
13893
13894 if (!idx)
13895 return CMD_WARNING;
13896
13897 argv_find(argv, argc, "neighbors", &idx);
13898 peerstr = argv[++idx]->arg;
13899
13900 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13901 if (!peer)
13902 return CMD_WARNING;
13903
96f3485c
MK
13904 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13905 show_flags);
f20ce998
DS
13906}
13907
ae248832 13908DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13909 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13910 "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 13911 SHOW_STR
13912 IP_STR
13913 BGP_STR
a636c635 13914 BGP_INSTANCE_HELP_STR
7395a2c9 13915 BGP_AFI_HELP_STR
4dd6177e 13916 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13917 "Display the entries for all address families\n"
718e3744 13918 "Detailed information on TCP and BGP neighbor connections\n"
13919 "Neighbor to display information about\n"
13920 "Neighbor to display information about\n"
91d37724 13921 "Neighbor on BGP configured interface\n"
a636c635 13922 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13923 "Display the received routes from neighbor\n"
13924 "Display the filtered routes received from neighbor\n"
a636c635
DW
13925 "Route-map to modify the attributes\n"
13926 "Name of the route map\n"
ae248832
MK
13927 JSON_STR
13928 "Increase table width for longer prefixes\n")
718e3744 13929{
d62a17ae 13930 afi_t afi = AFI_IP6;
13931 safi_t safi = SAFI_UNICAST;
13932 char *rmap_name = NULL;
13933 char *peerstr = NULL;
d62a17ae 13934 struct bgp *bgp = NULL;
13935 struct peer *peer;
6392aaa6 13936 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13937 int idx = 0;
96f3485c 13938 bool first = true;
96c81f66 13939 uint16_t show_flags = 0;
6392aaa6 13940
96f3485c 13941 if (uj) {
d62a17ae 13942 argc--;
96f3485c
MK
13943 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13944 }
13945
13946 if (all) {
13947 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13948 if (argv_find(argv, argc, "ipv4", &idx))
13949 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13950
13951 if (argv_find(argv, argc, "ipv6", &idx))
13952 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13953 }
13954
13955 if (wide)
13956 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13957
9f049418
DS
13958 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13959 &bgp, uj);
13960 if (!idx)
13961 return CMD_WARNING;
13962
d62a17ae 13963 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13964 argv_find(argv, argc, "neighbors", &idx);
13965 peerstr = argv[++idx]->arg;
8c3deaae 13966
d62a17ae 13967 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13968 if (!peer)
13969 return CMD_WARNING;
856ca177 13970
d62a17ae 13971 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13972 type = bgp_show_adj_route_advertised;
13973 else if (argv_find(argv, argc, "received-routes", &idx))
13974 type = bgp_show_adj_route_received;
13975 else if (argv_find(argv, argc, "filtered-routes", &idx))
13976 type = bgp_show_adj_route_filtered;
13977
d62a17ae 13978 if (argv_find(argv, argc, "route-map", &idx))
13979 rmap_name = argv[++idx]->arg;
95cbbd2a 13980
96f3485c
MK
13981 if (!all)
13982 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13983 show_flags);
13984 if (uj)
13985 vty_out(vty, "{\n");
13986
13987 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13988 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13989 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13990 : AFI_IP6;
13991 FOREACH_SAFI (safi) {
96f3485c
MK
13992 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13993 continue;
13994
13995 if (uj) {
13996 if (first)
13997 first = false;
13998 else
13999 vty_out(vty, ",\n");
14000 vty_out(vty, "\"%s\":",
14001 get_afi_safi_str(afi, safi, true));
14002 } else
14003 vty_out(vty, "\nFor address family: %s\n",
14004 get_afi_safi_str(afi, safi, false));
14005
14006 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14007 show_flags);
14008 }
14009 } else {
14010 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
14011 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14012 continue;
14013
14014 if (uj) {
14015 if (first)
14016 first = false;
14017 else
14018 vty_out(vty, ",\n");
14019 vty_out(vty, "\"%s\":",
14020 get_afi_safi_str(afi, safi, true));
14021 } else
14022 vty_out(vty, "\nFor address family: %s\n",
14023 get_afi_safi_str(afi, safi, false));
14024
14025 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14026 show_flags);
14027 }
14028 }
14029 if (uj)
14030 vty_out(vty, "}\n");
14031
14032 return CMD_SUCCESS;
95cbbd2a
ML
14033}
14034
718e3744 14035DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14036 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14037 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14038 SHOW_STR
14039 IP_STR
14040 BGP_STR
d3120452 14041 BGP_INSTANCE_HELP_STR
8c3deaae
QY
14042 "Address Family\n"
14043 "Address Family\n"
718e3744 14044 "Address Family modifier\n"
14045 "Detailed information on TCP and BGP neighbor connections\n"
14046 "Neighbor to display information about\n"
14047 "Neighbor to display information about\n"
91d37724 14048 "Neighbor on BGP configured interface\n"
718e3744 14049 "Display information received from a BGP neighbor\n"
856ca177 14050 "Display the prefixlist filter\n"
9973d184 14051 JSON_STR)
718e3744 14052{
d62a17ae 14053 afi_t afi = AFI_IP6;
14054 safi_t safi = SAFI_UNICAST;
14055 char *peerstr = NULL;
d62a17ae 14056 char name[BUFSIZ];
d62a17ae 14057 struct peer *peer;
d3120452 14058 int count;
d62a17ae 14059 int idx = 0;
d3120452
IR
14060 struct bgp *bgp = NULL;
14061 bool uj = use_json(argc, argv);
14062
14063 if (uj)
14064 argc--;
14065
14066 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14067 &bgp, uj);
14068 if (!idx)
14069 return CMD_WARNING;
d62a17ae 14070
d62a17ae 14071 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14072 argv_find(argv, argc, "neighbors", &idx);
14073 peerstr = argv[++idx]->arg;
14074
d3120452
IR
14075 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14076 if (!peer)
14077 return CMD_WARNING;
718e3744 14078
4ced1a2c 14079 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14080 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14081 if (count) {
14082 if (!uj)
14083 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14084 get_afi_safi_str(afi, safi, false));
d62a17ae 14085 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14086 } else {
14087 if (uj)
14088 vty_out(vty, "{}\n");
14089 else
14090 vty_out(vty, "No functional output\n");
14091 }
718e3744 14092
d62a17ae 14093 return CMD_SUCCESS;
14094}
14095
14096static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14097 afi_t afi, safi_t safi,
9f049418 14098 enum bgp_show_type type, bool use_json)
d62a17ae 14099{
96c81f66 14100 uint16_t show_flags = 0;
96f3485c
MK
14101
14102 if (use_json)
14103 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14104
d62a17ae 14105 if (!peer || !peer->afc[afi][safi]) {
14106 if (use_json) {
14107 json_object *json_no = NULL;
14108 json_no = json_object_new_object();
14109 json_object_string_add(
14110 json_no, "warning",
14111 "No such neighbor or address family");
14112 vty_out(vty, "%s\n",
14113 json_object_to_json_string(json_no));
14114 json_object_free(json_no);
14115 } else
14116 vty_out(vty, "%% No such neighbor or address family\n");
14117 return CMD_WARNING;
14118 }
47fc97cc 14119
7daf25a3
TA
14120 /* labeled-unicast routes live in the unicast table */
14121 if (safi == SAFI_LABELED_UNICAST)
14122 safi = SAFI_UNICAST;
14123
1e2ce4f1
DS
14124 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14125 RPKI_NOT_BEING_USED);
718e3744 14126}
14127
dba3c1d3
PG
14128DEFUN (show_ip_bgp_flowspec_routes_detailed,
14129 show_ip_bgp_flowspec_routes_detailed_cmd,
14130 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14131 SHOW_STR
14132 IP_STR
14133 BGP_STR
14134 BGP_INSTANCE_HELP_STR
14135 BGP_AFI_HELP_STR
14136 "SAFI Flowspec\n"
14137 "Detailed information on flowspec entries\n"
14138 JSON_STR)
14139{
458c1475 14140 afi_t afi = AFI_IP6;
dba3c1d3
PG
14141 safi_t safi = SAFI_UNICAST;
14142 struct bgp *bgp = NULL;
14143 int idx = 0;
9f049418 14144 bool uj = use_json(argc, argv);
96c81f66 14145 uint16_t show_flags = 0;
9f049418 14146
96f3485c 14147 if (uj) {
9f049418 14148 argc--;
96f3485c
MK
14149 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14150 }
dba3c1d3
PG
14151
14152 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14153 &bgp, uj);
dba3c1d3
PG
14154 if (!idx)
14155 return CMD_WARNING;
14156
96f3485c 14157 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14158 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14159}
14160
718e3744 14161DEFUN (show_ip_bgp_neighbor_routes,
14162 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14163 "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 14164 SHOW_STR
14165 IP_STR
14166 BGP_STR
8386ac43 14167 BGP_INSTANCE_HELP_STR
4f280b15 14168 BGP_AFI_HELP_STR
4dd6177e 14169 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14170 "Detailed information on TCP and BGP neighbor connections\n"
14171 "Neighbor to display information about\n"
14172 "Neighbor to display information about\n"
91d37724 14173 "Neighbor on BGP configured interface\n"
2525cf39 14174 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14175 "Display the dampened routes received from neighbor\n"
14176 "Display routes learned from neighbor\n"
9973d184 14177 JSON_STR)
718e3744 14178{
d62a17ae 14179 char *peerstr = NULL;
14180 struct bgp *bgp = NULL;
14181 afi_t afi = AFI_IP6;
14182 safi_t safi = SAFI_UNICAST;
14183 struct peer *peer;
14184 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14185 int idx = 0;
9f049418
DS
14186 bool uj = use_json(argc, argv);
14187
14188 if (uj)
14189 argc--;
bb46e94f 14190
d62a17ae 14191 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14192 &bgp, uj);
d62a17ae 14193 if (!idx)
14194 return CMD_WARNING;
c493f2d8 14195
d62a17ae 14196 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14197 argv_find(argv, argc, "neighbors", &idx);
14198 peerstr = argv[++idx]->arg;
8c3deaae 14199
d62a17ae 14200 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14201 if (!peer)
d62a17ae 14202 return CMD_WARNING;
bb46e94f 14203
d62a17ae 14204 if (argv_find(argv, argc, "flap-statistics", &idx))
14205 sh_type = bgp_show_type_flap_neighbor;
14206 else if (argv_find(argv, argc, "dampened-routes", &idx))
14207 sh_type = bgp_show_type_damp_neighbor;
14208 else if (argv_find(argv, argc, "routes", &idx))
14209 sh_type = bgp_show_type_neighbor;
2525cf39 14210
d62a17ae 14211 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14212}
6b0655a2 14213
734b349e 14214struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14215
d62a17ae 14216struct bgp_distance {
14217 /* Distance value for the IP source prefix. */
d7c0a89a 14218 uint8_t distance;
718e3744 14219
d62a17ae 14220 /* Name of the access-list to be matched. */
14221 char *access_list;
718e3744 14222};
14223
4f280b15
LB
14224DEFUN (show_bgp_afi_vpn_rd_route,
14225 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14226 "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
14227 SHOW_STR
14228 BGP_STR
14229 BGP_AFI_HELP_STR
14230 "Address Family modifier\n"
14231 "Display information for a route distinguisher\n"
14232 "Route Distinguisher\n"
a111dd97 14233 "All Route Distinguishers\n"
7395a2c9
DS
14234 "Network in the BGP routing table to display\n"
14235 "Network in the BGP routing table to display\n"
14236 JSON_STR)
4f280b15 14237{
d62a17ae 14238 int ret;
14239 struct prefix_rd prd;
14240 afi_t afi = AFI_MAX;
14241 int idx = 0;
4f280b15 14242
ff6566f3
DS
14243 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14244 vty_out(vty, "%% Malformed Address Family\n");
14245 return CMD_WARNING;
14246 }
14247
a111dd97
TA
14248 if (!strcmp(argv[5]->arg, "all"))
14249 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14250 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14251 RPKI_NOT_BEING_USED,
14252 use_json(argc, argv));
14253
d62a17ae 14254 ret = str2prefix_rd(argv[5]->arg, &prd);
14255 if (!ret) {
14256 vty_out(vty, "%% Malformed Route Distinguisher\n");
14257 return CMD_WARNING;
14258 }
ff6566f3 14259
d62a17ae 14260 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14261 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14262 use_json(argc, argv));
4f280b15
LB
14263}
14264
d62a17ae 14265static struct bgp_distance *bgp_distance_new(void)
718e3744 14266{
d62a17ae 14267 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14268}
14269
d62a17ae 14270static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14271{
d62a17ae 14272 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14273}
14274
585f1adc
IR
14275static int bgp_distance_set(struct vty *vty, const char *distance_str,
14276 const char *ip_str, const char *access_list_str)
718e3744 14277{
d62a17ae 14278 int ret;
585f1adc
IR
14279 afi_t afi;
14280 safi_t safi;
d62a17ae 14281 struct prefix p;
585f1adc 14282 uint8_t distance;
9bcb3eef 14283 struct bgp_dest *dest;
d62a17ae 14284 struct bgp_distance *bdistance;
718e3744 14285
585f1adc
IR
14286 afi = bgp_node_afi(vty);
14287 safi = bgp_node_safi(vty);
14288
d62a17ae 14289 ret = str2prefix(ip_str, &p);
14290 if (ret == 0) {
585f1adc 14291 vty_out(vty, "Malformed prefix\n");
d62a17ae 14292 return CMD_WARNING_CONFIG_FAILED;
14293 }
718e3744 14294
585f1adc
IR
14295 distance = atoi(distance_str);
14296
d62a17ae 14297 /* Get BGP distance node. */
9bcb3eef
DS
14298 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14299 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14300 if (bdistance)
9bcb3eef 14301 bgp_dest_unlock_node(dest);
ca2e160d 14302 else {
d62a17ae 14303 bdistance = bgp_distance_new();
9bcb3eef 14304 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14305 }
718e3744 14306
d62a17ae 14307 /* Set distance value. */
14308 bdistance->distance = distance;
718e3744 14309
d62a17ae 14310 /* Reset access-list configuration. */
e1b36e13 14311 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14312 if (access_list_str)
14313 bdistance->access_list =
14314 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14315
d62a17ae 14316 return CMD_SUCCESS;
718e3744 14317}
14318
585f1adc
IR
14319static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14320 const char *ip_str, const char *access_list_str)
718e3744 14321{
d62a17ae 14322 int ret;
585f1adc
IR
14323 afi_t afi;
14324 safi_t safi;
d62a17ae 14325 struct prefix p;
585f1adc 14326 int distance;
9bcb3eef 14327 struct bgp_dest *dest;
d62a17ae 14328 struct bgp_distance *bdistance;
718e3744 14329
585f1adc
IR
14330 afi = bgp_node_afi(vty);
14331 safi = bgp_node_safi(vty);
14332
d62a17ae 14333 ret = str2prefix(ip_str, &p);
14334 if (ret == 0) {
585f1adc 14335 vty_out(vty, "Malformed prefix\n");
d62a17ae 14336 return CMD_WARNING_CONFIG_FAILED;
14337 }
718e3744 14338
9bcb3eef
DS
14339 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14340 if (!dest) {
585f1adc 14341 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14342 return CMD_WARNING_CONFIG_FAILED;
14343 }
718e3744 14344
9bcb3eef 14345 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14346 distance = atoi(distance_str);
1f9a9fff 14347
d62a17ae 14348 if (bdistance->distance != distance) {
585f1adc 14349 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14350 bgp_dest_unlock_node(dest);
d62a17ae 14351 return CMD_WARNING_CONFIG_FAILED;
14352 }
718e3744 14353
0a22ddfb 14354 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14355 bgp_distance_free(bdistance);
718e3744 14356
9bcb3eef
DS
14357 bgp_dest_set_bgp_path_info(dest, NULL);
14358 bgp_dest_unlock_node(dest);
14359 bgp_dest_unlock_node(dest);
718e3744 14360
d62a17ae 14361 return CMD_SUCCESS;
718e3744 14362}
14363
718e3744 14364/* Apply BGP information to distance method. */
b8685f9b 14365uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14366 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14367{
9bcb3eef 14368 struct bgp_dest *dest;
801bb996 14369 struct prefix q = {0};
d62a17ae 14370 struct peer *peer;
14371 struct bgp_distance *bdistance;
14372 struct access_list *alist;
14373 struct bgp_static *bgp_static;
14374
14375 if (!bgp)
14376 return 0;
14377
40381db7 14378 peer = pinfo->peer;
d62a17ae 14379
7b7d48e5
DS
14380 if (pinfo->attr->distance)
14381 return pinfo->attr->distance;
14382
801bb996
CS
14383 /* Check source address.
14384 * Note: for aggregate route, peer can have unspec af type.
14385 */
14386 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14387 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14388 return 0;
14389
9bcb3eef
DS
14390 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14391 if (dest) {
14392 bdistance = bgp_dest_get_bgp_distance_info(dest);
14393 bgp_dest_unlock_node(dest);
d62a17ae 14394
14395 if (bdistance->access_list) {
14396 alist = access_list_lookup(afi, bdistance->access_list);
14397 if (alist
14398 && access_list_apply(alist, p) == FILTER_PERMIT)
14399 return bdistance->distance;
14400 } else
14401 return bdistance->distance;
718e3744 14402 }
718e3744 14403
d62a17ae 14404 /* Backdoor check. */
9bcb3eef
DS
14405 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14406 if (dest) {
14407 bgp_static = bgp_dest_get_bgp_static_info(dest);
14408 bgp_dest_unlock_node(dest);
718e3744 14409
d62a17ae 14410 if (bgp_static->backdoor) {
14411 if (bgp->distance_local[afi][safi])
14412 return bgp->distance_local[afi][safi];
14413 else
14414 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14415 }
718e3744 14416 }
718e3744 14417
d62a17ae 14418 if (peer->sort == BGP_PEER_EBGP) {
14419 if (bgp->distance_ebgp[afi][safi])
14420 return bgp->distance_ebgp[afi][safi];
14421 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14422 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14423 if (bgp->distance_ibgp[afi][safi])
14424 return bgp->distance_ibgp[afi][safi];
14425 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14426 } else {
14427 if (bgp->distance_local[afi][safi])
14428 return bgp->distance_local[afi][safi];
14429 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14430 }
718e3744 14431}
14432
a612fb77
DA
14433/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14434 * we should tell ZEBRA update the routes for a specific
14435 * AFI/SAFI to reflect changes in RIB.
14436 */
585f1adc
IR
14437static void bgp_announce_routes_distance_update(struct bgp *bgp,
14438 afi_t update_afi,
14439 safi_t update_safi)
a612fb77
DA
14440{
14441 afi_t afi;
14442 safi_t safi;
14443
14444 FOREACH_AFI_SAFI (afi, safi) {
14445 if (!bgp_fibupd_safi(safi))
14446 continue;
14447
8b54bc30
DA
14448 if (afi != update_afi && safi != update_safi)
14449 continue;
14450
14451 if (BGP_DEBUG(zebra, ZEBRA))
14452 zlog_debug(
14453 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14454 __func__, afi, safi);
14455 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14456 }
14457}
14458
585f1adc
IR
14459DEFUN (bgp_distance,
14460 bgp_distance_cmd,
14461 "distance bgp (1-255) (1-255) (1-255)",
14462 "Define an administrative distance\n"
14463 "BGP distance\n"
14464 "Distance for routes external to the AS\n"
14465 "Distance for routes internal to the AS\n"
14466 "Distance for local routes\n")
718e3744 14467{
585f1adc 14468 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14469 int idx_number = 2;
14470 int idx_number_2 = 3;
14471 int idx_number_3 = 4;
585f1adc
IR
14472 int distance_ebgp = atoi(argv[idx_number]->arg);
14473 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14474 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14475 afi_t afi;
14476 safi_t safi;
718e3744 14477
d62a17ae 14478 afi = bgp_node_afi(vty);
14479 safi = bgp_node_safi(vty);
718e3744 14480
585f1adc
IR
14481 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14482 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14483 || bgp->distance_local[afi][safi] != distance_local) {
14484 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14485 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14486 bgp->distance_local[afi][safi] = distance_local;
14487 bgp_announce_routes_distance_update(bgp, afi, safi);
14488 }
14489 return CMD_SUCCESS;
14490}
37a87b8f 14491
585f1adc
IR
14492DEFUN (no_bgp_distance,
14493 no_bgp_distance_cmd,
14494 "no distance bgp [(1-255) (1-255) (1-255)]",
14495 NO_STR
14496 "Define an administrative distance\n"
14497 "BGP distance\n"
14498 "Distance for routes external to the AS\n"
14499 "Distance for routes internal to the AS\n"
14500 "Distance for local routes\n")
718e3744 14501{
585f1adc 14502 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14503 afi_t afi;
14504 safi_t safi;
37a87b8f
CS
14505
14506 afi = bgp_node_afi(vty);
14507 safi = bgp_node_safi(vty);
14508
585f1adc
IR
14509 if (bgp->distance_ebgp[afi][safi] != 0
14510 || bgp->distance_ibgp[afi][safi] != 0
14511 || bgp->distance_local[afi][safi] != 0) {
14512 bgp->distance_ebgp[afi][safi] = 0;
14513 bgp->distance_ibgp[afi][safi] = 0;
14514 bgp->distance_local[afi][safi] = 0;
14515 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14516 }
585f1adc
IR
14517 return CMD_SUCCESS;
14518}
37a87b8f 14519
37a87b8f 14520
585f1adc
IR
14521DEFUN (bgp_distance_source,
14522 bgp_distance_source_cmd,
14523 "distance (1-255) A.B.C.D/M",
14524 "Define an administrative distance\n"
14525 "Administrative distance\n"
14526 "IP source prefix\n")
14527{
14528 int idx_number = 1;
14529 int idx_ipv4_prefixlen = 2;
14530 bgp_distance_set(vty, argv[idx_number]->arg,
14531 argv[idx_ipv4_prefixlen]->arg, NULL);
14532 return CMD_SUCCESS;
734b349e
MZ
14533}
14534
585f1adc
IR
14535DEFUN (no_bgp_distance_source,
14536 no_bgp_distance_source_cmd,
14537 "no distance (1-255) A.B.C.D/M",
14538 NO_STR
14539 "Define an administrative distance\n"
14540 "Administrative distance\n"
14541 "IP source prefix\n")
37a87b8f 14542{
585f1adc
IR
14543 int idx_number = 2;
14544 int idx_ipv4_prefixlen = 3;
14545 bgp_distance_unset(vty, argv[idx_number]->arg,
14546 argv[idx_ipv4_prefixlen]->arg, NULL);
14547 return CMD_SUCCESS;
37a87b8f
CS
14548}
14549
585f1adc
IR
14550DEFUN (bgp_distance_source_access_list,
14551 bgp_distance_source_access_list_cmd,
14552 "distance (1-255) A.B.C.D/M WORD",
14553 "Define an administrative distance\n"
14554 "Administrative distance\n"
14555 "IP source prefix\n"
14556 "Access list name\n")
37a87b8f 14557{
585f1adc
IR
14558 int idx_number = 1;
14559 int idx_ipv4_prefixlen = 2;
14560 int idx_word = 3;
14561 bgp_distance_set(vty, argv[idx_number]->arg,
14562 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14563 return CMD_SUCCESS;
14564}
718e3744 14565
585f1adc
IR
14566DEFUN (no_bgp_distance_source_access_list,
14567 no_bgp_distance_source_access_list_cmd,
14568 "no distance (1-255) A.B.C.D/M WORD",
14569 NO_STR
14570 "Define an administrative distance\n"
14571 "Administrative distance\n"
14572 "IP source prefix\n"
14573 "Access list name\n")
14574{
14575 int idx_number = 2;
14576 int idx_ipv4_prefixlen = 3;
14577 int idx_word = 4;
14578 bgp_distance_unset(vty, argv[idx_number]->arg,
14579 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14580 return CMD_SUCCESS;
14581}
37a87b8f 14582
585f1adc
IR
14583DEFUN (ipv6_bgp_distance_source,
14584 ipv6_bgp_distance_source_cmd,
14585 "distance (1-255) X:X::X:X/M",
14586 "Define an administrative distance\n"
14587 "Administrative distance\n"
14588 "IP source prefix\n")
14589{
14590 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14591 return CMD_SUCCESS;
14592}
7ebe9748 14593
585f1adc
IR
14594DEFUN (no_ipv6_bgp_distance_source,
14595 no_ipv6_bgp_distance_source_cmd,
14596 "no distance (1-255) X:X::X:X/M",
14597 NO_STR
14598 "Define an administrative distance\n"
14599 "Administrative distance\n"
14600 "IP source prefix\n")
14601{
14602 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14603 return CMD_SUCCESS;
14604}
37a87b8f 14605
585f1adc
IR
14606DEFUN (ipv6_bgp_distance_source_access_list,
14607 ipv6_bgp_distance_source_access_list_cmd,
14608 "distance (1-255) X:X::X:X/M WORD",
14609 "Define an administrative distance\n"
14610 "Administrative distance\n"
14611 "IP source prefix\n"
14612 "Access list name\n")
14613{
14614 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14615 return CMD_SUCCESS;
718e3744 14616}
14617
585f1adc
IR
14618DEFUN (no_ipv6_bgp_distance_source_access_list,
14619 no_ipv6_bgp_distance_source_access_list_cmd,
14620 "no distance (1-255) X:X::X:X/M WORD",
14621 NO_STR
14622 "Define an administrative distance\n"
14623 "Administrative distance\n"
14624 "IP source prefix\n"
14625 "Access list name\n")
718e3744 14626{
585f1adc
IR
14627 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14628 return CMD_SUCCESS;
14629}
37a87b8f 14630
585f1adc
IR
14631DEFUN (bgp_damp_set,
14632 bgp_damp_set_cmd,
a30fec23 14633 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14634 "BGP Specific commands\n"
14635 "Enable route-flap dampening\n"
14636 "Half-life time for the penalty\n"
14637 "Value to start reusing a route\n"
14638 "Value to start suppressing a route\n"
14639 "Maximum duration to suppress a stable route\n")
14640{
14641 VTY_DECLVAR_CONTEXT(bgp, bgp);
14642 int idx_half_life = 2;
14643 int idx_reuse = 3;
14644 int idx_suppress = 4;
14645 int idx_max_suppress = 5;
37a87b8f
CS
14646 int half = DEFAULT_HALF_LIFE * 60;
14647 int reuse = DEFAULT_REUSE;
14648 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14649 int max = 4 * half;
14650
14651 if (argc == 6) {
14652 half = atoi(argv[idx_half_life]->arg) * 60;
14653 reuse = atoi(argv[idx_reuse]->arg);
14654 suppress = atoi(argv[idx_suppress]->arg);
14655 max = atoi(argv[idx_max_suppress]->arg) * 60;
14656 } else if (argc == 3) {
14657 half = atoi(argv[idx_half_life]->arg) * 60;
14658 max = 4 * half;
14659 }
14660
14661 /*
14662 * These can't be 0 but our SA doesn't understand the
14663 * way our cli is constructed
14664 */
14665 assert(reuse);
14666 assert(half);
14667 if (suppress < reuse) {
14668 vty_out(vty,
14669 "Suppress value cannot be less than reuse value \n");
14670 return 0;
14671 }
14672
14673 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14674 reuse, suppress, max);
14675}
14676
14677DEFUN (bgp_damp_unset,
14678 bgp_damp_unset_cmd,
a30fec23 14679 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14680 NO_STR
14681 "BGP Specific commands\n"
14682 "Enable route-flap dampening\n"
14683 "Half-life time for the penalty\n"
14684 "Value to start reusing a route\n"
14685 "Value to start suppressing a route\n"
14686 "Maximum duration to suppress a stable route\n")
14687{
14688 VTY_DECLVAR_CONTEXT(bgp, bgp);
14689 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14690}
14691
718e3744 14692/* Display specified route of BGP table. */
d62a17ae 14693static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14694 const char *ip_str, afi_t afi, safi_t safi,
14695 struct prefix_rd *prd, int prefix_check)
14696{
14697 int ret;
14698 struct prefix match;
9bcb3eef
DS
14699 struct bgp_dest *dest;
14700 struct bgp_dest *rm;
40381db7
DS
14701 struct bgp_path_info *pi;
14702 struct bgp_path_info *pi_temp;
d62a17ae 14703 struct bgp *bgp;
14704 struct bgp_table *table;
14705
14706 /* BGP structure lookup. */
14707 if (view_name) {
14708 bgp = bgp_lookup_by_name(view_name);
14709 if (bgp == NULL) {
14710 vty_out(vty, "%% Can't find BGP instance %s\n",
14711 view_name);
14712 return CMD_WARNING;
14713 }
14714 } else {
14715 bgp = bgp_get_default();
14716 if (bgp == NULL) {
14717 vty_out(vty, "%% No BGP process is configured\n");
14718 return CMD_WARNING;
14719 }
718e3744 14720 }
718e3744 14721
d62a17ae 14722 /* Check IP address argument. */
14723 ret = str2prefix(ip_str, &match);
14724 if (!ret) {
14725 vty_out(vty, "%% address is malformed\n");
14726 return CMD_WARNING;
14727 }
718e3744 14728
d62a17ae 14729 match.family = afi2family(afi);
14730
14731 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14732 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14733 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14734 dest = bgp_route_next(dest)) {
14735 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14736
9bcb3eef 14737 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14738 continue;
9bcb3eef 14739 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14740 if (!table)
ea47320b 14741 continue;
4953391b
DA
14742 rm = bgp_node_match(table, &match);
14743 if (rm == NULL)
ea47320b 14744 continue;
d62a17ae 14745
9bcb3eef 14746 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14747
ea47320b 14748 if (!prefix_check
b54892e0 14749 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14750 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14751 while (pi) {
14752 if (pi->extra && pi->extra->damp_info) {
14753 pi_temp = pi->next;
ea47320b 14754 bgp_damp_info_free(
19971c9a 14755 pi->extra->damp_info,
5c8846f6 14756 1, afi, safi);
40381db7 14757 pi = pi_temp;
ea47320b 14758 } else
40381db7 14759 pi = pi->next;
d62a17ae 14760 }
ea47320b
DL
14761 }
14762
9bcb3eef 14763 bgp_dest_unlock_node(rm);
d62a17ae 14764 }
14765 } else {
4953391b
DA
14766 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14767 if (dest != NULL) {
9bcb3eef 14768 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14769
d62a17ae 14770 if (!prefix_check
9bcb3eef
DS
14771 || dest_p->prefixlen == match.prefixlen) {
14772 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14773 while (pi) {
14774 if (pi->extra && pi->extra->damp_info) {
14775 pi_temp = pi->next;
d62a17ae 14776 bgp_damp_info_free(
19971c9a 14777 pi->extra->damp_info,
5c8846f6 14778 1, afi, safi);
40381db7 14779 pi = pi_temp;
d62a17ae 14780 } else
40381db7 14781 pi = pi->next;
d62a17ae 14782 }
14783 }
14784
9bcb3eef 14785 bgp_dest_unlock_node(dest);
d62a17ae 14786 }
14787 }
718e3744 14788
d62a17ae 14789 return CMD_SUCCESS;
718e3744 14790}
14791
14792DEFUN (clear_ip_bgp_dampening,
14793 clear_ip_bgp_dampening_cmd,
14794 "clear ip bgp dampening",
14795 CLEAR_STR
14796 IP_STR
14797 BGP_STR
14798 "Clear route flap dampening information\n")
14799{
b4f7f45b 14800 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14801 return CMD_SUCCESS;
718e3744 14802}
14803
14804DEFUN (clear_ip_bgp_dampening_prefix,
14805 clear_ip_bgp_dampening_prefix_cmd,
14806 "clear ip bgp dampening A.B.C.D/M",
14807 CLEAR_STR
14808 IP_STR
14809 BGP_STR
14810 "Clear route flap dampening information\n"
0c7b1b01 14811 "IPv4 prefix\n")
718e3744 14812{
d62a17ae 14813 int idx_ipv4_prefixlen = 4;
14814 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14815 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14816}
14817
14818DEFUN (clear_ip_bgp_dampening_address,
14819 clear_ip_bgp_dampening_address_cmd,
14820 "clear ip bgp dampening A.B.C.D",
14821 CLEAR_STR
14822 IP_STR
14823 BGP_STR
14824 "Clear route flap dampening information\n"
14825 "Network to clear damping information\n")
14826{
d62a17ae 14827 int idx_ipv4 = 4;
14828 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14829 SAFI_UNICAST, NULL, 0);
718e3744 14830}
14831
14832DEFUN (clear_ip_bgp_dampening_address_mask,
14833 clear_ip_bgp_dampening_address_mask_cmd,
14834 "clear ip bgp dampening A.B.C.D A.B.C.D",
14835 CLEAR_STR
14836 IP_STR
14837 BGP_STR
14838 "Clear route flap dampening information\n"
14839 "Network to clear damping information\n"
14840 "Network mask\n")
14841{
d62a17ae 14842 int idx_ipv4 = 4;
14843 int idx_ipv4_2 = 5;
14844 int ret;
14845 char prefix_str[BUFSIZ];
718e3744 14846
d62a17ae 14847 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14848 prefix_str, sizeof(prefix_str));
d62a17ae 14849 if (!ret) {
14850 vty_out(vty, "%% Inconsistent address and mask\n");
14851 return CMD_WARNING;
14852 }
718e3744 14853
d62a17ae 14854 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14855 NULL, 0);
718e3744 14856}
6b0655a2 14857
e3b78da8 14858static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14859{
14860 struct vty *vty = arg;
e3b78da8 14861 struct peer *peer = bucket->data;
825d9834
DS
14862 char buf[SU_ADDRSTRLEN];
14863
14864 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14865 sockunion2str(&peer->su, buf, sizeof(buf)));
14866}
14867
2a0e69ae
DS
14868DEFUN (show_bgp_listeners,
14869 show_bgp_listeners_cmd,
14870 "show bgp listeners",
14871 SHOW_STR
14872 BGP_STR
14873 "Display Listen Sockets and who created them\n")
14874{
14875 bgp_dump_listener_info(vty);
14876
14877 return CMD_SUCCESS;
14878}
14879
825d9834
DS
14880DEFUN (show_bgp_peerhash,
14881 show_bgp_peerhash_cmd,
14882 "show bgp peerhash",
14883 SHOW_STR
14884 BGP_STR
14885 "Display information about the BGP peerhash\n")
14886{
14887 struct list *instances = bm->bgp;
14888 struct listnode *node;
14889 struct bgp *bgp;
14890
14891 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14892 vty_out(vty, "BGP: %s\n", bgp->name);
14893 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14894 vty);
14895 }
14896
14897 return CMD_SUCCESS;
14898}
14899
587ff0fd 14900/* also used for encap safi */
2b791107
DL
14901static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14902 afi_t afi, safi_t safi)
d62a17ae 14903{
9bcb3eef
DS
14904 struct bgp_dest *pdest;
14905 struct bgp_dest *dest;
d62a17ae 14906 struct bgp_table *table;
b54892e0
DS
14907 const struct prefix *p;
14908 const struct prefix_rd *prd;
d62a17ae 14909 struct bgp_static *bgp_static;
14910 mpls_label_t label;
d62a17ae 14911 char rdbuf[RD_ADDRSTRLEN];
14912
14913 /* Network configuration. */
9bcb3eef
DS
14914 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14915 pdest = bgp_route_next(pdest)) {
14916 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14917 if (!table)
ea47320b 14918 continue;
d62a17ae 14919
9bcb3eef
DS
14920 for (dest = bgp_table_top(table); dest;
14921 dest = bgp_route_next(dest)) {
14922 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14923 if (bgp_static == NULL)
ea47320b 14924 continue;
d62a17ae 14925
9bcb3eef
DS
14926 p = bgp_dest_get_prefix(dest);
14927 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14928 pdest);
d62a17ae 14929
ea47320b 14930 /* "network" configuration display. */
06b9f471 14931 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14932 label = decode_label(&bgp_static->label);
14933
8228a9a7 14934 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14935 if (safi == SAFI_MPLS_VPN)
14936 vty_out(vty, " label %u", label);
14937
14938 if (bgp_static->rmap.name)
14939 vty_out(vty, " route-map %s",
14940 bgp_static->rmap.name);
e2a86ad9
DS
14941
14942 if (bgp_static->backdoor)
14943 vty_out(vty, " backdoor");
14944
ea47320b
DL
14945 vty_out(vty, "\n");
14946 }
14947 }
d62a17ae 14948}
14949
2b791107
DL
14950static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14951 afi_t afi, safi_t safi)
d62a17ae 14952{
9bcb3eef
DS
14953 struct bgp_dest *pdest;
14954 struct bgp_dest *dest;
d62a17ae 14955 struct bgp_table *table;
b54892e0
DS
14956 const struct prefix *p;
14957 const struct prefix_rd *prd;
d62a17ae 14958 struct bgp_static *bgp_static;
ff44f570 14959 char buf[PREFIX_STRLEN * 2];
d62a17ae 14960 char buf2[SU_ADDRSTRLEN];
14961 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14962 char esi_buf[ESI_BYTES];
d62a17ae 14963
14964 /* Network configuration. */
9bcb3eef
DS
14965 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14966 pdest = bgp_route_next(pdest)) {
14967 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14968 if (!table)
ea47320b 14969 continue;
d62a17ae 14970
9bcb3eef
DS
14971 for (dest = bgp_table_top(table); dest;
14972 dest = bgp_route_next(dest)) {
14973 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14974 if (bgp_static == NULL)
ea47320b 14975 continue;
d62a17ae 14976
ea47320b 14977 char *macrouter = NULL;
d62a17ae 14978
ea47320b
DL
14979 if (bgp_static->router_mac)
14980 macrouter = prefix_mac2str(
14981 bgp_static->router_mac, NULL, 0);
14982 if (bgp_static->eth_s_id)
0a50c248
AK
14983 esi_to_str(bgp_static->eth_s_id,
14984 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14985 p = bgp_dest_get_prefix(dest);
14986 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14987
ea47320b 14988 /* "network" configuration display. */
06b9f471 14989 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14990 if (p->u.prefix_evpn.route_type == 5) {
14991 char local_buf[PREFIX_STRLEN];
3714a385 14992 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14993 struct prefix_evpn *)p)
14994 ? AF_INET
14995 : AF_INET6;
3714a385 14996 inet_ntop(family,
14997 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14998 local_buf, PREFIX_STRLEN);
772270f3
QY
14999 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15000 p->u.prefix_evpn.prefix_addr
15001 .ip_prefix_length);
197cb530
PG
15002 } else {
15003 prefix2str(p, buf, sizeof(buf));
15004 }
ea47320b 15005
a4d82a8a
PZ
15006 if (bgp_static->gatewayIp.family == AF_INET
15007 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15008 inet_ntop(bgp_static->gatewayIp.family,
15009 &bgp_static->gatewayIp.u.prefix, buf2,
15010 sizeof(buf2));
ea47320b 15011 vty_out(vty,
7bcc8dac 15012 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15013 buf, rdbuf,
15014 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15015 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15016 macrouter);
15017
0a22ddfb 15018 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15019 }
15020 }
3da6fcd5
PG
15021}
15022
718e3744 15023/* Configuration of static route announcement and aggregate
15024 information. */
2b791107
DL
15025void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15026 safi_t safi)
d62a17ae 15027{
9bcb3eef 15028 struct bgp_dest *dest;
b54892e0 15029 const struct prefix *p;
d62a17ae 15030 struct bgp_static *bgp_static;
15031 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15032
2b791107
DL
15033 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15034 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15035 return;
15036 }
d62a17ae 15037
2b791107
DL
15038 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15039 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15040 return;
15041 }
d62a17ae 15042
15043 /* Network configuration. */
9bcb3eef
DS
15044 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15045 dest = bgp_route_next(dest)) {
15046 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15047 if (bgp_static == NULL)
ea47320b 15048 continue;
d62a17ae 15049
9bcb3eef 15050 p = bgp_dest_get_prefix(dest);
d62a17ae 15051
8228a9a7 15052 vty_out(vty, " network %pFX", p);
d62a17ae 15053
ea47320b
DL
15054 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15055 vty_out(vty, " label-index %u",
15056 bgp_static->label_index);
d62a17ae 15057
ea47320b
DL
15058 if (bgp_static->rmap.name)
15059 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15060
15061 if (bgp_static->backdoor)
15062 vty_out(vty, " backdoor");
718e3744 15063
ea47320b
DL
15064 vty_out(vty, "\n");
15065 }
15066
d62a17ae 15067 /* Aggregate-address configuration. */
9bcb3eef
DS
15068 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15069 dest = bgp_route_next(dest)) {
15070 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15071 if (bgp_aggregate == NULL)
ea47320b 15072 continue;
d62a17ae 15073
9bcb3eef 15074 p = bgp_dest_get_prefix(dest);
d62a17ae 15075
8228a9a7 15076 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15077
ea47320b
DL
15078 if (bgp_aggregate->as_set)
15079 vty_out(vty, " as-set");
d62a17ae 15080
ea47320b
DL
15081 if (bgp_aggregate->summary_only)
15082 vty_out(vty, " summary-only");
718e3744 15083
20894f50
DA
15084 if (bgp_aggregate->rmap.name)
15085 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15086
229757f1
DA
15087 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15088 vty_out(vty, " origin %s",
15089 bgp_origin2str(bgp_aggregate->origin));
15090
6aabb15d
RZ
15091 if (bgp_aggregate->match_med)
15092 vty_out(vty, " matching-MED-only");
15093
365ab2e7
RZ
15094 if (bgp_aggregate->suppress_map_name)
15095 vty_out(vty, " suppress-map %s",
15096 bgp_aggregate->suppress_map_name);
15097
ea47320b
DL
15098 vty_out(vty, "\n");
15099 }
d62a17ae 15100}
734b349e 15101
2b791107 15102void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15103 safi_t safi)
d62a17ae 15104{
9bcb3eef 15105 struct bgp_dest *dest;
d62a17ae 15106 struct bgp_distance *bdistance;
15107
15108 /* Distance configuration. */
15109 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15110 && bgp->distance_local[afi][safi]
15111 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15112 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15113 || bgp->distance_local[afi][safi]
15114 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15115 vty_out(vty, " distance bgp %d %d %d\n",
15116 bgp->distance_ebgp[afi][safi],
15117 bgp->distance_ibgp[afi][safi],
15118 bgp->distance_local[afi][safi]);
15119 }
734b349e 15120
9bcb3eef
DS
15121 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15122 dest = bgp_route_next(dest)) {
15123 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15124 if (bdistance != NULL)
56ca3b5b 15125 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15126 bdistance->distance, dest,
d62a17ae 15127 bdistance->access_list ? bdistance->access_list
15128 : "");
ca2e160d 15129 }
718e3744 15130}
15131
15132/* Allocate routing table structure and install commands. */
d62a17ae 15133void bgp_route_init(void)
15134{
15135 afi_t afi;
15136 safi_t safi;
15137
15138 /* Init BGP distance table. */
05c7a1cc 15139 FOREACH_AFI_SAFI (afi, safi)
960035b2 15140 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15141
15142 /* IPv4 BGP commands. */
15143 install_element(BGP_NODE, &bgp_table_map_cmd);
15144 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15145 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15146
554b3b10 15147 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15148
15149 /* IPv4 unicast configuration. */
15150 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15151 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15152 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15153
554b3b10 15154 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15155
15156 /* IPv4 multicast configuration. */
15157 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15158 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15159 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15160 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15161
15162 /* IPv4 labeled-unicast configuration. */
fb985e0c 15163 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15164 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15165
d62a17ae 15166 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15167 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15168 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15169 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15170 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15171 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15172 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15173 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15174
15175 install_element(VIEW_NODE,
15176 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15177 install_element(VIEW_NODE,
15178 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15179 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15180 install_element(VIEW_NODE,
15181 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15182#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15183 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15184#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15185 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15186 install_element(VIEW_NODE,
44c69747 15187 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15188
d62a17ae 15189 /* BGP dampening clear commands */
15190 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15191 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15192
d62a17ae 15193 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15194 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15195
15196 /* prefix count */
15197 install_element(ENABLE_NODE,
15198 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15199#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15200 install_element(ENABLE_NODE,
15201 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15202#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15203
d62a17ae 15204 /* New config IPv6 BGP commands. */
15205 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15206 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15207 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15208
554b3b10 15209 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15210
15211 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15212
fb985e0c
DA
15213 /* IPv6 labeled unicast address family. */
15214 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15215 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15216
d62a17ae 15217 install_element(BGP_NODE, &bgp_distance_cmd);
15218 install_element(BGP_NODE, &no_bgp_distance_cmd);
15219 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15220 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15221 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15222 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15223 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15224 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15225 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15226 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15227 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15228 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15229 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15230 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15231 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15232 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15233 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15234 install_element(BGP_IPV4M_NODE,
15235 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15236 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15237 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15238 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15239 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15240 install_element(BGP_IPV6_NODE,
15241 &ipv6_bgp_distance_source_access_list_cmd);
15242 install_element(BGP_IPV6_NODE,
15243 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15244 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15245 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15246 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15247 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15248 install_element(BGP_IPV6M_NODE,
15249 &ipv6_bgp_distance_source_access_list_cmd);
15250 install_element(BGP_IPV6M_NODE,
15251 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15252
ef5f4b23 15253 /* BGP dampening */
585f1adc
IR
15254 install_element(BGP_NODE, &bgp_damp_set_cmd);
15255 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15256 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15257 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15258 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15259 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15260 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15261 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15262 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15263 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15264 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15265 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15266 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15267 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15268
15269 /* Large Communities */
15270 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15271 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15272
15273 /* show bgp ipv4 flowspec detailed */
15274 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15275
2a0e69ae 15276 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15277 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15278}
15279
15280void bgp_route_finish(void)
15281{
15282 afi_t afi;
15283 safi_t safi;
15284
05c7a1cc
QY
15285 FOREACH_AFI_SAFI (afi, safi) {
15286 bgp_table_unlock(bgp_distance_table[afi][safi]);
15287 bgp_distance_table[afi][safi] = NULL;
15288 }
228da428 15289}