]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #11422 from opensourcerouting/feature/autoclose_stale_issues_prs
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
7fd28dd2
PR
96DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 98 (rn, pi, added));
7fd28dd2 99
b5b99af8
DS
100DEFINE_HOOK(bgp_rpki_prefix_status,
101 (struct peer *peer, struct attr *attr,
102 const struct prefix *prefix),
8451921b 103 (peer, attr, prefix));
b5b99af8 104
2aad8c42
MS
105/* Render dest to prefix_rd based on safi */
106static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
107 safi_t safi);
108
718e3744 109/* Extern from bgp_dump.c */
dde72586
SH
110extern const char *bgp_origin_str[];
111extern const char *bgp_origin_long_str[];
3742de8d 112
b7d08f5a 113/* PMSI strings. */
114#define PMSI_TNLTYPE_STR_NO_INFO "No info"
115#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116static const struct message bgp_pmsi_tnltype_str[] = {
117 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 125 {0}
126};
b7d08f5a 127
9df8b37c 128#define VRFID_NONE_STR "-"
46aeabed 129#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 130
4a11bf2c 131DEFINE_HOOK(bgp_process,
9bcb3eef
DS
132 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
133 struct peer *peer, bool withdraw),
8451921b 134 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 135
4056a5f6
RZ
136/** Test if path is suppressed. */
137static bool bgp_path_suppressed(struct bgp_path_info *pi)
138{
139 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
140 return false;
141
142 return listcount(pi->extra->aggr_suppressors) > 0;
143}
4a11bf2c 144
9bcb3eef 145struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 146 safi_t safi, const struct prefix *p,
d62a17ae 147 struct prefix_rd *prd)
148{
9bcb3eef
DS
149 struct bgp_dest *dest;
150 struct bgp_dest *pdest = NULL;
d62a17ae 151
152 assert(table);
d62a17ae 153
154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN)) {
9bcb3eef 156 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 157
9bcb3eef
DS
158 if (!bgp_dest_has_bgp_path_info_data(pdest))
159 bgp_dest_set_bgp_table_info(
160 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 161 else
9bcb3eef
DS
162 bgp_dest_unlock_node(pdest);
163 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 164 }
718e3744 165
9bcb3eef 166 dest = bgp_node_get(table, p);
718e3744 167
d62a17ae 168 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
169 || (safi == SAFI_EVPN))
9bcb3eef 170 dest->pdest = pdest;
718e3744 171
9bcb3eef 172 return dest;
718e3744 173}
6b0655a2 174
9bcb3eef 175struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 176 safi_t safi, const struct prefix *p,
d62a17ae 177 struct prefix_rd *prd)
128ea8ab 178{
9bcb3eef
DS
179 struct bgp_dest *dest;
180 struct bgp_dest *pdest = NULL;
128ea8ab 181
d62a17ae 182 if (!table)
183 return NULL;
128ea8ab 184
d62a17ae 185 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
186 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
187 pdest = bgp_node_lookup(table, (struct prefix *)prd);
188 if (!pdest)
d62a17ae 189 return NULL;
128ea8ab 190
9bcb3eef
DS
191 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
192 bgp_dest_unlock_node(pdest);
d62a17ae 193 return NULL;
194 }
128ea8ab 195
9bcb3eef 196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 197 }
128ea8ab 198
9bcb3eef 199 dest = bgp_node_lookup(table, p);
128ea8ab 200
9bcb3eef 201 return dest;
128ea8ab 202}
203
18ee8310
DS
204/* Allocate bgp_path_info_extra */
205static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 206{
4b7e6066
DS
207 struct bgp_path_info_extra *new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
209 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
210 new->label[0] = MPLS_INVALID_LABEL;
211 new->num_labels = 0;
3e3708cb
PG
212 new->bgp_fs_pbr = NULL;
213 new->bgp_fs_iprule = NULL;
d62a17ae 214 return new;
fb982c25
PJ
215}
216
a2e219fe 217void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 218{
4b7e6066 219 struct bgp_path_info_extra *e;
d62a17ae 220
c93a3b77
DS
221 if (!extra || !*extra)
222 return;
d62a17ae 223
c93a3b77 224 e = *extra;
4538f895 225 if (e->damp_info)
b4f7f45b
IR
226 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
227 e->damp_info->safi);
4538f895 228
c93a3b77
DS
229 e->damp_info = NULL;
230 if (e->parent) {
40381db7 231 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 232
40381db7 233 if (bpi->net) {
0e70e6c8
DL
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
237 *
40381db7
DS
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
0e70e6c8
DL
241 */
242 unsigned refcount;
243
40381db7 244 bpi = bgp_path_info_lock(bpi);
c10e14e9 245 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 246 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 247 if (!refcount)
40381db7
DS
248 bpi->net = NULL;
249 bgp_path_info_unlock(bpi);
0e70e6c8 250 }
18ee8310 251 bgp_path_info_unlock(e->parent);
c93a3b77 252 e->parent = NULL;
d62a17ae 253 }
c93a3b77
DS
254
255 if (e->bgp_orig)
256 bgp_unlock(e->bgp_orig);
c26edcda 257
ff3bf9a4
DS
258 if (e->aggr_suppressors)
259 list_delete(&e->aggr_suppressors);
260
60605cbc
AK
261 if (e->mh_info)
262 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 263
ce3c0614
PG
264 if ((*extra)->bgp_fs_iprule)
265 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 266 if ((*extra)->bgp_fs_pbr)
6a154c88 267 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 268 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
269}
270
18ee8310
DS
271/* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
fb982c25 273 */
40381db7 274struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 275{
40381db7
DS
276 if (!pi->extra)
277 pi->extra = bgp_path_info_extra_new();
278 return pi->extra;
fb982c25
PJ
279}
280
718e3744 281/* Free bgp route information. */
9b6d8fcf 282static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 283{
05864da7 284 bgp_attr_unintern(&path->attr);
fb018d25 285
9b6d8fcf
DS
286 bgp_unlink_nexthop(path);
287 bgp_path_info_extra_free(&path->extra);
288 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
289 if (path->net)
290 bgp_addpath_free_info_data(&path->tx_addpath,
291 &path->net->tx_addpath);
718e3744 292
9b6d8fcf 293 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 294
9b6d8fcf 295 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 296}
297
9b6d8fcf 298struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 299{
9b6d8fcf
DS
300 path->lock++;
301 return path;
200df115 302}
303
9b6d8fcf 304struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 305{
9b6d8fcf
DS
306 assert(path && path->lock > 0);
307 path->lock--;
d62a17ae 308
9b6d8fcf 309 if (path->lock == 0) {
9b6d8fcf 310 bgp_path_info_free(path);
d62a17ae 311 return NULL;
312 }
200df115 313
9b6d8fcf 314 return path;
200df115 315}
316
f009ff26 317/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 318static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 319{
320 struct peer *peer;
321 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 322 bool set_flag = false;
f009ff26 323 struct bgp *bgp = NULL;
324 struct bgp_table *table = NULL;
325 afi_t afi = 0;
326 safi_t safi = 0;
f009ff26 327
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
330 */
9bcb3eef 331 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 332 return 0;
333
9bcb3eef 334 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 335 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 336 zlog_debug(
56ca3b5b
DL
337 "Route %pBD is in workqueue and being processed, not deferred.",
338 dest);
b54892e0 339
5f9c1aa2 340 return 0;
341 }
342
9bcb3eef 343 table = bgp_dest_table(dest);
f009ff26 344 if (table) {
345 bgp = table->bgp;
346 afi = table->afi;
347 safi = table->safi;
348 }
349
9bcb3eef 350 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 351 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
352 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
353 continue;
354
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
357 */
36235319
QY
358 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
359 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 360 set_flag = true;
f009ff26 361 } else {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
364 */
365 peer = old_pi->peer;
36235319
QY
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
367 && BGP_PEER_RESTARTING_MODE(peer)
368 && (old_pi
369 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 370 set_flag = true;
f009ff26 371 }
372 }
373 if (set_flag)
374 break;
375 }
376
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
378 * is active
379 */
2ba1fe69 380 if (set_flag && table) {
f009ff26 381 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
382 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
383 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 384 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 385 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
386 zlog_debug("DEFER route %pBD, dest %p", dest,
387 dest);
f009ff26 388 return 0;
389 }
390 }
391 return -1;
392}
393
9bcb3eef 394void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 395{
4b7e6066 396 struct bgp_path_info *top;
718e3744 397
9bcb3eef 398 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 399
6f94b685 400 pi->next = top;
40381db7 401 pi->prev = NULL;
d62a17ae 402 if (top)
40381db7 403 top->prev = pi;
9bcb3eef 404 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 405
40381db7 406 bgp_path_info_lock(pi);
9bcb3eef 407 bgp_dest_lock_node(dest);
40381db7 408 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 409 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 410 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 411}
412
d62a17ae 413/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 414 completion callback *only* */
9bcb3eef 415void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 416{
40381db7
DS
417 if (pi->next)
418 pi->next->prev = pi->prev;
419 if (pi->prev)
420 pi->prev->next = pi->next;
d62a17ae 421 else
9bcb3eef 422 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 423
40381db7
DS
424 bgp_path_info_mpath_dequeue(pi);
425 bgp_path_info_unlock(pi);
7fd28dd2 426 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 427 bgp_dest_unlock_node(dest);
718e3744 428}
429
9bcb3eef 430void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 431{
9bcb3eef 432 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 433 /* set of previous already took care of pcount */
40381db7 434 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 435}
436
18ee8310 437/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
438 called when a route is deleted and then quickly re-added before the
439 deletion has been processed */
9bcb3eef 440void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 441{
9bcb3eef 442 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 443 /* unset of previous already took care of pcount */
40381db7 444 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
445}
446
d62a17ae 447/* Adjust pcount as required */
9bcb3eef 448static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 449{
d62a17ae 450 struct bgp_table *table;
67174041 451
9bcb3eef 452 assert(dest && bgp_dest_table(dest));
40381db7 453 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 454
9bcb3eef 455 table = bgp_dest_table(dest);
67174041 456
40381db7 457 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 458 return;
459
40381db7
DS
460 if (!BGP_PATH_COUNTABLE(pi)
461 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 462
40381db7 463 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 464
465 /* slight hack, but more robust against errors. */
40381db7
DS
466 if (pi->peer->pcount[table->afi][table->safi])
467 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 468 else
450971aa 469 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 470 "Asked to decrement 0 prefix count for peer");
40381db7
DS
471 } else if (BGP_PATH_COUNTABLE(pi)
472 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
473 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
474 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 475 }
1a392d46
PJ
476}
477
40381db7
DS
478static int bgp_label_index_differs(struct bgp_path_info *pi1,
479 struct bgp_path_info *pi2)
28d58fd7 480{
40381db7 481 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 482}
1a392d46 483
18ee8310 484/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
485 * This is here primarily to keep prefix-count in check.
486 */
9bcb3eef 487void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 488 uint32_t flag)
1a392d46 489{
40381db7 490 SET_FLAG(pi->flags, flag);
d62a17ae 491
492 /* early bath if we know it's not a flag that changes countability state
493 */
494 if (!CHECK_FLAG(flag,
1defdda8 495 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 496 return;
497
9bcb3eef 498 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
499}
500
9bcb3eef 501void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 502 uint32_t flag)
1a392d46 503{
40381db7 504 UNSET_FLAG(pi->flags, flag);
d62a17ae 505
506 /* early bath if we know it's not a flag that changes countability state
507 */
508 if (!CHECK_FLAG(flag,
1defdda8 509 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 510 return;
511
9bcb3eef 512 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
513}
514
718e3744 515/* Get MED value. If MED value is missing and "bgp bestpath
516 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 517static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 518{
519 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
520 return attr->med;
521 else {
892fedb6 522 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 523 return BGP_MED_MAX;
524 else
525 return 0;
526 }
718e3744 527}
528
7533cad7
QY
529void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
530 size_t buf_len)
2ec1e66f 531{
40381db7 532 if (pi->addpath_rx_id)
7533cad7
QY
533 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
534 pi->peer->host, pi->addpath_rx_id);
d62a17ae 535 else
7533cad7 536 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 537}
9fbdd100 538
da0c0ef7
KM
539
540/*
541 * Get the ultimate path info.
542 */
543struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
544{
545 struct bgp_path_info *bpi_ultimate;
546
547 if (info->sub_type != BGP_ROUTE_IMPORTED)
548 return info;
549
550 for (bpi_ultimate = info;
551 bpi_ultimate->extra && bpi_ultimate->extra->parent;
552 bpi_ultimate = bpi_ultimate->extra->parent)
553 ;
554
555 return bpi_ultimate;
556}
557
d62a17ae 558/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 */
18ee8310
DS
560static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
561 struct bgp_path_info *exist, int *paths_eq,
562 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
563 char *pfx_buf, afi_t afi, safi_t safi,
564 enum bgp_path_selection_reason *reason)
d62a17ae 565{
5df26422 566 const struct prefix *new_p;
d62a17ae 567 struct attr *newattr, *existattr;
3061acc2
DA
568 enum bgp_peer_sort new_sort;
569 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
570 uint32_t new_pref;
571 uint32_t exist_pref;
572 uint32_t new_med;
573 uint32_t exist_med;
574 uint32_t new_weight;
575 uint32_t exist_weight;
d62a17ae 576 uint32_t newm, existm;
577 struct in_addr new_id;
578 struct in_addr exist_id;
579 int new_cluster;
580 int exist_cluster;
581 int internal_as_route;
582 int confed_as_route;
04d14c8b 583 int ret = 0;
ee88563a
JM
584 int igp_metric_ret = 0;
585 int peer_sort_ret = -1;
d62a17ae 586 char new_buf[PATH_ADDPATH_STR_BUFFER];
587 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
588 uint32_t new_mm_seq;
589 uint32_t exist_mm_seq;
6d8c603a 590 int nh_cmp;
d071f237
AK
591 esi_t *exist_esi;
592 esi_t *new_esi;
593 bool same_esi;
594 bool old_proxy;
595 bool new_proxy;
33c6e933 596 bool new_origin, exist_origin;
da0c0ef7 597 struct bgp_path_info *bpi_ultimate;
d62a17ae 598
599 *paths_eq = 0;
600
601 /* 0. Null check. */
602 if (new == NULL) {
fdf81fa0 603 *reason = bgp_path_selection_none;
d62a17ae 604 if (debug)
605 zlog_debug("%s: new is NULL", pfx_buf);
606 return 0;
607 }
2ec1e66f 608
da0c0ef7
KM
609 if (debug) {
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 612 sizeof(new_buf));
da0c0ef7 613 }
718e3744 614
d62a17ae 615 if (exist == NULL) {
fdf81fa0 616 *reason = bgp_path_selection_first;
d62a17ae 617 if (debug)
4378495a
DS
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 620 return 1;
621 }
2ec1e66f 622
d62a17ae 623 if (debug) {
da0c0ef7
KM
624 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 626 sizeof(exist_buf));
4378495a
DS
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf, bgp->name_pretty, new_buf, new->flags,
629 exist_buf, exist->flags);
d62a17ae 630 }
8ff56318 631
d62a17ae 632 newattr = new->attr;
633 existattr = exist->attr;
634
1479ed2f
DA
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
639 *
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
643 */
9a706b42
DA
644 if (bgp_attr_get_community(newattr) &&
645 community_include(bgp_attr_get_community(newattr),
646 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
647 if (debug)
648 zlog_debug(
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf, new_buf, exist_buf);
651 return 0;
652 }
653
9a706b42
DA
654 if (bgp_attr_get_community(existattr) &&
655 community_include(bgp_attr_get_community(existattr),
656 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
657 if (debug)
658 zlog_debug(
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf, new_buf, exist_buf);
661 return 1;
662 }
663
5df26422
NS
664 new_p = bgp_dest_get_prefix(new->net);
665
d62a17ae 666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
668 */
5df26422
NS
669 if ((safi == SAFI_EVPN)
670 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 671 /* This is an error condition described in RFC 7432 Section
672 * 15.2. The RFC
673 * states that in this scenario "the PE MUST alert the operator"
674 * but it
675 * does not state what other action to take. In order to provide
676 * some
677 * consistency in this scenario we are going to prefer the path
678 * with the
679 * sticky flag.
680 */
681 if (newattr->sticky != existattr->sticky) {
682 if (!debug) {
5df26422
NS
683 prefix2str(new_p, pfx_buf,
684 sizeof(*pfx_buf)
685 * PREFIX2STR_BUFFER);
18ee8310 686 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
687 new, new_buf, sizeof(new_buf));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist, exist_buf, sizeof(exist_buf));
d62a17ae 690 }
691
692 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 693 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
694 if (debug)
695 zlog_debug(
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf, new_buf, exist_buf);
d62a17ae 698 return 1;
699 }
700
701 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 702 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
703 if (debug)
704 zlog_debug(
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf, new_buf, exist_buf);
d62a17ae 707 return 0;
708 }
709 }
128ea8ab 710
d071f237
AK
711 new_esi = bgp_evpn_attr_get_esi(newattr);
712 exist_esi = bgp_evpn_attr_get_esi(existattr);
713 if (bgp_evpn_is_esi_valid(new_esi) &&
714 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
715 same_esi = true;
716 } else {
717 same_esi = false;
718 }
719
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
726 */
727 if (same_esi) {
728 char esi_buf[ESI_STR_LEN];
729
730 if (bgp_evpn_is_path_local(bgp, new)) {
731 *reason = bgp_path_selection_evpn_local_path;
732 if (debug)
733 zlog_debug(
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf, new_buf, exist_buf,
736 esi_to_str(new_esi, esi_buf,
737 sizeof(esi_buf)));
738 return 1;
739 }
740 if (bgp_evpn_is_path_local(bgp, exist)) {
741 *reason = bgp_path_selection_evpn_local_path;
742 if (debug)
743 zlog_debug(
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf, new_buf, exist_buf,
746 esi_to_str(new_esi, esi_buf,
747 sizeof(esi_buf)));
748 return 0;
749 }
750 }
751
d62a17ae 752 new_mm_seq = mac_mobility_seqnum(newattr);
753 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 754
d62a17ae 755 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 756 *reason = bgp_path_selection_evpn_seq;
d62a17ae 757 if (debug)
758 zlog_debug(
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf, new_buf, exist_buf, new_mm_seq,
761 exist_mm_seq);
762 return 1;
763 }
8ff56318 764
d62a17ae 765 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 766 *reason = bgp_path_selection_evpn_seq;
d62a17ae 767 if (debug)
768 zlog_debug(
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf, new_buf, exist_buf, new_mm_seq,
771 exist_mm_seq);
772 return 0;
773 }
6d8c603a 774
d071f237
AK
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
777 */
778 new_proxy = bgp_evpn_attr_is_proxy(newattr);
779 old_proxy = bgp_evpn_attr_is_proxy(existattr);
780 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
781 old_proxy != new_proxy) {
782 if (!new_proxy) {
783 *reason = bgp_path_selection_evpn_non_proxy;
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf, new_buf, exist_buf);
788 return 1;
789 }
790
791 *reason = bgp_path_selection_evpn_non_proxy;
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf, new_buf, exist_buf);
796 return 0;
797 }
798
6d8c603a
AK
799 /*
800 * if sequence numbers are the same path with the lowest IP
801 * wins
802 */
803 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
804 if (nh_cmp < 0) {
fdf81fa0 805 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
806 if (debug)
807 zlog_debug(
23d0a753 808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 809 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 810 &new->attr->nexthop);
6d8c603a
AK
811 return 1;
812 }
813 if (nh_cmp > 0) {
fdf81fa0 814 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
815 if (debug)
816 zlog_debug(
23d0a753 817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 818 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 819 &new->attr->nexthop);
6d8c603a
AK
820 return 0;
821 }
d62a17ae 822 }
9fbdd100 823
d62a17ae 824 /* 1. Weight check. */
d62a17ae 825 new_weight = newattr->weight;
826 exist_weight = existattr->weight;
8ff56318 827
d62a17ae 828 if (new_weight > exist_weight) {
fdf81fa0 829 *reason = bgp_path_selection_weight;
d62a17ae 830 if (debug)
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf, new_buf, exist_buf, new_weight,
833 exist_weight);
834 return 1;
835 }
718e3744 836
d62a17ae 837 if (new_weight < exist_weight) {
fdf81fa0 838 *reason = bgp_path_selection_weight;
d62a17ae 839 if (debug)
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf, new_buf, exist_buf, new_weight,
842 exist_weight);
843 return 0;
844 }
9fbdd100 845
d62a17ae 846 /* 2. Local preference check. */
847 new_pref = exist_pref = bgp->default_local_pref;
848
849 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 new_pref = newattr->local_pref;
851 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
852 exist_pref = existattr->local_pref;
853
854 if (new_pref > exist_pref) {
fdf81fa0 855 *reason = bgp_path_selection_local_pref;
d62a17ae 856 if (debug)
857 zlog_debug(
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf, new_buf, exist_buf, new_pref,
860 exist_pref);
861 return 1;
862 }
718e3744 863
d62a17ae 864 if (new_pref < exist_pref) {
fdf81fa0 865 *reason = bgp_path_selection_local_pref;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf, new_buf, exist_buf, new_pref,
870 exist_pref);
871 return 0;
872 }
9fbdd100 873
d62a17ae 874 /* 3. Local route check. We prefer:
875 * - BGP_ROUTE_STATIC
876 * - BGP_ROUTE_AGGREGATE
877 * - BGP_ROUTE_REDISTRIBUTE
878 */
33c6e933
DS
879 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
880 new->sub_type == BGP_ROUTE_IMPORTED);
881 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
882 exist->sub_type == BGP_ROUTE_IMPORTED);
883
884 if (new_origin && !exist_origin) {
fdf81fa0 885 *reason = bgp_path_selection_local_route;
d62a17ae 886 if (debug)
887 zlog_debug(
888 "%s: %s wins over %s due to preferred BGP_ROUTE type",
889 pfx_buf, new_buf, exist_buf);
890 return 1;
891 }
718e3744 892
33c6e933 893 if (!new_origin && exist_origin) {
fdf81fa0 894 *reason = bgp_path_selection_local_route;
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s loses to %s due to preferred BGP_ROUTE type",
898 pfx_buf, new_buf, exist_buf);
899 return 0;
6811845b 900 }
718e3744 901
da0c0ef7
KM
902 /* Here if these are imported routes then get ultimate pi for
903 * path compare.
904 */
905 new = bgp_get_imported_bpi_ultimate(new);
906 exist = bgp_get_imported_bpi_ultimate(exist);
907 newattr = new->attr;
908 existattr = exist->attr;
909
d62a17ae 910 /* 4. AS path length check. */
892fedb6 911 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 912 int exist_hops = aspath_count_hops(existattr->aspath);
913 int exist_confeds = aspath_count_confeds(existattr->aspath);
914
892fedb6 915 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 916 int aspath_hops;
917
918 aspath_hops = aspath_count_hops(newattr->aspath);
919 aspath_hops += aspath_count_confeds(newattr->aspath);
920
921 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 922 *reason = bgp_path_selection_confed_as_path;
d62a17ae 923 if (debug)
924 zlog_debug(
925 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
926 pfx_buf, new_buf, exist_buf,
927 aspath_hops,
928 (exist_hops + exist_confeds));
929 return 1;
930 }
931
932 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 933 *reason = bgp_path_selection_confed_as_path;
d62a17ae 934 if (debug)
935 zlog_debug(
936 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
937 pfx_buf, new_buf, exist_buf,
938 aspath_hops,
939 (exist_hops + exist_confeds));
940 return 0;
941 }
942 } else {
943 int newhops = aspath_count_hops(newattr->aspath);
944
945 if (newhops < exist_hops) {
fdf81fa0 946 *reason = bgp_path_selection_as_path;
d62a17ae 947 if (debug)
948 zlog_debug(
949 "%s: %s wins over %s due to aspath hopcount %d < %d",
950 pfx_buf, new_buf, exist_buf,
951 newhops, exist_hops);
952 return 1;
953 }
954
955 if (newhops > exist_hops) {
fdf81fa0 956 *reason = bgp_path_selection_as_path;
d62a17ae 957 if (debug)
958 zlog_debug(
959 "%s: %s loses to %s due to aspath hopcount %d > %d",
960 pfx_buf, new_buf, exist_buf,
961 newhops, exist_hops);
962 return 0;
963 }
964 }
965 }
9fbdd100 966
d62a17ae 967 /* 5. Origin check. */
968 if (newattr->origin < existattr->origin) {
fdf81fa0 969 *reason = bgp_path_selection_origin;
d62a17ae 970 if (debug)
971 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
972 pfx_buf, new_buf, exist_buf,
973 bgp_origin_long_str[newattr->origin],
974 bgp_origin_long_str[existattr->origin]);
975 return 1;
976 }
718e3744 977
d62a17ae 978 if (newattr->origin > existattr->origin) {
fdf81fa0 979 *reason = bgp_path_selection_origin;
d62a17ae 980 if (debug)
981 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
982 pfx_buf, new_buf, exist_buf,
983 bgp_origin_long_str[newattr->origin],
984 bgp_origin_long_str[existattr->origin]);
985 return 0;
986 }
718e3744 987
d62a17ae 988 /* 6. MED check. */
989 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
990 && aspath_count_hops(existattr->aspath) == 0);
991 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
992 && aspath_count_confeds(existattr->aspath) > 0
993 && aspath_count_hops(newattr->aspath) == 0
994 && aspath_count_hops(existattr->aspath) == 0);
995
892fedb6
DA
996 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
997 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 998 || aspath_cmp_left(newattr->aspath, existattr->aspath)
999 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1000 || internal_as_route) {
1001 new_med = bgp_med_value(new->attr, bgp);
1002 exist_med = bgp_med_value(exist->attr, bgp);
1003
1004 if (new_med < exist_med) {
fdf81fa0 1005 *reason = bgp_path_selection_med;
d62a17ae 1006 if (debug)
1007 zlog_debug(
1008 "%s: %s wins over %s due to MED %d < %d",
1009 pfx_buf, new_buf, exist_buf, new_med,
1010 exist_med);
1011 return 1;
1012 }
8ff56318 1013
d62a17ae 1014 if (new_med > exist_med) {
fdf81fa0 1015 *reason = bgp_path_selection_med;
d62a17ae 1016 if (debug)
1017 zlog_debug(
1018 "%s: %s loses to %s due to MED %d > %d",
1019 pfx_buf, new_buf, exist_buf, new_med,
1020 exist_med);
1021 return 0;
1022 }
1023 }
9fbdd100 1024
d62a17ae 1025 /* 7. Peer type check. */
1026 new_sort = new->peer->sort;
1027 exist_sort = exist->peer->sort;
1028
1029 if (new_sort == BGP_PEER_EBGP
1030 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1031 *reason = bgp_path_selection_peer;
d62a17ae 1032 if (debug)
1033 zlog_debug(
1034 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1035 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1036 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1037 return 1;
1038 peer_sort_ret = 1;
d62a17ae 1039 }
718e3744 1040
d62a17ae 1041 if (exist_sort == BGP_PEER_EBGP
1042 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1043 *reason = bgp_path_selection_peer;
d62a17ae 1044 if (debug)
1045 zlog_debug(
1046 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1047 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1048 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1049 return 0;
1050 peer_sort_ret = 0;
d62a17ae 1051 }
8ff56318 1052
d62a17ae 1053 /* 8. IGP metric check. */
1054 newm = existm = 0;
8ff56318 1055
d62a17ae 1056 if (new->extra)
1057 newm = new->extra->igpmetric;
1058 if (exist->extra)
1059 existm = exist->extra->igpmetric;
9fbdd100 1060
d62a17ae 1061 if (newm < existm) {
ee88563a 1062 if (debug && peer_sort_ret < 0)
d62a17ae 1063 zlog_debug(
d588b995 1064 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1065 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1066 igp_metric_ret = 1;
d62a17ae 1067 }
718e3744 1068
d62a17ae 1069 if (newm > existm) {
ee88563a 1070 if (debug && peer_sort_ret < 0)
d62a17ae 1071 zlog_debug(
d588b995 1072 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1073 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1074 igp_metric_ret = 0;
5e242b0d 1075 }
5e242b0d 1076
d62a17ae 1077 /* 9. Same IGP metric. Compare the cluster list length as
1078 representative of IGP hops metric. Rewrite the metric value
1079 pair (newm, existm) with the cluster list length. Prefer the
1080 path with smaller cluster list length. */
1081 if (newm == existm) {
aa53c036
DS
1082 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1083 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1084 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1085 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1086 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1087
1088 if (newm < existm) {
ee88563a 1089 if (debug && peer_sort_ret < 0)
d62a17ae 1090 zlog_debug(
d588b995 1091 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1092 pfx_buf, new_buf, exist_buf,
1093 newm, existm);
ee88563a 1094 igp_metric_ret = 1;
d62a17ae 1095 }
1096
1097 if (newm > existm) {
ee88563a 1098 if (debug && peer_sort_ret < 0)
d62a17ae 1099 zlog_debug(
d588b995 1100 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1101 pfx_buf, new_buf, exist_buf,
1102 newm, existm);
ee88563a 1103 igp_metric_ret = 0;
d62a17ae 1104 }
1105 }
1106 }
31a4638f 1107
d62a17ae 1108 /* 10. confed-external vs. confed-internal */
1109 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1110 if (new_sort == BGP_PEER_CONFED
1111 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1112 *reason = bgp_path_selection_confed;
d62a17ae 1113 if (debug)
1114 zlog_debug(
1115 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1116 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1117 if (!CHECK_FLAG(bgp->flags,
1118 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1119 return 1;
1120 peer_sort_ret = 1;
d62a17ae 1121 }
718e3744 1122
d62a17ae 1123 if (exist_sort == BGP_PEER_CONFED
1124 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1125 *reason = bgp_path_selection_confed;
d62a17ae 1126 if (debug)
1127 zlog_debug(
1128 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1129 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1130 if (!CHECK_FLAG(bgp->flags,
1131 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1132 return 0;
1133 peer_sort_ret = 0;
d62a17ae 1134 }
1135 }
718e3744 1136
d62a17ae 1137 /* 11. Maximum path check. */
1138 if (newm == existm) {
1139 /* If one path has a label but the other does not, do not treat
1140 * them as equals for multipath
1141 */
a4d82a8a 1142 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1143 != (exist->extra
b57ba6d2 1144 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1145 if (debug)
1146 zlog_debug(
1147 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1148 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1149 } else if (CHECK_FLAG(bgp->flags,
1150 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1151
1152 /*
1153 * For the two paths, all comparison steps till IGP
1154 * metric
1155 * have succeeded - including AS_PATH hop count. Since
1156 * 'bgp
1157 * bestpath as-path multipath-relax' knob is on, we
1158 * don't need
1159 * an exact match of AS_PATH. Thus, mark the paths are
1160 * equal.
1161 * That will trigger both these paths to get into the
1162 * multipath
1163 * array.
1164 */
1165 *paths_eq = 1;
1166
1167 if (debug)
1168 zlog_debug(
1169 "%s: %s and %s are equal via multipath-relax",
1170 pfx_buf, new_buf, exist_buf);
1171 } else if (new->peer->sort == BGP_PEER_IBGP) {
1172 if (aspath_cmp(new->attr->aspath,
1173 exist->attr->aspath)) {
1174 *paths_eq = 1;
1175
1176 if (debug)
1177 zlog_debug(
1178 "%s: %s and %s are equal via matching aspaths",
1179 pfx_buf, new_buf, exist_buf);
1180 }
1181 } else if (new->peer->as == exist->peer->as) {
1182 *paths_eq = 1;
1183
1184 if (debug)
1185 zlog_debug(
1186 "%s: %s and %s are equal via same remote-as",
1187 pfx_buf, new_buf, exist_buf);
1188 }
1189 } else {
1190 /*
1191 * TODO: If unequal cost ibgp multipath is enabled we can
1192 * mark the paths as equal here instead of returning
1193 */
ee88563a
JM
1194
1195 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1196 * if either step 7 or 10 (peer type checks) yielded a winner,
1197 * that result was returned immediately. Returning from step 10
1198 * ignored the return value computed in steps 8 and 9 (IGP
1199 * metric checks). In order to preserve that behavior, if
1200 * peer_sort_ret is set, return that rather than igp_metric_ret.
1201 */
1202 ret = peer_sort_ret;
1203 if (peer_sort_ret < 0) {
1204 ret = igp_metric_ret;
1205 if (debug) {
1206 if (ret == 1)
1207 zlog_debug(
1208 "%s: %s wins over %s after IGP metric comparison",
1209 pfx_buf, new_buf, exist_buf);
1210 else
1211 zlog_debug(
1212 "%s: %s loses to %s after IGP metric comparison",
1213 pfx_buf, new_buf, exist_buf);
1214 }
1215 *reason = bgp_path_selection_igp_metric;
d62a17ae 1216 }
1217 return ret;
1218 }
718e3744 1219
ee88563a
JM
1220 /*
1221 * At this point, the decision whether to set *paths_eq = 1 has been
1222 * completed. If we deferred returning because of bestpath peer-type
1223 * relax configuration, return now.
1224 */
1225 if (peer_sort_ret >= 0)
1226 return peer_sort_ret;
1227
d62a17ae 1228 /* 12. If both paths are external, prefer the path that was received
1229 first (the oldest one). This step minimizes route-flap, since a
1230 newer path won't displace an older one, even if it was the
1231 preferred route based on the additional decision criteria below. */
892fedb6 1232 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1233 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1234 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1235 *reason = bgp_path_selection_older;
d62a17ae 1236 if (debug)
1237 zlog_debug(
1238 "%s: %s wins over %s due to oldest external",
1239 pfx_buf, new_buf, exist_buf);
1240 return 1;
1241 }
9fbdd100 1242
1defdda8 1243 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1244 *reason = bgp_path_selection_older;
d62a17ae 1245 if (debug)
1246 zlog_debug(
1247 "%s: %s loses to %s due to oldest external",
1248 pfx_buf, new_buf, exist_buf);
1249 return 0;
1250 }
1251 }
718e3744 1252
ce5002c6 1253 /* 13. Router-ID comparison. */
d62a17ae 1254 /* If one of the paths is "stale", the corresponding peer router-id will
1255 * be 0 and would always win over the other path. If originator id is
ce5002c6 1256 * used for the comparison, it will decide which path is better.
d62a17ae 1257 */
1258 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1259 new_id.s_addr = newattr->originator_id.s_addr;
1260 else
1261 new_id.s_addr = new->peer->remote_id.s_addr;
1262 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1263 exist_id.s_addr = existattr->originator_id.s_addr;
1264 else
1265 exist_id.s_addr = exist->peer->remote_id.s_addr;
1266
1267 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1268 *reason = bgp_path_selection_router_id;
d62a17ae 1269 if (debug)
1270 zlog_debug(
1271 "%s: %s wins over %s due to Router-ID comparison",
1272 pfx_buf, new_buf, exist_buf);
1273 return 1;
1274 }
718e3744 1275
d62a17ae 1276 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1277 *reason = bgp_path_selection_router_id;
d62a17ae 1278 if (debug)
1279 zlog_debug(
1280 "%s: %s loses to %s due to Router-ID comparison",
1281 pfx_buf, new_buf, exist_buf);
1282 return 0;
1283 }
9fbdd100 1284
ce5002c6 1285 /* 14. Cluster length comparison. */
d62a17ae 1286 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1287 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1288
1289 if (new_cluster < exist_cluster) {
fdf81fa0 1290 *reason = bgp_path_selection_cluster_length;
d62a17ae 1291 if (debug)
1292 zlog_debug(
1293 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1294 pfx_buf, new_buf, exist_buf, new_cluster,
1295 exist_cluster);
1296 return 1;
1297 }
718e3744 1298
d62a17ae 1299 if (new_cluster > exist_cluster) {
fdf81fa0 1300 *reason = bgp_path_selection_cluster_length;
d62a17ae 1301 if (debug)
1302 zlog_debug(
1303 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1304 pfx_buf, new_buf, exist_buf, new_cluster,
1305 exist_cluster);
1306 return 0;
1307 }
9fbdd100 1308
ce5002c6 1309 /* 15. Neighbor address comparison. */
d62a17ae 1310 /* Do this only if neither path is "stale" as stale paths do not have
1311 * valid peer information (as the connection may or may not be up).
1312 */
1defdda8 1313 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1314 *reason = bgp_path_selection_stale;
d62a17ae 1315 if (debug)
1316 zlog_debug(
1317 "%s: %s wins over %s due to latter path being STALE",
1318 pfx_buf, new_buf, exist_buf);
1319 return 1;
1320 }
0de5153c 1321
1defdda8 1322 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1323 *reason = bgp_path_selection_stale;
d62a17ae 1324 if (debug)
1325 zlog_debug(
1326 "%s: %s loses to %s due to former path being STALE",
1327 pfx_buf, new_buf, exist_buf);
1328 return 0;
1329 }
718e3744 1330
d62a17ae 1331 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1332 if (new->peer->su_remote == NULL) {
1333 *reason = bgp_path_selection_local_configured;
d62a17ae 1334 return 0;
fdf81fa0
DS
1335 }
1336 if (exist->peer->su_remote == NULL) {
1337 *reason = bgp_path_selection_local_configured;
d62a17ae 1338 return 1;
fdf81fa0 1339 }
9fbdd100 1340
d62a17ae 1341 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1342
1343 if (ret == 1) {
fdf81fa0 1344 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1345 if (debug)
1346 zlog_debug(
1347 "%s: %s loses to %s due to Neighor IP comparison",
1348 pfx_buf, new_buf, exist_buf);
1349 return 0;
1350 }
1351
1352 if (ret == -1) {
fdf81fa0 1353 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1354 if (debug)
1355 zlog_debug(
1356 "%s: %s wins over %s due to Neighor IP comparison",
1357 pfx_buf, new_buf, exist_buf);
1358 return 1;
1359 }
9fbdd100 1360
fdf81fa0 1361 *reason = bgp_path_selection_default;
d62a17ae 1362 if (debug)
1363 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1364 pfx_buf, new_buf, exist_buf);
718e3744 1365
d62a17ae 1366 return 1;
718e3744 1367}
1368
d071f237
AK
1369
1370int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1371 struct bgp_path_info *exist, int *paths_eq)
1372{
1373 enum bgp_path_selection_reason reason;
1374 char pfx_buf[PREFIX2STR_BUFFER];
1375
1376 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1377 AFI_L2VPN, SAFI_EVPN, &reason);
1378}
1379
65efcfce
LB
1380/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1381 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1382 * multipath is enabled
65efcfce 1383 * This version is compatible with */
18ee8310
DS
1384int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1385 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1386 afi_t afi, safi_t safi,
1387 enum bgp_path_selection_reason *reason)
d62a17ae 1388{
1389 int paths_eq;
1390 int ret;
18ee8310 1391 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1392 afi, safi, reason);
d62a17ae 1393
1394 if (paths_eq)
1395 ret = 0;
1396 else {
1397 if (ret == 1)
1398 ret = -1;
1399 else
1400 ret = 1;
1401 }
1402 return ret;
65efcfce
LB
1403}
1404
5a1ae2c2
DS
1405static enum filter_type bgp_input_filter(struct peer *peer,
1406 const struct prefix *p,
d62a17ae 1407 struct attr *attr, afi_t afi,
1408 safi_t safi)
718e3744 1409{
d62a17ae 1410 struct bgp_filter *filter;
6401252f 1411 enum filter_type ret = FILTER_PERMIT;
718e3744 1412
d62a17ae 1413 filter = &peer->filter[afi][safi];
718e3744 1414
d62a17ae 1415#define FILTER_EXIST_WARN(F, f, filter) \
1416 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1417 zlog_debug("%s: Could not find configured input %s-list %s!", \
1418 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1419
1420 if (DISTRIBUTE_IN_NAME(filter)) {
1421 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1422
6401252f
QY
1423 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1424 == FILTER_DENY) {
1425 ret = FILTER_DENY;
1426 goto done;
1427 }
d62a17ae 1428 }
1429
1430 if (PREFIX_LIST_IN_NAME(filter)) {
1431 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1432
6401252f
QY
1433 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1434 == PREFIX_DENY) {
1435 ret = FILTER_DENY;
1436 goto done;
1437 }
d62a17ae 1438 }
1439
1440 if (FILTER_LIST_IN_NAME(filter)) {
1441 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1442
1443 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1444 == AS_FILTER_DENY) {
1445 ret = FILTER_DENY;
1446 goto done;
1447 }
d62a17ae 1448 }
1449
6401252f 1450done:
c7bb4f00 1451 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1452 char pfxprint[PREFIX2STR_BUFFER];
1453
1454 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1455 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1456 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1457 }
1458
1459 return ret;
650f76c2 1460#undef FILTER_EXIST_WARN
718e3744 1461}
1462
b8685f9b
DS
1463static enum filter_type bgp_output_filter(struct peer *peer,
1464 const struct prefix *p,
d62a17ae 1465 struct attr *attr, afi_t afi,
1466 safi_t safi)
718e3744 1467{
d62a17ae 1468 struct bgp_filter *filter;
6401252f 1469 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1470
1471 filter = &peer->filter[afi][safi];
1472
1473#define FILTER_EXIST_WARN(F, f, filter) \
1474 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1475 zlog_debug("%s: Could not find configured output %s-list %s!", \
1476 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1477
d62a17ae 1478 if (DISTRIBUTE_OUT_NAME(filter)) {
1479 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1480
6401252f
QY
1481 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1482 == FILTER_DENY) {
1483 ret = FILTER_DENY;
1484 goto done;
1485 }
d62a17ae 1486 }
1487
1488 if (PREFIX_LIST_OUT_NAME(filter)) {
1489 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1490
d62a17ae 1491 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1492 == PREFIX_DENY) {
1493 ret = FILTER_DENY;
1494 goto done;
1495 }
d62a17ae 1496 }
718e3744 1497
d62a17ae 1498 if (FILTER_LIST_OUT_NAME(filter)) {
1499 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1500
d62a17ae 1501 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1502 == AS_FILTER_DENY) {
1503 ret = FILTER_DENY;
1504 goto done;
1505 }
1506 }
1507
c7bb4f00 1508 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1509 char pfxprint[PREFIX2STR_BUFFER];
1510
1511 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1512 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1513 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1514 }
718e3744 1515
6401252f
QY
1516done:
1517 return ret;
650f76c2 1518#undef FILTER_EXIST_WARN
718e3744 1519}
1520
1521/* If community attribute includes no_export then return 1. */
3dc339cd 1522static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1523{
9a706b42 1524 if (bgp_attr_get_community(attr)) {
d62a17ae 1525 /* NO_ADVERTISE check. */
9a706b42
DA
1526 if (community_include(bgp_attr_get_community(attr),
1527 COMMUNITY_NO_ADVERTISE))
3dc339cd 1528 return true;
d62a17ae 1529
1530 /* NO_EXPORT check. */
9a706b42
DA
1531 if (peer->sort == BGP_PEER_EBGP &&
1532 community_include(bgp_attr_get_community(attr),
1533 COMMUNITY_NO_EXPORT))
3dc339cd 1534 return true;
d62a17ae 1535
1536 /* NO_EXPORT_SUBCONFED check. */
1537 if (peer->sort == BGP_PEER_EBGP
1538 || peer->sort == BGP_PEER_CONFED)
9a706b42 1539 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1540 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1541 return true;
d62a17ae 1542 }
3dc339cd 1543 return false;
718e3744 1544}
1545
1546/* Route reflection loop check. */
3dc339cd 1547static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1548{
d62a17ae 1549 struct in_addr cluster_id;
779fee93 1550 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1551
779fee93 1552 if (cluster) {
d62a17ae 1553 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1554 cluster_id = peer->bgp->cluster_id;
1555 else
1556 cluster_id = peer->bgp->router_id;
1557
779fee93 1558 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1559 return true;
d62a17ae 1560 }
3dc339cd 1561 return false;
718e3744 1562}
6b0655a2 1563
5a1ae2c2 1564static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1565 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1566 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1567 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1568{
d62a17ae 1569 struct bgp_filter *filter;
82b692c0
LK
1570 struct bgp_path_info rmap_path = { 0 };
1571 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1572 route_map_result_t ret;
1573 struct route_map *rmap = NULL;
718e3744 1574
d62a17ae 1575 filter = &peer->filter[afi][safi];
718e3744 1576
d62a17ae 1577 /* Apply default weight value. */
1578 if (peer->weight[afi][safi])
1579 attr->weight = peer->weight[afi][safi];
718e3744 1580
d62a17ae 1581 if (rmap_name) {
1582 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1583
d62a17ae 1584 if (rmap == NULL)
1585 return RMAP_DENY;
1586 } else {
1587 if (ROUTE_MAP_IN_NAME(filter)) {
1588 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1589
d62a17ae 1590 if (rmap == NULL)
1591 return RMAP_DENY;
1592 }
1593 }
0b16f239 1594
d62a17ae 1595 /* Route map apply. */
1596 if (rmap) {
6006b807 1597 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1598 /* Duplicate current value to new structure for modification. */
40381db7
DS
1599 rmap_path.peer = peer;
1600 rmap_path.attr = attr;
82b692c0 1601 rmap_path.extra = &extra;
9bcb3eef 1602 rmap_path.net = dest;
196c6b09 1603
82b692c0
LK
1604 extra.num_labels = num_labels;
1605 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1606 memcpy(extra.label, label,
1607 num_labels * sizeof(mpls_label_t));
718e3744 1608
d62a17ae 1609 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1610
d62a17ae 1611 /* Apply BGP route map to the attribute. */
1782514f 1612 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1613
d62a17ae 1614 peer->rmap_type = 0;
0b16f239 1615
1f2263be 1616 if (ret == RMAP_DENYMATCH)
d62a17ae 1617 return RMAP_DENY;
0b16f239 1618 }
d62a17ae 1619 return RMAP_PERMIT;
0b16f239
DS
1620}
1621
5f040085 1622static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1623 struct attr *attr, afi_t afi, safi_t safi,
1624 const char *rmap_name)
0b16f239 1625{
40381db7 1626 struct bgp_path_info rmap_path;
d62a17ae 1627 route_map_result_t ret;
1628 struct route_map *rmap = NULL;
d7c0a89a 1629 uint8_t rmap_type;
0b16f239 1630
b787157a
DS
1631 /*
1632 * So if we get to this point and have no rmap_name
1633 * we want to just show the output as it currently
1634 * exists.
1635 */
1636 if (!rmap_name)
1637 return RMAP_PERMIT;
0b16f239 1638
d62a17ae 1639 /* Apply default weight value. */
1640 if (peer->weight[afi][safi])
1641 attr->weight = peer->weight[afi][safi];
0b16f239 1642
b787157a 1643 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1644
b787157a
DS
1645 /*
1646 * If we have a route map name and we do not find
1647 * the routemap that means we have an implicit
1648 * deny.
1649 */
1650 if (rmap == NULL)
1651 return RMAP_DENY;
0b16f239 1652
6006b807 1653 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1654 /* Route map apply. */
544be979 1655 /* Duplicate current value to new structure for modification. */
40381db7
DS
1656 rmap_path.peer = peer;
1657 rmap_path.attr = attr;
0b16f239 1658
0f672529 1659 rmap_type = peer->rmap_type;
b787157a 1660 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1661
b787157a 1662 /* Apply BGP route map to the attribute. */
1782514f 1663 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1664
0f672529 1665 peer->rmap_type = rmap_type;
b787157a
DS
1666
1667 if (ret == RMAP_DENYMATCH)
1668 /*
1669 * caller has multiple error paths with bgp_attr_flush()
1670 */
1671 return RMAP_DENY;
ac41b2a2 1672
d62a17ae 1673 return RMAP_PERMIT;
718e3744 1674}
6b0655a2 1675
5000f21c 1676/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1677static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1678 struct peer *peer, struct attr *attr)
1679{
1680 if (peer->sort == BGP_PEER_EBGP
1681 && (peer_af_flag_check(peer, afi, safi,
1682 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1683 || peer_af_flag_check(peer, afi, safi,
1684 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1685 || peer_af_flag_check(peer, afi, safi,
1686 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1687 || peer_af_flag_check(peer, afi, safi,
1688 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1689 // Take action on the entire aspath
1690 if (peer_af_flag_check(peer, afi, safi,
1691 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1692 || peer_af_flag_check(peer, afi, safi,
1693 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1694 if (peer_af_flag_check(
1695 peer, afi, safi,
1696 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1697 attr->aspath = aspath_replace_private_asns(
bf26b80e 1698 attr->aspath, bgp->as, peer->as);
d62a17ae 1699
179d5a0e
TA
1700 /*
1701 * Even if the aspath consists of just private ASNs we
1702 * need to walk the AS-Path to maintain all instances
1703 * of the peer's ASN to break possible loops.
1704 */
d62a17ae 1705 else
1706 attr->aspath = aspath_remove_private_asns(
bf26b80e 1707 attr->aspath, peer->as);
d62a17ae 1708 }
1709
1710 // 'all' was not specified so the entire aspath must be private
1711 // ASNs
1712 // for us to do anything
1713 else if (aspath_private_as_check(attr->aspath)) {
1714 if (peer_af_flag_check(
1715 peer, afi, safi,
1716 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1717 attr->aspath = aspath_replace_private_asns(
bf26b80e 1718 attr->aspath, bgp->as, peer->as);
d62a17ae 1719 else
179d5a0e
TA
1720 /*
1721 * Walk the aspath to retain any instances of
1722 * the peer_asn
1723 */
1724 attr->aspath = aspath_remove_private_asns(
1725 attr->aspath, peer->as);
d62a17ae 1726 }
1727 }
5000f21c
DS
1728}
1729
c7122e14 1730/* If this is an EBGP peer with as-override */
d62a17ae 1731static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1732 struct peer *peer, struct attr *attr)
1733{
1734 if (peer->sort == BGP_PEER_EBGP
1735 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1736 if (aspath_single_asn_check(attr->aspath, peer->as))
1737 attr->aspath = aspath_replace_specific_asn(
1738 attr->aspath, peer->as, bgp->as);
1739 }
1740}
1741
1479ed2f
DA
1742void bgp_attr_add_llgr_community(struct attr *attr)
1743{
1744 struct community *old;
1745 struct community *new;
1746 struct community *merge;
1747 struct community *llgr;
1748
9a706b42 1749 old = bgp_attr_get_community(attr);
1479ed2f
DA
1750 llgr = community_str2com("llgr-stale");
1751
1752 assert(llgr);
1753
1754 if (old) {
1755 merge = community_merge(community_dup(old), llgr);
1756
1757 if (old->refcnt == 0)
1758 community_free(&old);
1759
1760 new = community_uniq_sort(merge);
1761 community_free(&merge);
1762 } else {
1763 new = community_dup(llgr);
1764 }
1765
1766 community_free(&llgr);
1767
9a706b42 1768 bgp_attr_set_community(attr, new);
1479ed2f
DA
1769}
1770
7f323236
DW
1771void bgp_attr_add_gshut_community(struct attr *attr)
1772{
1773 struct community *old;
1774 struct community *new;
1775 struct community *merge;
1776 struct community *gshut;
1777
9a706b42 1778 old = bgp_attr_get_community(attr);
7f323236
DW
1779 gshut = community_str2com("graceful-shutdown");
1780
990f4f91 1781 assert(gshut);
1782
7f323236
DW
1783 if (old) {
1784 merge = community_merge(community_dup(old), gshut);
1785
a4d82a8a 1786 if (old->refcnt == 0)
3c1f53de 1787 community_free(&old);
7f323236
DW
1788
1789 new = community_uniq_sort(merge);
3c1f53de 1790 community_free(&merge);
7f323236
DW
1791 } else {
1792 new = community_dup(gshut);
1793 }
1794
3c1f53de 1795 community_free(&gshut);
9a706b42 1796 bgp_attr_set_community(attr, new);
7f323236
DW
1797
1798 /* When we add the graceful-shutdown community we must also
1799 * lower the local-preference */
1800 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1801 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1802}
1803
1804
e73c112e
MK
1805/* Notify BGP Conditional advertisement scanner process. */
1806void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1807{
e73c112e 1808 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1809 afi_t afi = SUBGRP_AFI(subgrp);
1810 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1811 struct bgp_filter *filter = &peer->filter[afi][safi];
1812
1813 if (!ADVERTISE_MAP_NAME(filter))
1814 return;
1815
52979c3b
DS
1816 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1817 return;
e73c112e 1818
52979c3b 1819 peer->advmap_table_change = true;
e73c112e
MK
1820}
1821
1822
f2ee6d5c 1823void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1824{
960035b2 1825 if (family == AF_INET) {
975a328e
DA
1826 attr->nexthop.s_addr = INADDR_ANY;
1827 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1828 }
d62a17ae 1829 if (family == AF_INET6)
1830 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1831 if (family == AF_EVPN)
1832 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1833}
1834
9bcb3eef 1835bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1836 struct update_subgroup *subgrp,
7f7940e6 1837 const struct prefix *p, struct attr *attr,
51c3a7de 1838 struct attr *post_attr)
d62a17ae 1839{
1840 struct bgp_filter *filter;
1841 struct peer *from;
1842 struct peer *peer;
1843 struct peer *onlypeer;
1844 struct bgp *bgp;
40381db7 1845 struct attr *piattr;
b68885f9 1846 route_map_result_t ret;
d62a17ae 1847 int transparent;
1848 int reflect;
1849 afi_t afi;
1850 safi_t safi;
1851 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1852 bool nh_reset = false;
1853 uint64_t cum_bw;
d62a17ae 1854
1855 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1856 return false;
d62a17ae 1857
1858 afi = SUBGRP_AFI(subgrp);
1859 safi = SUBGRP_SAFI(subgrp);
1860 peer = SUBGRP_PEER(subgrp);
1861 onlypeer = NULL;
1862 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1863 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1864
40381db7 1865 from = pi->peer;
d62a17ae 1866 filter = &peer->filter[afi][safi];
1867 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1868 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1869 : pi->attr;
3f9c7369 1870
d0bf49ec
LS
1871 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1872 peer->pmax_out[afi][safi] != 0 &&
1873 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1874 if (BGP_DEBUG(update, UPDATE_OUT) ||
1875 BGP_DEBUG(update, UPDATE_PREFIX)) {
1876 zlog_debug("%s reached maximum prefix to be send (%u)",
1877 peer->host, peer->pmax_out[afi][safi]);
1878 }
1879 return false;
1880 }
1881
49e5a4a0 1882#ifdef ENABLE_BGP_VNC
d62a17ae 1883 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1884 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1885 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1886
1887 /*
1888 * direct and direct_ext type routes originate internally even
1889 * though they can have peer pointers that reference other
1890 * systems
1891 */
8228a9a7
DS
1892 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1893 __func__, p);
d62a17ae 1894 samepeer_safe = 1;
1895 }
65efcfce
LB
1896#endif
1897
ddb5b488
PZ
1898 if (((afi == AFI_IP) || (afi == AFI_IP6))
1899 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1900 && (pi->type == ZEBRA_ROUTE_BGP)
1901 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1902
1903 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1904
1905 samepeer_safe = 1;
1906 }
1907
d62a17ae 1908 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1909 * pi is valid */
1910 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1911 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1912 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1913 return false;
d62a17ae 1914 }
adbac85e 1915
d62a17ae 1916 /* If this is not the bestpath then check to see if there is an enabled
1917 * addpath
1918 * feature that requires us to advertise it */
40381db7 1919 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1920 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1921 return false;
d62a17ae 1922 }
1923 }
06370dac 1924
d62a17ae 1925 /* Aggregate-address suppress check. */
4056a5f6
RZ
1926 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1927 return false;
3f9c7369 1928
13b7e7f0
DS
1929 /*
1930 * If we are doing VRF 2 VRF leaking via the import
1931 * statement, we want to prevent the route going
1932 * off box as that the RT and RD created are localy
1933 * significant and globaly useless.
1934 */
40381db7
DS
1935 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1936 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1937 return false;
13b7e7f0 1938
d62a17ae 1939 /* If it's labeled safi, make sure the route has a valid label. */
1940 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1941 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1942 if (!bgp_is_valid_label(&label)) {
1943 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1944 zlog_debug("u%" PRIu64 ":s%" PRIu64
1945 " %pFX is filtered - no label (%p)",
d62a17ae 1946 subgrp->update_group->id, subgrp->id,
8228a9a7 1947 p, &label);
3dc339cd 1948 return false;
d62a17ae 1949 }
1950 }
cd1964ff 1951
d62a17ae 1952 /* Do not send back route to sender. */
1953 if (onlypeer && from == onlypeer) {
3dc339cd 1954 return false;
d62a17ae 1955 }
3f9c7369 1956
d62a17ae 1957 /* Do not send the default route in the BGP table if the neighbor is
1958 * configured for default-originate */
1959 if (CHECK_FLAG(peer->af_flags[afi][safi],
1960 PEER_FLAG_DEFAULT_ORIGINATE)) {
1961 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1962 return false;
d62a17ae 1963 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1964 return false;
d62a17ae 1965 }
4125bb67 1966
d62a17ae 1967 /* Transparency check. */
1968 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1969 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1970 transparent = 1;
1971 else
1972 transparent = 0;
1973
1974 /* If community is not disabled check the no-export and local. */
40381db7 1975 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1976 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1977 zlog_debug("%s: community filter check fail for %pFX",
1978 __func__, p);
3dc339cd 1979 return false;
d62a17ae 1980 }
3f9c7369 1981
d62a17ae 1982 /* If the attribute has originator-id and it is same as remote
1983 peer's id. */
40381db7
DS
1984 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1985 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1986 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1987 zlog_debug(
8228a9a7
DS
1988 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1989 onlypeer->host, p);
3dc339cd 1990 return false;
d62a17ae 1991 }
3f9c7369 1992
d62a17ae 1993 /* ORF prefix-list filter check */
1994 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1995 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1996 || CHECK_FLAG(peer->af_cap[afi][safi],
1997 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1998 if (peer->orf_plist[afi][safi]) {
1999 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2000 == PREFIX_DENY) {
2001 if (bgp_debug_update(NULL, p,
2002 subgrp->update_group, 0))
2003 zlog_debug(
8228a9a7
DS
2004 "%s [Update:SEND] %pFX is filtered via ORF",
2005 peer->host, p);
3dc339cd 2006 return false;
d62a17ae 2007 }
2008 }
2009
2010 /* Output filter check. */
40381db7 2011 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2012 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2013 zlog_debug("%s [Update:SEND] %pFX is filtered",
2014 peer->host, p);
3dc339cd 2015 return false;
d62a17ae 2016 }
3f9c7369 2017
d62a17ae 2018 /* AS path loop check. */
2b31007c
RZ
2019 if (onlypeer && onlypeer->as_path_loop_detection
2020 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2021 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2022 zlog_debug(
3efd0893 2023 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 2024 onlypeer->host, onlypeer->as);
3dc339cd 2025 return false;
d62a17ae 2026 }
3f9c7369 2027
d62a17ae 2028 /* If we're a CONFED we need to loop check the CONFED ID too */
2029 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2030 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2031 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2032 zlog_debug(
3efd0893 2033 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 2034 peer->host, bgp->confed_id);
3dc339cd 2035 return false;
d62a17ae 2036 }
3f9c7369 2037 }
3f9c7369 2038
d62a17ae 2039 /* Route-Reflect check. */
2040 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2041 reflect = 1;
2042 else
2043 reflect = 0;
2044
2045 /* IBGP reflection check. */
2046 if (reflect && !samepeer_safe) {
2047 /* A route from a Client peer. */
2048 if (CHECK_FLAG(from->af_flags[afi][safi],
2049 PEER_FLAG_REFLECTOR_CLIENT)) {
2050 /* Reflect to all the Non-Client peers and also to the
2051 Client peers other than the originator. Originator
2052 check
2053 is already done. So there is noting to do. */
2054 /* no bgp client-to-client reflection check. */
892fedb6
DA
2055 if (CHECK_FLAG(bgp->flags,
2056 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2057 if (CHECK_FLAG(peer->af_flags[afi][safi],
2058 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2059 return false;
d62a17ae 2060 } else {
2061 /* A route from a Non-client peer. Reflect to all other
2062 clients. */
2063 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2064 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2065 return false;
d62a17ae 2066 }
2067 }
3f9c7369 2068
51c3a7de
DA
2069 /* For modify attribute, copy it to temporary structure.
2070 * post_attr comes from BGP conditional advertisements, where
2071 * attributes are already processed by advertise-map route-map,
2072 * and this needs to be saved instead of overwriting from the
2073 * path attributes.
2074 */
2075 if (post_attr)
2076 *attr = *post_attr;
2077 else
2078 *attr = *piattr;
d62a17ae 2079
2080 /* If local-preference is not set. */
2081 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2082 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2083 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2084 attr->local_pref = bgp->default_local_pref;
3f9c7369 2085 }
3f9c7369 2086
d62a17ae 2087 /* If originator-id is not set and the route is to be reflected,
2088 set the originator id */
2089 if (reflect
2090 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2091 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2092 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2093 }
3f9c7369 2094
d62a17ae 2095 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2096 */
2097 if (peer->sort == BGP_PEER_EBGP
2098 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2099 if (from != bgp->peer_self && !transparent
2100 && !CHECK_FLAG(peer->af_flags[afi][safi],
2101 PEER_FLAG_MED_UNCHANGED))
2102 attr->flag &=
2103 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2104 }
3f9c7369 2105
d62a17ae 2106 /* Since the nexthop attribute can vary per peer, it is not explicitly
2107 * set
2108 * in announce check, only certain flags and length (or number of
2109 * nexthops
2110 * -- for IPv6/MP_REACH) are set here in order to guide the update
2111 * formation
2112 * code in setting the nexthop(s) on a per peer basis in
2113 * reformat_peer().
2114 * Typically, the source nexthop in the attribute is preserved but in
2115 * the
2116 * scenarios where we know it will always be overwritten, we reset the
2117 * nexthop to "0" in an attempt to achieve better Update packing. An
2118 * example of this is when a prefix from each of 2 IBGP peers needs to
2119 * be
2120 * announced to an EBGP peer (and they have the same attributes barring
2121 * their nexthop).
2122 */
2123 if (reflect)
2124 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2125
2126#define NEXTHOP_IS_V6 \
2127 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2128 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2129 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2130 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2131
2132 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2133 * if
2134 * the peer (group) is configured to receive link-local nexthop
2135 * unchanged
c728d027
DA
2136 * and it is available in the prefix OR we're not reflecting the route,
2137 * link-local nexthop address is valid and
d62a17ae 2138 * the peer (group) to whom we're going to announce is on a shared
2139 * network
2140 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2141 * By checking if nexthop LL address is valid we are sure that
2142 * we do not announce LL address as `::`.
d62a17ae 2143 */
2144 if (NEXTHOP_IS_V6) {
2145 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2146 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2147 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2148 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2149 || (!reflect && !transparent
c728d027
DA
2150 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2151 && peer->shared_network
d62a17ae 2152 && (from == bgp->peer_self
2153 || peer->sort == BGP_PEER_EBGP))) {
2154 attr->mp_nexthop_len =
2155 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2156 }
3f9c7369 2157
d62a17ae 2158 /* Clear off link-local nexthop in source, whenever it is not
2159 * needed to
2160 * ensure more prefixes share the same attribute for
2161 * announcement.
2162 */
2163 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2164 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2165 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2166 }
3f9c7369 2167
d62a17ae 2168 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2169 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2170
2171 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2172 if (!post_attr &&
2173 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2174 struct bgp_path_info rmap_path = {0};
2175 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2176 struct attr dummy_attr = {0};
d62a17ae 2177
e34291b8 2178 /* Fill temp path_info */
9bcb3eef
DS
2179 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2180 pi, peer, attr);
16f7ce2b 2181
d62a17ae 2182 /* don't confuse inbound and outbound setting */
2183 RESET_FLAG(attr->rmap_change_flags);
2184
2185 /*
2186 * The route reflector is not allowed to modify the attributes
2187 * of the reflected IBGP routes unless explicitly allowed.
2188 */
2189 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2190 && !CHECK_FLAG(bgp->flags,
2191 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2192 dummy_attr = *attr;
40381db7 2193 rmap_path.attr = &dummy_attr;
d62a17ae 2194 }
3f9c7369 2195
d62a17ae 2196 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2197
4056a5f6 2198 if (bgp_path_suppressed(pi))
d62a17ae 2199 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2200 &rmap_path);
d62a17ae 2201 else
2202 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2203 &rmap_path);
d62a17ae 2204
7e7639f5 2205 bgp_attr_flush(&dummy_attr);
d62a17ae 2206 peer->rmap_type = 0;
2207
2208 if (ret == RMAP_DENYMATCH) {
778048bf 2209 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2210 zlog_debug(
02494580
DA
2211 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2212 peer->host, p,
2213 ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2214 bgp_attr_flush(rmap_path.attr);
3dc339cd 2215 return false;
d62a17ae 2216 }
3f9c7369 2217 }
3f9c7369 2218
9dac9fc8
DA
2219 /* RFC 8212 to prevent route leaks.
2220 * This specification intends to improve this situation by requiring the
2221 * explicit configuration of both BGP Import and Export Policies for any
2222 * External BGP (EBGP) session such as customers, peers, or
2223 * confederation boundaries for all enabled address families. Through
2224 * codification of the aforementioned requirement, operators will
2225 * benefit from consistent behavior across different BGP
2226 * implementations.
2227 */
1d3fdccf 2228 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2229 if (!bgp_outbound_policy_exists(peer, filter)) {
2230 if (monotime_since(&bgp->ebgprequirespolicywarning,
2231 NULL) > FIFTEENMINUTE2USEC ||
2232 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2233 zlog_warn(
2234 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2235 monotime(&bgp->ebgprequirespolicywarning);
2236 }
3dc339cd 2237 return false;
b17826b7 2238 }
9dac9fc8 2239
fb29348a
DA
2240 /* draft-ietf-idr-deprecate-as-set-confed-set
2241 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2242 * Eventually, This document (if approved) updates RFC 4271
2243 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2244 * and obsoletes RFC 6472.
2245 */
7f972cd8 2246 if (peer->bgp->reject_as_sets)
fb29348a 2247 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2248 return false;
fb29348a 2249
33d022bc
DA
2250 /* Codification of AS 0 Processing */
2251 if (aspath_check_as_zero(attr->aspath))
e2369003 2252 return false;
33d022bc 2253
637e5ba4 2254 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2255 if (peer->sort == BGP_PEER_IBGP
2256 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2257 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2258 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2259 } else {
2260 bgp_attr_add_gshut_community(attr);
2261 }
2262 }
2263
1479ed2f
DA
2264 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2265 * Capability" to a neighbor MUST perform the following upon receiving
2266 * a route from that neighbor with the "LLGR_STALE" community, or upon
2267 * attaching the "LLGR_STALE" community itself per Section 4.2:
2268 *
2269 * The route SHOULD NOT be advertised to any neighbor from which the
2270 * Long-lived Graceful Restart Capability has not been received.
2271 */
9a706b42
DA
2272 if (bgp_attr_get_community(attr) &&
2273 community_include(bgp_attr_get_community(attr),
2274 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2275 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2276 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2277 return false;
2278
d62a17ae 2279 /* After route-map has been applied, we check to see if the nexthop to
2280 * be carried in the attribute (that is used for the announcement) can
2281 * be cleared off or not. We do this in all cases where we would be
2282 * setting the nexthop to "ourselves". For IPv6, we only need to
2283 * consider
2284 * the global nexthop here; the link-local nexthop would have been
2285 * cleared
2286 * already, and if not, it is required by the update formation code.
2287 * Also see earlier comments in this function.
2288 */
2289 /*
2290 * If route-map has performed some operation on the nexthop or the peer
2291 * configuration says to pass it unchanged, we cannot reset the nexthop
2292 * here, so only attempt to do it if these aren't true. Note that the
2293 * route-map handler itself might have cleared the nexthop, if for
2294 * example,
2295 * it is configured as 'peer-address'.
2296 */
2297 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2298 piattr->rmap_change_flags)
d62a17ae 2299 && !transparent
2300 && !CHECK_FLAG(peer->af_flags[afi][safi],
2301 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2302 /* We can reset the nexthop, if setting (or forcing) it to
2303 * 'self' */
2304 if (CHECK_FLAG(peer->af_flags[afi][safi],
2305 PEER_FLAG_NEXTHOP_SELF)
2306 || CHECK_FLAG(peer->af_flags[afi][safi],
2307 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2308 if (!reflect
2309 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2310 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2311 subgroup_announce_reset_nhop(
2312 (peer_cap_enhe(peer, afi, safi)
2313 ? AF_INET6
2314 : p->family),
2315 attr);
7b651a32 2316 nh_reset = true;
2317 }
d62a17ae 2318 } else if (peer->sort == BGP_PEER_EBGP) {
2319 /* Can also reset the nexthop if announcing to EBGP, but
2320 * only if
2321 * no peer in the subgroup is on a shared subnet.
2322 * Note: 3rd party nexthop currently implemented for
2323 * IPv4 only.
2324 */
737af885
BS
2325 if ((p->family == AF_INET) &&
2326 (!bgp_subgrp_multiaccess_check_v4(
2327 piattr->nexthop,
7b651a32 2328 subgrp, from))) {
d62a17ae 2329 subgroup_announce_reset_nhop(
2330 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2331 ? AF_INET6
2332 : p->family),
737af885 2333 attr);
7b651a32 2334 nh_reset = true;
2335 }
737af885
BS
2336
2337 if ((p->family == AF_INET6) &&
2338 (!bgp_subgrp_multiaccess_check_v6(
2339 piattr->mp_nexthop_global,
7b651a32 2340 subgrp, from))) {
737af885
BS
2341 subgroup_announce_reset_nhop(
2342 (peer_cap_enhe(peer, afi, safi)
2343 ? AF_INET6
2344 : p->family),
2345 attr);
7b651a32 2346 nh_reset = true;
2347 }
737af885
BS
2348
2349
2350
40381db7 2351 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2352 /*
2353 * This flag is used for leaked vpn-vrf routes
2354 */
2355 int family = p->family;
2356
2357 if (peer_cap_enhe(peer, afi, safi))
2358 family = AF_INET6;
2359
2360 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2361 zlog_debug(
1defdda8 2362 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2363 __func__, family2str(family));
2364 subgroup_announce_reset_nhop(family, attr);
7b651a32 2365 nh_reset = true;
d62a17ae 2366 }
63696f1d 2367 }
960035b2 2368
63696f1d 2369 /* If IPv6/MP and nexthop does not have any override and happens
2370 * to
2371 * be a link-local address, reset it so that we don't pass along
2372 * the
2373 * source's link-local IPv6 address to recipients who may not be
2374 * on
2375 * the same interface.
2376 */
2377 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2378 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2379 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2380 nh_reset = true;
2381 }
d62a17ae 2382 }
3f9c7369 2383
7b651a32 2384 /*
2385 * When the next hop is set to ourselves, if all multipaths have
2386 * link-bandwidth announce the cumulative bandwidth as that makes
2387 * the most sense. However, don't modify if the link-bandwidth has
2388 * been explicitly set by user policy.
2389 */
2390 if (nh_reset &&
f7e1c681 2391 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2392 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2393 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2394 bgp_attr_set_ecommunity(
2395 attr,
2396 ecommunity_replace_linkbw(
2397 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2398 CHECK_FLAG(
2399 peer->flags,
2400 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2401
3dc339cd 2402 return true;
3f9c7369
DS
2403}
2404
cc9f21da 2405static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2406{
2407 struct afi_safi_info *info;
2408 afi_t afi;
2409 safi_t safi;
2410 struct bgp *bgp;
2411
2412 info = THREAD_ARG(thread);
2413 afi = info->afi;
2414 safi = info->safi;
2415 bgp = info->bgp;
2416
2417 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2418 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2419 safi);
f009ff26 2420
2421 bgp->gr_info[afi][safi].t_route_select = NULL;
2422
2423 XFREE(MTYPE_TMP, info);
2424
2425 /* Best path selection */
cc9f21da 2426 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2427}
2428
9bcb3eef 2429void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2430 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2431 struct bgp_path_info_pair *result, afi_t afi,
2432 safi_t safi)
2433{
2434 struct bgp_path_info *new_select;
2435 struct bgp_path_info *old_select;
40381db7
DS
2436 struct bgp_path_info *pi;
2437 struct bgp_path_info *pi1;
2438 struct bgp_path_info *pi2;
2439 struct bgp_path_info *nextpi = NULL;
d62a17ae 2440 int paths_eq, do_mpath, debug;
2441 struct list mp_list;
2442 char pfx_buf[PREFIX2STR_BUFFER];
2443 char path_buf[PATH_ADDPATH_STR_BUFFER];
2444
2445 bgp_mp_list_init(&mp_list);
2446 do_mpath =
2447 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2448
9bcb3eef 2449 debug = bgp_debug_bestpath(dest);
d62a17ae 2450
2451 if (debug)
9bcb3eef 2452 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2453
9bcb3eef 2454 dest->reason = bgp_path_selection_none;
d62a17ae 2455 /* bgp deterministic-med */
2456 new_select = NULL;
892fedb6 2457 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2458
1defdda8 2459 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2460 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2461 pi1 = pi1->next)
9bcb3eef 2462 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2463 BGP_PATH_DMED_SELECTED);
d62a17ae 2464
9bcb3eef 2465 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2466 pi1 = pi1->next) {
40381db7 2467 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2468 continue;
40381db7 2469 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2470 continue;
ea8b2282 2471 if (pi1->peer != bgp->peer_self)
feb17238 2472 if (!peer_established(pi1->peer))
d62a17ae 2473 continue;
2474
40381db7
DS
2475 new_select = pi1;
2476 if (pi1->next) {
2477 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2478 if (CHECK_FLAG(pi2->flags,
1defdda8 2479 BGP_PATH_DMED_CHECK))
d62a17ae 2480 continue;
40381db7 2481 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2482 continue;
ea8b2282 2483 if (pi2->peer != bgp->peer_self
d62a17ae 2484 && !CHECK_FLAG(
ea8b2282
DS
2485 pi2->peer->sflags,
2486 PEER_STATUS_NSF_WAIT))
40381db7 2487 if (pi2->peer->status
d62a17ae 2488 != Established)
2489 continue;
2490
121e245d
DS
2491 if (!aspath_cmp_left(pi1->attr->aspath,
2492 pi2->attr->aspath)
2493 && !aspath_cmp_left_confed(
40381db7 2494 pi1->attr->aspath,
121e245d
DS
2495 pi2->attr->aspath))
2496 continue;
d62a17ae 2497
121e245d
DS
2498 if (bgp_path_info_cmp(
2499 bgp, pi2, new_select,
2500 &paths_eq, mpath_cfg, debug,
fdf81fa0 2501 pfx_buf, afi, safi,
9bcb3eef 2502 &dest->reason)) {
121e245d 2503 bgp_path_info_unset_flag(
9bcb3eef 2504 dest, new_select,
121e245d
DS
2505 BGP_PATH_DMED_SELECTED);
2506 new_select = pi2;
d62a17ae 2507 }
121e245d
DS
2508
2509 bgp_path_info_set_flag(
9bcb3eef 2510 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2511 }
2512 }
9bcb3eef 2513 bgp_path_info_set_flag(dest, new_select,
18ee8310 2514 BGP_PATH_DMED_CHECK);
9bcb3eef 2515 bgp_path_info_set_flag(dest, new_select,
18ee8310 2516 BGP_PATH_DMED_SELECTED);
d62a17ae 2517
2518 if (debug) {
18ee8310 2519 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2520 new_select, path_buf, sizeof(path_buf));
8228a9a7 2521 zlog_debug(
4378495a
DS
2522 "%pBD(%s): %s is the bestpath from AS %u",
2523 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2524 aspath_get_first_as(
2525 new_select->attr->aspath));
d62a17ae 2526 }
2527 }
2528 }
96450faf 2529
d62a17ae 2530 /* Check old selected route and new selected route. */
2531 old_select = NULL;
2532 new_select = NULL;
9bcb3eef 2533 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2534 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2535 enum bgp_path_selection_reason reason;
2536
40381db7
DS
2537 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2538 old_select = pi;
d62a17ae 2539
40381db7 2540 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2541 /* reap REMOVED routes, if needs be
2542 * selected route must stay for a while longer though
2543 */
40381db7
DS
2544 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2545 && (pi != old_select))
9bcb3eef 2546 bgp_path_info_reap(dest, pi);
d62a17ae 2547
ddb5b488 2548 if (debug)
40381db7
DS
2549 zlog_debug("%s: pi %p in holddown", __func__,
2550 pi);
ddb5b488 2551
d62a17ae 2552 continue;
2553 }
96450faf 2554
40381db7
DS
2555 if (pi->peer && pi->peer != bgp->peer_self
2556 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2557 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2558
2559 if (debug)
2560 zlog_debug(
40381db7
DS
2561 "%s: pi %p non self peer %s not estab state",
2562 __func__, pi, pi->peer->host);
ddb5b488 2563
d62a17ae 2564 continue;
ddb5b488 2565 }
9fbdd100 2566
892fedb6 2567 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2568 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2569 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2570 if (debug)
40381db7 2571 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2572 continue;
2573 }
9fbdd100 2574
9bcb3eef 2575 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2576
9bcb3eef 2577 reason = dest->reason;
40381db7 2578 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2579 debug, pfx_buf, afi, safi,
2580 &dest->reason)) {
19ea4cec
DS
2581 if (new_select == NULL &&
2582 reason != bgp_path_selection_none)
9bcb3eef 2583 dest->reason = reason;
40381db7 2584 new_select = pi;
d62a17ae 2585 }
2586 }
718e3744 2587
d62a17ae 2588 /* Now that we know which path is the bestpath see if any of the other
2589 * paths
2590 * qualify as multipaths
2591 */
2592 if (debug) {
2593 if (new_select)
7533cad7
QY
2594 bgp_path_info_path_with_addpath_rx_str(
2595 new_select, path_buf, sizeof(path_buf));
d62a17ae 2596 else
772270f3 2597 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2598 zlog_debug(
4378495a
DS
2599 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2600 dest, bgp->name_pretty, path_buf,
d62a17ae 2601 old_select ? old_select->peer->host : "NONE");
96450faf 2602 }
9fbdd100 2603
d62a17ae 2604 if (do_mpath && new_select) {
9bcb3eef 2605 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2606 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2607
2608 if (debug)
18ee8310 2609 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2610 pi, path_buf, sizeof(path_buf));
d62a17ae 2611
40381db7 2612 if (pi == new_select) {
d62a17ae 2613 if (debug)
2614 zlog_debug(
4378495a
DS
2615 "%pBD(%s): %s is the bestpath, add to the multipath list",
2616 dest, bgp->name_pretty,
2617 path_buf);
40381db7 2618 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2619 continue;
2620 }
2621
40381db7 2622 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2623 continue;
2624
40381db7
DS
2625 if (pi->peer && pi->peer != bgp->peer_self
2626 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2627 PEER_STATUS_NSF_WAIT))
feb17238 2628 if (!peer_established(pi->peer))
d62a17ae 2629 continue;
2630
40381db7 2631 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2632 if (debug)
2633 zlog_debug(
8228a9a7
DS
2634 "%pBD: %s has the same nexthop as the bestpath, skip it",
2635 dest, path_buf);
d62a17ae 2636 continue;
2637 }
2638
40381db7 2639 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2640 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2641 &dest->reason);
d62a17ae 2642
2643 if (paths_eq) {
2644 if (debug)
2645 zlog_debug(
8228a9a7
DS
2646 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2647 dest, path_buf);
40381db7 2648 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2649 }
2650 }
2651 }
fee0f4c6 2652
4378495a 2653 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2654 mpath_cfg);
2655 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2656 bgp_mp_list_clear(&mp_list);
96450faf 2657
9bcb3eef 2658 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2659
d62a17ae 2660 result->old = old_select;
2661 result->new = new_select;
96450faf 2662
d62a17ae 2663 return;
fee0f4c6 2664}
2665
3f9c7369
DS
2666/*
2667 * A new route/change in bestpath of an existing route. Evaluate the path
2668 * for advertisement to the subgroup.
2669 */
3dc339cd
DA
2670void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2671 struct bgp_path_info *selected,
9bcb3eef 2672 struct bgp_dest *dest,
3dc339cd 2673 uint32_t addpath_tx_id)
d62a17ae 2674{
b54892e0 2675 const struct prefix *p;
d62a17ae 2676 struct peer *onlypeer;
2677 struct attr attr;
2678 afi_t afi;
2679 safi_t safi;
a77e2f4b
S
2680 struct bgp *bgp;
2681 bool advertise;
adbac85e 2682
9bcb3eef 2683 p = bgp_dest_get_prefix(dest);
d62a17ae 2684 afi = SUBGRP_AFI(subgrp);
2685 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2686 bgp = SUBGRP_INST(subgrp);
d62a17ae 2687 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2688 : NULL);
2689
2dbe669b
DA
2690 if (BGP_DEBUG(update, UPDATE_OUT))
2691 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2692
d62a17ae 2693 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2694 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2695 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2696 return;
d62a17ae 2697
6006b807 2698 memset(&attr, 0, sizeof(attr));
d62a17ae 2699 /* It's initialized in bgp_announce_check() */
2700
a77e2f4b
S
2701 /* Announcement to the subgroup. If the route is filtered withdraw it.
2702 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2703 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2704 * route
d62a17ae 2705 */
a77e2f4b
S
2706 advertise = bgp_check_advertise(bgp, dest);
2707
d62a17ae 2708 if (selected) {
7f7940e6 2709 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2710 NULL)) {
a77e2f4b
S
2711 /* Route is selected, if the route is already installed
2712 * in FIB, then it is advertised
2713 */
be785e35
DS
2714 if (advertise) {
2715 if (!bgp_check_withdrawal(bgp, dest))
2716 bgp_adj_out_set_subgroup(
2717 dest, subgrp, &attr, selected);
2718 else
2719 bgp_adj_out_unset_subgroup(
2720 dest, subgrp, 1, addpath_tx_id);
2721 }
a77e2f4b 2722 } else
9bcb3eef 2723 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2724 addpath_tx_id);
d62a17ae 2725 }
2726
2727 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2728 else {
9bcb3eef 2729 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2730 }
200df115 2731}
fee0f4c6 2732
3064bf43 2733/*
e1072051 2734 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2735 * This is called at the end of route processing.
3064bf43 2736 */
9bcb3eef 2737void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2738{
40381db7 2739 struct bgp_path_info *pi;
3064bf43 2740
9bcb3eef 2741 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2742 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2743 continue;
40381db7
DS
2744 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2745 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2746 }
3064bf43 2747}
2748
2749/*
2750 * Has the route changed from the RIB's perspective? This is invoked only
2751 * if the route selection returns the same best route as earlier - to
2752 * determine if we need to update zebra or not.
2753 */
9bcb3eef 2754bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2755{
4b7e6066 2756 struct bgp_path_info *mpinfo;
d62a17ae 2757
2bb9eff4
DS
2758 /* If this is multipath, check all selected paths for any nexthop
2759 * change or attribute change. Some attribute changes (e.g., community)
2760 * aren't of relevance to the RIB, but we'll update zebra to ensure
2761 * we handle the case of BGP nexthop change. This is the behavior
2762 * when the best path has an attribute change anyway.
d62a17ae 2763 */
1defdda8 2764 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2765 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2766 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2767 return true;
d62a17ae 2768
2bb9eff4
DS
2769 /*
2770 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2771 */
18ee8310
DS
2772 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2773 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2774 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2775 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2776 return true;
d62a17ae 2777 }
3064bf43 2778
d62a17ae 2779 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2780 return false;
3064bf43 2781}
2782
d62a17ae 2783struct bgp_process_queue {
2784 struct bgp *bgp;
9bcb3eef 2785 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2786#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2787 unsigned int flags;
2788 unsigned int queued;
200df115 2789};
2790
3b0c17e1 2791static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2792 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2793 struct bgp_path_info *new_select,
2794 struct bgp_path_info *old_select)
2795{
9bcb3eef 2796 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2797
2798 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2799 return;
2800
2801 if (advertise_type5_routes(bgp, afi) && new_select
2802 && is_route_injectable_into_evpn(new_select)) {
2803
2804 /* apply the route-map */
2805 if (bgp->adv_cmd_rmap[afi][safi].map) {
2806 route_map_result_t ret;
2807 struct bgp_path_info rmap_path;
2808 struct bgp_path_info_extra rmap_path_extra;
2809 struct attr dummy_attr;
2810
2811 dummy_attr = *new_select->attr;
2812
2813 /* Fill temp path_info */
9bcb3eef 2814 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2815 new_select, new_select->peer,
2816 &dummy_attr);
2817
2818 RESET_FLAG(dummy_attr.rmap_change_flags);
2819
2820 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2821 p, &rmap_path);
3b0c17e1 2822
2823 if (ret == RMAP_DENYMATCH) {
2824 bgp_attr_flush(&dummy_attr);
2825 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2826 safi);
2827 } else
2828 bgp_evpn_advertise_type5_route(
2829 bgp, p, &dummy_attr, afi, safi);
2830 } else {
2831 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2832 afi, safi);
2833 }
2834 } else if (advertise_type5_routes(bgp, afi) && old_select
2835 && is_route_injectable_into_evpn(old_select))
2836 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2837}
2838
bb2ca692
MS
2839/*
2840 * Utility to determine whether a particular path_info should use
2841 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2842 * in a path where we basically _know_ this is a BGP-LU route.
2843 */
2844static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2845{
2846 /* Certain types get imp null; so do paths where the nexthop is
2847 * not labeled.
2848 */
2849 if (new_select->sub_type == BGP_ROUTE_STATIC
2850 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2851 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2852 return true;
2853 else if (new_select->extra == NULL ||
2854 !bgp_is_valid_label(&new_select->extra->label[0]))
2855 /* TODO -- should be configurable? */
2856 return true;
2857 else
2858 return false;
2859}
2860
3103e8d2
DS
2861/*
2862 * old_select = The old best path
2863 * new_select = the new best path
2864 *
2865 * if (!old_select && new_select)
2866 * We are sending new information on.
2867 *
2868 * if (old_select && new_select) {
2869 * if (new_select != old_select)
2870 * We have a new best path send a change
2871 * else
2872 * We've received a update with new attributes that needs
2873 * to be passed on.
2874 * }
2875 *
2876 * if (old_select && !new_select)
2877 * We have no eligible route that we can announce or the rn
2878 * is being removed.
2879 */
9bcb3eef 2880static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2881 afi_t afi, safi_t safi)
d62a17ae 2882{
4b7e6066
DS
2883 struct bgp_path_info *new_select;
2884 struct bgp_path_info *old_select;
2885 struct bgp_path_info_pair old_and_new;
ddb5b488 2886 int debug = 0;
d62a17ae 2887
892fedb6 2888 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2889 if (dest)
2890 debug = bgp_debug_bestpath(dest);
b54892e0 2891 if (debug)
f4c713ae 2892 zlog_debug(
56ca3b5b 2893 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2894 __func__, dest);
f4c713ae
LB
2895 return;
2896 }
d62a17ae 2897 /* Is it end of initial update? (after startup) */
9bcb3eef 2898 if (!dest) {
e36f61b5
DS
2899 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2900 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2901
2902 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2903 FOREACH_AFI_SAFI (afi, safi) {
2904 if (bgp_fibupd_safi(safi))
2905 bgp_zebra_announce_table(bgp, afi, safi);
2906 }
d62a17ae 2907 bgp->main_peers_update_hold = 0;
2908
2909 bgp_start_routeadv(bgp);
aac24838 2910 return;
d62a17ae 2911 }
cb1faec9 2912
9bcb3eef 2913 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2914
9bcb3eef 2915 debug = bgp_debug_bestpath(dest);
b54892e0 2916 if (debug)
4378495a
DS
2917 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2918 dest, bgp->name_pretty, afi2str(afi),
2919 safi2str(safi));
ddb5b488 2920
f009ff26 2921 /* The best path calculation for the route is deferred if
2922 * BGP_NODE_SELECT_DEFER is set
2923 */
9bcb3eef 2924 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2925 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2926 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2927 return;
2928 }
2929
d62a17ae 2930 /* Best path selection. */
9bcb3eef 2931 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2932 afi, safi);
2933 old_select = old_and_new.old;
2934 new_select = old_and_new.new;
2935
2936 /* Do we need to allocate or free labels?
2937 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2938 * necessary to do this upon changes to best path. Exceptions:
2939 * - label index has changed -> recalculate resulting label
2940 * - path_info sub_type changed -> switch to/from implicit-null
2941 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2942 */
318cac96 2943 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2944 if (new_select) {
2945 if (!old_select
2946 || bgp_label_index_differs(new_select, old_select)
57592a53 2947 || new_select->sub_type != old_select->sub_type
9bcb3eef 2948 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2949 /* Enforced penultimate hop popping:
2950 * implicit-null for local routes, aggregate
2951 * and redistributed routes
2952 */
bb2ca692 2953 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 2954 if (CHECK_FLAG(
9bcb3eef 2955 dest->flags,
992dd67e
PR
2956 BGP_NODE_REGISTERED_FOR_LABEL)
2957 || CHECK_FLAG(
2958 dest->flags,
2959 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2960 bgp_unregister_for_label(dest);
67f67ba4
DA
2961 dest->local_label = mpls_lse_encode(
2962 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
2963 1);
9bcb3eef 2964 bgp_set_valid_label(&dest->local_label);
d62a17ae 2965 } else
9bcb3eef
DS
2966 bgp_register_for_label(dest,
2967 new_select);
d62a17ae 2968 }
9bcb3eef 2969 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2970 BGP_NODE_REGISTERED_FOR_LABEL)
2971 || CHECK_FLAG(dest->flags,
2972 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2973 bgp_unregister_for_label(dest);
318cac96 2974 }
992dd67e
PR
2975 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2976 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2977 bgp_unregister_for_label(dest);
d62a17ae 2978 }
cd1964ff 2979
b54892e0 2980 if (debug)
ddb5b488 2981 zlog_debug(
4378495a
DS
2982 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2983 __func__, dest, bgp->name_pretty, afi2str(afi),
2984 safi2str(safi), old_select, new_select);
ddb5b488 2985
d62a17ae 2986 /* If best route remains the same and this is not due to user-initiated
2987 * clear, see exactly what needs to be done.
2988 */
d62a17ae 2989 if (old_select && old_select == new_select
9bcb3eef 2990 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2991 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2992 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2993 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2994#ifdef ENABLE_BGP_VNC
d62a17ae 2995 vnc_import_bgp_add_route(bgp, p, old_select);
2996 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2997#endif
bb744275 2998 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2999 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3000
be785e35
DS
3001 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3002 && new_select->sub_type == BGP_ROUTE_NORMAL)
3003 SET_FLAG(dest->flags,
3004 BGP_NODE_FIB_INSTALL_PENDING);
3005
ddb5b488
PZ
3006 if (new_select->type == ZEBRA_ROUTE_BGP
3007 && (new_select->sub_type == BGP_ROUTE_NORMAL
3008 || new_select->sub_type
3009 == BGP_ROUTE_IMPORTED))
3010
9bcb3eef 3011 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3012 bgp, afi, safi);
3013 }
d62a17ae 3014 }
d62a17ae 3015
3016 /* If there is a change of interest to peers, reannounce the
3017 * route. */
1defdda8 3018 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3019 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3020 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3021 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3022
3023 /* unicast routes must also be annouced to
3024 * labeled-unicast update-groups */
3025 if (safi == SAFI_UNICAST)
3026 group_announce_route(bgp, afi,
9bcb3eef 3027 SAFI_LABELED_UNICAST, dest,
d62a17ae 3028 new_select);
3029
1defdda8 3030 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3031 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3032 }
fee0f4c6 3033
3b0c17e1 3034 /* advertise/withdraw type-5 routes */
3035 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3036 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3037 bgp_process_evpn_route_injection(
9bcb3eef 3038 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3039
b1875e65 3040 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3041 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3042 bgp_zebra_clear_route_change_flags(dest);
3043 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3044 return;
d62a17ae 3045 }
8ad7271d 3046
d62a17ae 3047 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3048 */
9bcb3eef 3049 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3050
3051 /* bestpath has changed; bump version */
3052 if (old_select || new_select) {
9bcb3eef 3053 bgp_bump_version(dest);
d62a17ae 3054
3055 if (!bgp->t_rmap_def_originate_eval) {
3056 bgp_lock(bgp);
3057 thread_add_timer(
3058 bm->master,
3059 update_group_refresh_default_originate_route_map,
3060 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3061 &bgp->t_rmap_def_originate_eval);
3062 }
3063 }
3f9c7369 3064
d62a17ae 3065 if (old_select)
9bcb3eef 3066 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3067 if (new_select) {
ddb5b488
PZ
3068 if (debug)
3069 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3070 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3071 bgp_path_info_unset_flag(dest, new_select,
3072 BGP_PATH_ATTR_CHANGED);
1defdda8 3073 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3074 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3075 }
338b3424 3076
49e5a4a0 3077#ifdef ENABLE_BGP_VNC
d62a17ae 3078 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3079 if (old_select != new_select) {
3080 if (old_select) {
3081 vnc_import_bgp_exterior_del_route(bgp, p,
3082 old_select);
3083 vnc_import_bgp_del_route(bgp, p, old_select);
3084 }
3085 if (new_select) {
3086 vnc_import_bgp_exterior_add_route(bgp, p,
3087 new_select);
3088 vnc_import_bgp_add_route(bgp, p, new_select);
3089 }
3090 }
3091 }
65efcfce
LB
3092#endif
3093
9bcb3eef 3094 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3095
3096 /* unicast routes must also be annouced to labeled-unicast update-groups
3097 */
3098 if (safi == SAFI_UNICAST)
9bcb3eef 3099 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3100 new_select);
3101
3102 /* FIB update. */
3103 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3104 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3105
d62a17ae 3106 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3107 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3108 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3109 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3110
be785e35
DS
3111 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3112 SET_FLAG(dest->flags,
3113 BGP_NODE_FIB_INSTALL_PENDING);
3114
2b659f33
MK
3115 /* if this is an evpn imported type-5 prefix,
3116 * we need to withdraw the route first to clear
3117 * the nh neigh and the RMAC entry.
3118 */
3119 if (old_select &&
3120 is_route_parent_evpn(old_select))
3121 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3122
9bcb3eef 3123 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3124 } else {
d62a17ae 3125 /* Withdraw the route from the kernel. */
3126 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3127 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3128 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3129 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3130
568e10ca 3131 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3132 }
718e3744 3133 }
3064bf43 3134
9bcb3eef 3135 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3136 old_select);
5424b7ba 3137
d62a17ae 3138 /* Clear any route change flags. */
9bcb3eef 3139 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3140
18ee8310 3141 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3142 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3143 bgp_path_info_reap(dest, old_select);
d62a17ae 3144
9bcb3eef 3145 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3146 return;
718e3744 3147}
3148
f009ff26 3149/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3150int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3151{
9bcb3eef 3152 struct bgp_dest *dest;
f009ff26 3153 int cnt = 0;
3154 struct afi_safi_info *thread_info;
f009ff26 3155
56c226e7
DS
3156 if (bgp->gr_info[afi][safi].t_route_select) {
3157 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3158
3159 thread_info = THREAD_ARG(t);
3160 XFREE(MTYPE_TMP, thread_info);
f009ff26 3161 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3162 }
f009ff26 3163
3164 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3165 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3166 get_afi_safi_str(afi, safi, false),
26742171 3167 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3168 }
3169
3170 /* Process the route list */
6338d242 3171 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3172 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3173 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3174 dest = bgp_route_next(dest)) {
3175 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3176 continue;
3177
3178 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3179 bgp->gr_info[afi][safi].gr_deferred--;
3180 bgp_process_main_one(bgp, dest, afi, safi);
3181 cnt++;
067ea165
CB
3182 }
3183 /* If iteration stopped before the entire table was traversed then the
3184 * node needs to be unlocked.
3185 */
3186 if (dest) {
3187 bgp_dest_unlock_node(dest);
3188 dest = NULL;
f009ff26 3189 }
3190
9e3b51a7 3191 /* Send EOR message when all routes are processed */
6338d242 3192 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3193 bgp_send_delayed_eor(bgp);
8c48b3b6 3194 /* Send route processing complete message to RIB */
3195 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3196 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3197 return 0;
9e3b51a7 3198 }
f009ff26 3199
3200 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3201
3202 thread_info->afi = afi;
3203 thread_info->safi = safi;
3204 thread_info->bgp = bgp;
3205
3206 /* If there are more routes to be processed, start the
3207 * selection timer
3208 */
3209 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3210 BGP_ROUTE_SELECT_DELAY,
3211 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3212 return 0;
3213}
3214
aac24838 3215static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3216{
aac24838
JB
3217 struct bgp_process_queue *pqnode = data;
3218 struct bgp *bgp = pqnode->bgp;
d62a17ae 3219 struct bgp_table *table;
9bcb3eef 3220 struct bgp_dest *dest;
aac24838
JB
3221
3222 /* eoiu marker */
3223 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3224 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3225 /* should always have dedicated wq call */
3226 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3227 return WQ_SUCCESS;
3228 }
3229
ac021f40 3230 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3231 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3232 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3233 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3234 table = bgp_dest_table(dest);
3235 /* note, new DESTs may be added as part of processing */
3236 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3237
9bcb3eef 3238 bgp_dest_unlock_node(dest);
d62a17ae 3239 bgp_table_unlock(table);
3240 }
aac24838
JB
3241
3242 return WQ_SUCCESS;
3243}
3244
3245static void bgp_processq_del(struct work_queue *wq, void *data)
3246{
3247 struct bgp_process_queue *pqnode = data;
3248
3249 bgp_unlock(pqnode->bgp);
3250
3251 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3252}
3253
b6c386bb 3254void bgp_process_queue_init(struct bgp *bgp)
200df115 3255{
b6c386bb
DS
3256 if (!bgp->process_queue) {
3257 char name[BUFSIZ];
3258
3259 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3260 bgp->process_queue = work_queue_new(bm->master, name);
3261 }
3262
3263 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3264 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3265 bgp->process_queue->spec.max_retries = 0;
3266 bgp->process_queue->spec.hold = 50;
d62a17ae 3267 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3268 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3269}
3270
cfe8d15a 3271static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3272{
3273 struct bgp_process_queue *pqnode;
3274
a4d82a8a
PZ
3275 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3276 sizeof(struct bgp_process_queue));
aac24838
JB
3277
3278 /* unlocked in bgp_processq_del */
3279 pqnode->bgp = bgp_lock(bgp);
3280 STAILQ_INIT(&pqnode->pqueue);
3281
aac24838
JB
3282 return pqnode;
3283}
3284
9bcb3eef 3285void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3286{
aac24838 3287#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3288 struct work_queue *wq = bgp->process_queue;
d62a17ae 3289 struct bgp_process_queue *pqnode;
cfe8d15a 3290 int pqnode_reuse = 0;
495f0b13 3291
d62a17ae 3292 /* already scheduled for processing? */
9bcb3eef 3293 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3294 return;
2e02b9b2 3295
f009ff26 3296 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3297 * the workqueue
3298 */
9bcb3eef 3299 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3300 if (BGP_DEBUG(update, UPDATE_OUT))
3301 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3302 dest);
f009ff26 3303 return;
3304 }
3305
46aeabed
LS
3306 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3307 if (BGP_DEBUG(update, UPDATE_OUT))
3308 zlog_debug(
3309 "Soft reconfigure table in progress for route %p",
3310 dest);
3311 return;
3312 }
3313
aac24838 3314 if (wq == NULL)
d62a17ae 3315 return;
3316
aac24838 3317 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3318 limit only if is from the same BGP view and it's not an EOIU marker
3319 */
aac24838
JB
3320 if (work_queue_item_count(wq)) {
3321 struct work_queue_item *item = work_queue_last_item(wq);
3322 pqnode = item->data;
228da428 3323
a4d82a8a
PZ
3324 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3325 || pqnode->bgp != bgp
3326 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3327 pqnode = bgp_processq_alloc(bgp);
3328 else
3329 pqnode_reuse = 1;
aac24838 3330 } else
cfe8d15a 3331 pqnode = bgp_processq_alloc(bgp);
aac24838 3332 /* all unlocked in bgp_process_wq */
9bcb3eef 3333 bgp_table_lock(bgp_dest_table(dest));
aac24838 3334
9bcb3eef
DS
3335 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3336 bgp_dest_lock_node(dest);
aac24838 3337
60466a63 3338 /* can't be enqueued twice */
9bcb3eef
DS
3339 assert(STAILQ_NEXT(dest, pq) == NULL);
3340 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3341 pqnode->queued++;
3342
cfe8d15a
LB
3343 if (!pqnode_reuse)
3344 work_queue_add(wq, pqnode);
3345
d62a17ae 3346 return;
fee0f4c6 3347}
0a486e5f 3348
d62a17ae 3349void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3350{
d62a17ae 3351 struct bgp_process_queue *pqnode;
cb1faec9 3352
b6c386bb 3353 if (bgp->process_queue == NULL)
d62a17ae 3354 return;
2e02b9b2 3355
cfe8d15a 3356 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3357
aac24838 3358 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3359 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3360}
3361
cc9f21da 3362static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3363{
d62a17ae 3364 struct peer *peer;
0a486e5f 3365
d62a17ae 3366 peer = THREAD_ARG(thread);
3367 peer->t_pmax_restart = NULL;
0a486e5f 3368
d62a17ae 3369 if (bgp_debug_neighbor_events(peer))
3370 zlog_debug(
3371 "%s Maximum-prefix restart timer expired, restore peering",
3372 peer->host);
0a486e5f 3373
a9bafa95 3374 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3375 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3376}
3377
9cbd06e0
DA
3378static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3379 safi_t safi)
3380{
3381 uint32_t count = 0;
f41b0459 3382 bool filtered = false;
9cbd06e0
DA
3383 struct bgp_dest *dest;
3384 struct bgp_adj_in *ain;
40bb2ccf 3385 struct attr attr = {};
9cbd06e0
DA
3386 struct bgp_table *table = peer->bgp->rib[afi][safi];
3387
3388 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3389 for (ain = dest->adj_in; ain; ain = ain->next) {
3390 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3391
3392 attr = *ain->attr;
9cbd06e0
DA
3393
3394 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3395 == FILTER_DENY)
f41b0459
DA
3396 filtered = true;
3397
3398 if (bgp_input_modifier(
3399 peer, rn_p, &attr, afi, safi,
3400 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3401 NULL, 0, NULL)
3402 == RMAP_DENY)
3403 filtered = true;
3404
3405 if (filtered)
9cbd06e0 3406 count++;
f41b0459 3407
d498917e 3408 bgp_attr_flush(&attr);
9cbd06e0
DA
3409 }
3410 }
3411
3412 return count;
3413}
3414
3dc339cd
DA
3415bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3416 int always)
718e3744 3417{
d62a17ae 3418 iana_afi_t pkt_afi;
5c525538 3419 iana_safi_t pkt_safi;
9cbd06e0
DA
3420 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3421 PEER_FLAG_MAX_PREFIX_FORCE))
3422 ? bgp_filtered_routes_count(peer, afi, safi)
3423 + peer->pcount[afi][safi]
3424 : peer->pcount[afi][safi];
9cabb64b 3425
d62a17ae 3426 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3427 return false;
e0701b79 3428
9cbd06e0 3429 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3430 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3431 PEER_STATUS_PREFIX_LIMIT)
3432 && !always)
3dc339cd 3433 return false;
e0701b79 3434
d62a17ae 3435 zlog_info(
f70c91dc
DA
3436 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3437 get_afi_safi_str(afi, safi, false), peer, pcount,
3438 peer->pmax[afi][safi]);
d62a17ae 3439 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3440
3441 if (CHECK_FLAG(peer->af_flags[afi][safi],
3442 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3443 return false;
d62a17ae 3444
3445 /* Convert AFI, SAFI to values for packet. */
3446 pkt_afi = afi_int2iana(afi);
3447 pkt_safi = safi_int2iana(safi);
3448 {
d7c0a89a 3449 uint8_t ndata[7];
d62a17ae 3450
3451 ndata[0] = (pkt_afi >> 8);
3452 ndata[1] = pkt_afi;
3453 ndata[2] = pkt_safi;
3454 ndata[3] = (peer->pmax[afi][safi] >> 24);
3455 ndata[4] = (peer->pmax[afi][safi] >> 16);
3456 ndata[5] = (peer->pmax[afi][safi] >> 8);
3457 ndata[6] = (peer->pmax[afi][safi]);
3458
3459 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3460 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3461 BGP_NOTIFY_CEASE_MAX_PREFIX,
3462 ndata, 7);
3463 }
3464
3465 /* Dynamic peers will just close their connection. */
3466 if (peer_dynamic_neighbor(peer))
3dc339cd 3467 return true;
d62a17ae 3468
3469 /* restart timer start */
3470 if (peer->pmax_restart[afi][safi]) {
3471 peer->v_pmax_restart =
3472 peer->pmax_restart[afi][safi] * 60;
3473
3474 if (bgp_debug_neighbor_events(peer))
3475 zlog_debug(
f70c91dc
DA
3476 "%pBP Maximum-prefix restart timer started for %d secs",
3477 peer, peer->v_pmax_restart);
d62a17ae 3478
3479 BGP_TIMER_ON(peer->t_pmax_restart,
3480 bgp_maximum_prefix_restart_timer,
3481 peer->v_pmax_restart);
3482 }
3483
3dc339cd 3484 return true;
d62a17ae 3485 } else
3486 UNSET_FLAG(peer->af_sflags[afi][safi],
3487 PEER_STATUS_PREFIX_LIMIT);
3488
b1823b69
DS
3489 if (pcount
3490 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3491 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3492 PEER_STATUS_PREFIX_THRESHOLD)
3493 && !always)
3dc339cd 3494 return false;
d62a17ae 3495
3496 zlog_info(
f70c91dc
DA
3497 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3498 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3499 peer->pmax[afi][safi]);
d62a17ae 3500 SET_FLAG(peer->af_sflags[afi][safi],
3501 PEER_STATUS_PREFIX_THRESHOLD);
3502 } else
3503 UNSET_FLAG(peer->af_sflags[afi][safi],
3504 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3505 return false;
718e3744 3506}
3507
b40d939b 3508/* Unconditionally remove the route from the RIB, without taking
3509 * damping into consideration (eg, because the session went down)
3510 */
9bcb3eef 3511void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3512 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3513{
f009ff26 3514
3515 struct bgp *bgp = NULL;
3516 bool delete_route = false;
3517
9bcb3eef
DS
3518 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3519 safi);
d62a17ae 3520
f009ff26 3521 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3522 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3523
f009ff26 3524 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3525 * flag
3526 */
3527 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3528 delete_route = true;
9bcb3eef 3529 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3530 delete_route = true;
f009ff26 3531 if (delete_route) {
9bcb3eef
DS
3532 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3533 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3534 bgp = pi->peer->bgp;
26742171 3535 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3536 }
3537 }
3538 }
4a11bf2c 3539
9bcb3eef
DS
3540 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3541 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3542}
3543
9bcb3eef 3544static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3545 struct peer *peer, afi_t afi, safi_t safi,
3546 struct prefix_rd *prd)
3547{
9bcb3eef 3548 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3549
d62a17ae 3550 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3551 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3552 */
b4f7f45b
IR
3553 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3554 && peer->sort == BGP_PEER_EBGP)
3555 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3556 == BGP_DAMP_SUPPRESSED) {
3557 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3558 safi);
3559 return;
d62a17ae 3560 }
3561
49e5a4a0 3562#ifdef ENABLE_BGP_VNC
d62a17ae 3563 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3564 struct bgp_dest *pdest = NULL;
d62a17ae 3565 struct bgp_table *table = NULL;
3566
9bcb3eef
DS
3567 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3568 (struct prefix *)prd);
3569 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3570 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3571
3572 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3573 peer->bgp, prd, table, p, pi);
d62a17ae 3574 }
9bcb3eef 3575 bgp_dest_unlock_node(pdest);
d62a17ae 3576 }
3577 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3578 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3579
b54892e0
DS
3580 vnc_import_bgp_del_route(peer->bgp, p, pi);
3581 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3582 }
65efcfce 3583 }
d62a17ae 3584#endif
128ea8ab 3585
d62a17ae 3586 /* If this is an EVPN route, process for un-import. */
3587 if (safi == SAFI_EVPN)
b54892e0 3588 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3589
9bcb3eef 3590 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3591}
3592
4b7e6066
DS
3593struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3594 struct peer *peer, struct attr *attr,
9bcb3eef 3595 struct bgp_dest *dest)
fb018d25 3596{
4b7e6066 3597 struct bgp_path_info *new;
fb018d25 3598
d62a17ae 3599 /* Make new BGP info. */
4b7e6066 3600 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3601 new->type = type;
3602 new->instance = instance;
3603 new->sub_type = sub_type;
3604 new->peer = peer;
3605 new->attr = attr;
3606 new->uptime = bgp_clock();
9bcb3eef 3607 new->net = dest;
d62a17ae 3608 return new;
fb018d25
DS
3609}
3610
c265ee22 3611/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3612bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3613 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3614 struct bgp_dest *dest)
d62a17ae 3615{
2dbe3fa9 3616 bool ret = false;
b099a5c8
DA
3617 bool is_bgp_static_route =
3618 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3619 : false;
d62a17ae 3620
e8442016
DS
3621 /*
3622 * Only validated for unicast and multicast currently.
3623 * Also valid for EVPN where the nexthop is an IP address.
3624 * If we are a bgp static route being checked then there is
3625 * no need to check to see if the nexthop is martian as
3626 * that it should be ok.
3627 */
3628 if (is_bgp_static_route ||
3629 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3630 return false;
d62a17ae 3631
3632 /* If NEXT_HOP is present, validate it. */
3633 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3634 if (attr->nexthop.s_addr == INADDR_ANY ||
3635 !ipv4_unicast_valid(&attr->nexthop) ||
3636 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3637 return true;
d62a17ae 3638 }
c265ee22 3639
d62a17ae 3640 /* If MP_NEXTHOP is present, validate it. */
3641 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3642 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3643 * it is not an IPv6 link-local address.
0355b41d
DA
3644 *
3645 * If we receive an UPDATE with nexthop length set to 32 bytes
3646 * we shouldn't discard an UPDATE if it's set to (::).
3647 * The link-local (2st) is validated along the code path later.
d62a17ae 3648 */
3649 if (attr->mp_nexthop_len) {
3650 switch (attr->mp_nexthop_len) {
3651 case BGP_ATTR_NHLEN_IPV4:
3652 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3653 ret = (attr->mp_nexthop_global_in.s_addr ==
3654 INADDR_ANY ||
3655 !ipv4_unicast_valid(
3656 &attr->mp_nexthop_global_in) ||
3657 bgp_nexthop_self(bgp, afi, type, stype, attr,
3658 dest));
d62a17ae 3659 break;
3660
3661 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3662 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3663 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3664 &attr->mp_nexthop_global)
d62a17ae 3665 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3666 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3667 &attr->mp_nexthop_global)
3668 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3669 dest));
d62a17ae 3670 break;
0355b41d
DA
3671 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3672 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3673 || IN6_IS_ADDR_MULTICAST(
3674 &attr->mp_nexthop_global)
3675 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3676 dest));
0355b41d 3677 break;
d62a17ae 3678
3679 default:
3dc339cd 3680 ret = true;
d62a17ae 3681 break;
3682 }
3683 }
c265ee22 3684
d62a17ae 3685 return ret;
3686}
3687
aade37d7 3688static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3689{
3690 struct community *old;
3691 struct community *new;
3692 struct community *merge;
aade37d7 3693 struct community *no_export;
2721dd61 3694
9a706b42 3695 old = bgp_attr_get_community(attr);
aade37d7 3696 no_export = community_str2com("no-export");
2721dd61 3697
b4efa101
DA
3698 assert(no_export);
3699
2721dd61 3700 if (old) {
aade37d7 3701 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3702
3703 if (!old->refcnt)
3704 community_free(&old);
3705
3706 new = community_uniq_sort(merge);
3707 community_free(&merge);
3708 } else {
aade37d7 3709 new = community_dup(no_export);
2721dd61
DA
3710 }
3711
aade37d7 3712 community_free(&no_export);
2721dd61 3713
9a706b42 3714 bgp_attr_set_community(attr, new);
2721dd61
DA
3715}
3716
5a1ae2c2 3717int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3718 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3719 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3720 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3721 struct bgp_route_evpn *evpn)
d62a17ae 3722{
3723 int ret;
3724 int aspath_loop_count = 0;
9bcb3eef 3725 struct bgp_dest *dest;
d62a17ae 3726 struct bgp *bgp;
3727 struct attr new_attr;
3728 struct attr *attr_new;
40381db7 3729 struct bgp_path_info *pi;
4b7e6066
DS
3730 struct bgp_path_info *new;
3731 struct bgp_path_info_extra *extra;
d62a17ae 3732 const char *reason;
3733 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3734 int connected = 0;
3735 int do_loop_check = 1;
3736 int has_valid_label = 0;
7c312383 3737 afi_t nh_afi;
949b0f24 3738 uint8_t pi_type = 0;
3739 uint8_t pi_sub_type = 0;
9146341f 3740 bool force_evpn_import = false;
907707db 3741 safi_t orig_safi = safi;
949b0f24 3742
c7bb4f00 3743 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3744 char pfxprint[PREFIX2STR_BUFFER];
3745
3746 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3747 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3748 afi, safi, attr);
6401252f
QY
3749 }
3750
49e5a4a0 3751#ifdef ENABLE_BGP_VNC
d62a17ae 3752 int vnc_implicit_withdraw = 0;
65efcfce 3753#endif
d62a17ae 3754 int same_attr = 0;
718e3744 3755
907707db
MS
3756 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3757 if (orig_safi == SAFI_LABELED_UNICAST)
3758 safi = SAFI_UNICAST;
3759
6006b807 3760 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3761 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3762 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3763
d62a17ae 3764 bgp = peer->bgp;
9bcb3eef 3765 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3766 /* TODO: Check to see if we can get rid of "is_valid_label" */
3767 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3768 has_valid_label = (num_labels > 0) ? 1 : 0;
3769 else
3770 has_valid_label = bgp_is_valid_label(label);
718e3744 3771
28f66de2
MS
3772 if (has_valid_label)
3773 assert(label != NULL);
3774
66ff6089
AD
3775 /* Update overlay index of the attribute */
3776 if (afi == AFI_L2VPN && evpn)
3777 memcpy(&attr->evpn_overlay, evpn,
3778 sizeof(struct bgp_route_evpn));
3779
d62a17ae 3780 /* When peer's soft reconfiguration enabled. Record input packet in
3781 Adj-RIBs-In. */
3782 if (!soft_reconfig
3783 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3784 && peer != bgp->peer_self)
9bcb3eef 3785 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3786
3787 /* Check previously received route. */
9bcb3eef 3788 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3789 if (pi->peer == peer && pi->type == type
3790 && pi->sub_type == sub_type
3791 && pi->addpath_rx_id == addpath_id)
d62a17ae 3792 break;
3793
3794 /* AS path local-as loop check. */
3795 if (peer->change_local_as) {
c4368918
DW
3796 if (peer->allowas_in[afi][safi])
3797 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3798 else if (!CHECK_FLAG(peer->flags,
3799 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3800 aspath_loop_count = 1;
3801
3802 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3803 > aspath_loop_count) {
b4d46cc9 3804 peer->stat_pfx_aspath_loop++;
692174a1 3805 reason = "as-path contains our own AS;";
d62a17ae 3806 goto filtered;
3807 }
718e3744 3808 }
718e3744 3809
d62a17ae 3810 /* If the peer is configured for "allowas-in origin" and the last ASN in
3811 * the
3812 * as-path is our ASN then we do not need to call aspath_loop_check
3813 */
3814 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3815 if (aspath_get_last_as(attr->aspath) == bgp->as)
3816 do_loop_check = 0;
3817
3818 /* AS path loop check. */
3819 if (do_loop_check) {
3820 if (aspath_loop_check(attr->aspath, bgp->as)
3821 > peer->allowas_in[afi][safi]
3822 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3823 && aspath_loop_check(attr->aspath, bgp->confed_id)
3824 > peer->allowas_in[afi][safi])) {
b4d46cc9 3825 peer->stat_pfx_aspath_loop++;
d62a17ae 3826 reason = "as-path contains our own AS;";
3827 goto filtered;
3828 }
3829 }
aac9ef6c 3830
d62a17ae 3831 /* Route reflector originator ID check. */
3832 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3833 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3834 peer->stat_pfx_originator_loop++;
d62a17ae 3835 reason = "originator is us;";
3836 goto filtered;
3837 }
718e3744 3838
d62a17ae 3839 /* Route reflector cluster ID check. */
3840 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3841 peer->stat_pfx_cluster_loop++;
d62a17ae 3842 reason = "reflected from the same cluster;";
3843 goto filtered;
3844 }
718e3744 3845
d62a17ae 3846 /* Apply incoming filter. */
907707db 3847 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3848 peer->stat_pfx_filter++;
d62a17ae 3849 reason = "filter;";
3850 goto filtered;
3851 }
718e3744 3852
a8b72dc6
DA
3853 /* RFC 8212 to prevent route leaks.
3854 * This specification intends to improve this situation by requiring the
3855 * explicit configuration of both BGP Import and Export Policies for any
3856 * External BGP (EBGP) session such as customers, peers, or
3857 * confederation boundaries for all enabled address families. Through
3858 * codification of the aforementioned requirement, operators will
3859 * benefit from consistent behavior across different BGP
3860 * implementations.
3861 */
1d3fdccf 3862 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3863 if (!bgp_inbound_policy_exists(peer,
3864 &peer->filter[afi][safi])) {
3865 reason = "inbound policy missing";
b17826b7
DS
3866 if (monotime_since(&bgp->ebgprequirespolicywarning,
3867 NULL) > FIFTEENMINUTE2USEC ||
3868 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3869 zlog_warn(
3870 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3871 monotime(&bgp->ebgprequirespolicywarning);
3872 }
a8b72dc6
DA
3873 goto filtered;
3874 }
3875
fb29348a
DA
3876 /* draft-ietf-idr-deprecate-as-set-confed-set
3877 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3878 * Eventually, This document (if approved) updates RFC 4271
3879 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3880 * and obsoletes RFC 6472.
3881 */
7f972cd8 3882 if (peer->bgp->reject_as_sets)
fb29348a
DA
3883 if (aspath_check_as_sets(attr->aspath)) {
3884 reason =
3885 "as-path contains AS_SET or AS_CONFED_SET type;";
3886 goto filtered;
3887 }
3888
6f4f49b2 3889 new_attr = *attr;
d62a17ae 3890
3891 /* Apply incoming route-map.
3892 * NB: new_attr may now contain newly allocated values from route-map
3893 * "set"
3894 * commands, so we need bgp_attr_flush in the error paths, until we
3895 * intern
3896 * the attr (which takes over the memory references) */
907707db 3897 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3898 num_labels, dest)
3899 == RMAP_DENY) {
b4d46cc9 3900 peer->stat_pfx_filter++;
d62a17ae 3901 reason = "route-map;";
3902 bgp_attr_flush(&new_attr);
3903 goto filtered;
3904 }
718e3744 3905
05864da7 3906 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3907 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3908 /* remove from RIB previous entry */
3909 bgp_zebra_withdraw(p, pi, bgp, safi);
3910 }
3911
7f323236
DW
3912 if (peer->sort == BGP_PEER_EBGP) {
3913
2721dd61
DA
3914 /* rfc7999:
3915 * A BGP speaker receiving an announcement tagged with the
3916 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3917 * NO_EXPORT community as defined in RFC1997, or a
3918 * similar community, to prevent propagation of the
3919 * prefix outside the local AS. The community to prevent
3920 * propagation SHOULD be chosen according to the operator's
3921 * routing policy.
3922 */
9a706b42
DA
3923 if (bgp_attr_get_community(&new_attr) &&
3924 community_include(bgp_attr_get_community(&new_attr),
3925 COMMUNITY_BLACKHOLE))
aade37d7 3926 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3927
a4d82a8a
PZ
3928 /* If we receive the graceful-shutdown community from an eBGP
3929 * peer we must lower local-preference */
9a706b42
DA
3930 if (bgp_attr_get_community(&new_attr) &&
3931 community_include(bgp_attr_get_community(&new_attr),
3932 COMMUNITY_GSHUT)) {
7f323236
DW
3933 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3934 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3935
a4d82a8a
PZ
3936 /* If graceful-shutdown is configured then add the GSHUT
3937 * community to all paths received from eBGP peers */
637e5ba4 3938 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3939 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3940 }
3941
949b0f24 3942 if (pi) {
3943 pi_type = pi->type;
3944 pi_sub_type = pi->sub_type;
3945 }
3946
d62a17ae 3947 /* next hop check. */
a4d82a8a 3948 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3949 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3950 &new_attr, dest)) {
b4d46cc9 3951 peer->stat_pfx_nh_invalid++;
d62a17ae 3952 reason = "martian or self next-hop;";
3953 bgp_attr_flush(&new_attr);
3954 goto filtered;
3955 }
718e3744 3956
5c14a191 3957 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3958 peer->stat_pfx_nh_invalid++;
4e802e66 3959 reason = "self mac;";
4dbf2038 3960 bgp_attr_flush(&new_attr);
4e802e66
DS
3961 goto filtered;
3962 }
3963
a1b773e2
DS
3964 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3965 * condition :
3966 * Suppress fib is enabled
3967 * BGP_OPT_NO_FIB is not enabled
3968 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3969 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3970 */
3971 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3972 && (sub_type == BGP_ROUTE_NORMAL)
3973 && (!bgp_option_check(BGP_OPT_NO_FIB))
3974 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3975 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3976
9cbd06e0
DA
3977 /* If maximum prefix count is configured and current prefix
3978 * count exeed it.
3979 */
4dbf2038
IR
3980 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
3981 bgp_attr_flush(&new_attr);
9cbd06e0 3982 return -1;
4dbf2038
IR
3983 }
3984
3985 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 3986
d62a17ae 3987 /* If the update is implicit withdraw. */
40381db7
DS
3988 if (pi) {
3989 pi->uptime = bgp_clock();
3990 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3991
9bcb3eef 3992 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3993
d62a17ae 3994 /* Same attribute comes in. */
40381db7 3995 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3996 && same_attr
d62a17ae 3997 && (!has_valid_label
40381db7 3998 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3999 num_labels * sizeof(mpls_label_t))
66ff6089 4000 == 0)) {
b4f7f45b
IR
4001 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4002 BGP_CONFIG_DAMPENING)
d62a17ae 4003 && peer->sort == BGP_PEER_EBGP
40381db7 4004 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4005 if (bgp_debug_update(peer, p, NULL, 1)) {
4006 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4007 afi, safi, prd, p, label,
4008 num_labels, addpath_id ? 1 : 0,
66ff6089 4009 addpath_id, evpn, pfx_buf,
a4d82a8a 4010 sizeof(pfx_buf));
f70c91dc 4011 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4012 pfx_buf);
4013 }
4014
9bcb3eef 4015 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4016 != BGP_DAMP_SUPPRESSED) {
40381db7 4017 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4018 safi);
9bcb3eef 4019 bgp_process(bgp, dest, afi, safi);
d62a17ae 4020 }
4021 } else /* Duplicate - odd */
4022 {
4023 if (bgp_debug_update(peer, p, NULL, 1)) {
4024 if (!peer->rcvd_attr_printed) {
4025 zlog_debug(
f70c91dc
DA
4026 "%pBP rcvd UPDATE w/ attr: %s",
4027 peer,
d62a17ae 4028 peer->rcvd_attr_str);
4029 peer->rcvd_attr_printed = 1;
4030 }
4031
4032 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4033 afi, safi, prd, p, label,
4034 num_labels, addpath_id ? 1 : 0,
66ff6089 4035 addpath_id, evpn, pfx_buf,
a4d82a8a 4036 sizeof(pfx_buf));
d62a17ae 4037 zlog_debug(
f70c91dc
DA
4038 "%pBP rcvd %s...duplicate ignored",
4039 peer, pfx_buf);
d62a17ae 4040 }
4041
4042 /* graceful restart STALE flag unset. */
40381db7 4043 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4044 bgp_path_info_unset_flag(
9bcb3eef
DS
4045 dest, pi, BGP_PATH_STALE);
4046 bgp_dest_set_defer_flag(dest, false);
4047 bgp_process(bgp, dest, afi, safi);
d62a17ae 4048 }
4049 }
4050
9bcb3eef 4051 bgp_dest_unlock_node(dest);
d62a17ae 4052 bgp_attr_unintern(&attr_new);
4053
4054 return 0;
4055 }
718e3744 4056
d62a17ae 4057 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4058 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4059 if (bgp_debug_update(peer, p, NULL, 1)) {
4060 bgp_debug_rdpfxpath2str(
a4d82a8a 4061 afi, safi, prd, p, label, num_labels,
66ff6089 4062 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4063 pfx_buf, sizeof(pfx_buf));
d62a17ae 4064 zlog_debug(
f70c91dc
DA
4065 "%pBP rcvd %s, flapped quicker than processing",
4066 peer, pfx_buf);
d62a17ae 4067 }
4068
9bcb3eef 4069 bgp_path_info_restore(dest, pi);
9146341f 4070
4071 /*
4072 * If the BGP_PATH_REMOVED flag is set, then EVPN
4073 * routes would have been unimported already when a
4074 * prior BGP withdraw processing happened. Such routes
4075 * need to be imported again, so flag accordingly.
4076 */
4077 force_evpn_import = true;
d62a17ae 4078 }
718e3744 4079
d62a17ae 4080 /* Received Logging. */
4081 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4082 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4083 num_labels, addpath_id ? 1 : 0,
66ff6089 4084 addpath_id, evpn, pfx_buf,
a4d82a8a 4085 sizeof(pfx_buf));
f70c91dc 4086 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4087 }
718e3744 4088
d62a17ae 4089 /* graceful restart STALE flag unset. */
f009ff26 4090 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4091 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4092 bgp_dest_set_defer_flag(dest, false);
f009ff26 4093 }
d62a17ae 4094
4095 /* The attribute is changed. */
9bcb3eef 4096 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4097
4098 /* implicit withdraw, decrement aggregate and pcount here.
4099 * only if update is accepted, they'll increment below.
4100 */
40381db7 4101 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4102
4103 /* Update bgp route dampening information. */
b4f7f45b 4104 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4105 && peer->sort == BGP_PEER_EBGP) {
4106 /* This is implicit withdraw so we should update
b4f7f45b
IR
4107 dampening
4108 information. */
40381db7 4109 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4110 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4111 }
49e5a4a0 4112#ifdef ENABLE_BGP_VNC
d62a17ae 4113 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4114 struct bgp_dest *pdest = NULL;
d62a17ae 4115 struct bgp_table *table = NULL;
4116
9bcb3eef
DS
4117 pdest = bgp_node_get(bgp->rib[afi][safi],
4118 (struct prefix *)prd);
4119 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4120 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4121
4122 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4123 bgp, prd, table, p, pi);
d62a17ae 4124 }
9bcb3eef 4125 bgp_dest_unlock_node(pdest);
d62a17ae 4126 }
4127 if ((afi == AFI_IP || afi == AFI_IP6)
4128 && (safi == SAFI_UNICAST)) {
40381db7 4129 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4130 /*
4131 * Implicit withdraw case.
4132 */
4133 ++vnc_implicit_withdraw;
40381db7
DS
4134 vnc_import_bgp_del_route(bgp, p, pi);
4135 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4136 }
4137 }
65efcfce 4138#endif
128ea8ab 4139
d62a17ae 4140 /* Special handling for EVPN update of an existing route. If the
4141 * extended community attribute has changed, we need to
4142 * un-import
4143 * the route using its existing extended community. It will be
4144 * subsequently processed for import with the new extended
4145 * community.
4146 */
6f8c9c11
PR
4147 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4148 && !same_attr) {
40381db7 4149 if ((pi->attr->flag
d62a17ae 4150 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4151 && (attr_new->flag
4152 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4153 int cmp;
4154
b53e67a3
DA
4155 cmp = ecommunity_cmp(
4156 bgp_attr_get_ecommunity(pi->attr),
4157 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4158 if (!cmp) {
4159 if (bgp_debug_update(peer, p, NULL, 1))
4160 zlog_debug(
4161 "Change in EXT-COMM, existing %s new %s",
4162 ecommunity_str(
b53e67a3
DA
4163 bgp_attr_get_ecommunity(
4164 pi->attr)),
d62a17ae 4165 ecommunity_str(
b53e67a3
DA
4166 bgp_attr_get_ecommunity(
4167 attr_new)));
6f8c9c11
PR
4168 if (safi == SAFI_EVPN)
4169 bgp_evpn_unimport_route(
4170 bgp, afi, safi, p, pi);
4171 else /* SAFI_MPLS_VPN */
4172 vpn_leak_to_vrf_withdraw(bgp,
4173 pi);
d62a17ae 4174 }
4175 }
4176 }
718e3744 4177
d62a17ae 4178 /* Update to new attribute. */
40381db7
DS
4179 bgp_attr_unintern(&pi->attr);
4180 pi->attr = attr_new;
d62a17ae 4181
4182 /* Update MPLS label */
4183 if (has_valid_label) {
40381db7 4184 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4185 if (extra->label != label) {
4186 memcpy(&extra->label, label,
dbd587da 4187 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4188 extra->num_labels = num_labels;
4189 }
b57ba6d2
MK
4190 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4191 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4192 }
718e3744 4193
e496b420
HS
4194 /* Update SRv6 SID */
4195 if (attr->srv6_l3vpn) {
4196 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4197 if (sid_diff(&extra->sid[0].sid,
4198 &attr->srv6_l3vpn->sid)) {
4199 sid_copy(&extra->sid[0].sid,
e496b420
HS
4200 &attr->srv6_l3vpn->sid);
4201 extra->num_sids = 1;
cc8f05df 4202
16f3db2d
RS
4203 extra->sid[0].loc_block_len = 0;
4204 extra->sid[0].loc_node_len = 0;
4205 extra->sid[0].func_len = 0;
4206 extra->sid[0].arg_len = 0;
ea7cd161
RS
4207 extra->sid[0].transposition_len = 0;
4208 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4209
4210 if (attr->srv6_l3vpn->loc_block_len != 0) {
4211 extra->sid[0].loc_block_len =
4212 attr->srv6_l3vpn->loc_block_len;
4213 extra->sid[0].loc_node_len =
4214 attr->srv6_l3vpn->loc_node_len;
4215 extra->sid[0].func_len =
4216 attr->srv6_l3vpn->func_len;
4217 extra->sid[0].arg_len =
4218 attr->srv6_l3vpn->arg_len;
ea7cd161 4219 extra->sid[0].transposition_len =
cc8f05df 4220 attr->srv6_l3vpn
ea7cd161
RS
4221 ->transposition_len;
4222 extra->sid[0].transposition_offset =
cc8f05df 4223 attr->srv6_l3vpn
ea7cd161
RS
4224 ->transposition_offset;
4225 }
e496b420
HS
4226 }
4227 } else if (attr->srv6_vpn) {
4228 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4229 if (sid_diff(&extra->sid[0].sid,
4230 &attr->srv6_vpn->sid)) {
4231 sid_copy(&extra->sid[0].sid,
4232 &attr->srv6_vpn->sid);
e496b420
HS
4233 extra->num_sids = 1;
4234 }
4235 }
4236
49e5a4a0 4237#ifdef ENABLE_BGP_VNC
d62a17ae 4238 if ((afi == AFI_IP || afi == AFI_IP6)
4239 && (safi == SAFI_UNICAST)) {
4240 if (vnc_implicit_withdraw) {
4241 /*
4242 * Add back the route with its new attributes
4243 * (e.g., nexthop).
4244 * The route is still selected, until the route
4245 * selection
4246 * queued by bgp_process actually runs. We have
4247 * to make this
4248 * update to the VNC side immediately to avoid
4249 * racing against
4250 * configuration changes (e.g., route-map
4251 * changes) which
4252 * trigger re-importation of the entire RIB.
4253 */
40381db7
DS
4254 vnc_import_bgp_add_route(bgp, p, pi);
4255 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4256 }
4257 }
65efcfce
LB
4258#endif
4259
d62a17ae 4260 /* Update bgp route dampening information. */
b4f7f45b 4261 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4262 && peer->sort == BGP_PEER_EBGP) {
4263 /* Now we do normal update dampening. */
9bcb3eef 4264 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4265 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4266 bgp_dest_unlock_node(dest);
d62a17ae 4267 return 0;
4268 }
4269 }
128ea8ab 4270
d62a17ae 4271 /* Nexthop reachability check - for unicast and
4272 * labeled-unicast.. */
7c312383
AD
4273 if (((afi == AFI_IP || afi == AFI_IP6)
4274 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4275 || (safi == SAFI_EVPN &&
4276 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4277 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4278 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4279 && !CHECK_FLAG(peer->flags,
4280 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4281 && !CHECK_FLAG(bgp->flags,
4282 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4283 connected = 1;
4284 else
4285 connected = 0;
4286
960035b2
PZ
4287 struct bgp *bgp_nexthop = bgp;
4288
40381db7
DS
4289 if (pi->extra && pi->extra->bgp_orig)
4290 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4291
7c312383
AD
4292 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4293
4294 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4295 safi, pi, NULL, connected,
4296 p)
a4d82a8a 4297 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4298 bgp_path_info_set_flag(dest, pi,
4299 BGP_PATH_VALID);
d62a17ae 4300 else {
4301 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4302 zlog_debug("%s(%pI4): NH unresolved",
4303 __func__,
4304 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4305 }
9bcb3eef 4306 bgp_path_info_unset_flag(dest, pi,
18ee8310 4307 BGP_PATH_VALID);
d62a17ae 4308 }
4309 } else
9bcb3eef 4310 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4311
49e5a4a0 4312#ifdef ENABLE_BGP_VNC
d62a17ae 4313 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4314 struct bgp_dest *pdest = NULL;
d62a17ae 4315 struct bgp_table *table = NULL;
4316
9bcb3eef
DS
4317 pdest = bgp_node_get(bgp->rib[afi][safi],
4318 (struct prefix *)prd);
4319 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4320 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4321
4322 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4323 bgp, prd, table, p, pi);
d62a17ae 4324 }
9bcb3eef 4325 bgp_dest_unlock_node(pdest);
d62a17ae 4326 }
4327#endif
718e3744 4328
d62a17ae 4329 /* If this is an EVPN route and some attribute has changed,
9146341f 4330 * or we are explicitly told to perform a route import, process
d62a17ae 4331 * route for import. If the extended community has changed, we
4332 * would
4333 * have done the un-import earlier and the import would result
4334 * in the
4335 * route getting injected into appropriate L2 VNIs. If it is
4336 * just
4337 * some other attribute change, the import will result in
4338 * updating
4339 * the attributes for the route in the VNI(s).
4340 */
9146341f 4341 if (safi == SAFI_EVPN &&
4342 (!same_attr || force_evpn_import) &&
7c312383 4343 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4344 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4345
4346 /* Process change. */
40381db7 4347 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4348
9bcb3eef
DS
4349 bgp_process(bgp, dest, afi, safi);
4350 bgp_dest_unlock_node(dest);
558d1fec 4351
ddb5b488
PZ
4352 if (SAFI_UNICAST == safi
4353 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4354 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4355
40381db7 4356 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4357 }
4358 if ((SAFI_MPLS_VPN == safi)
4359 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4360
40381db7 4361 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4362 }
4363
49e5a4a0 4364#ifdef ENABLE_BGP_VNC
d62a17ae 4365 if (SAFI_MPLS_VPN == safi) {
4366 mpls_label_t label_decoded = decode_label(label);
28070ee3 4367
d62a17ae 4368 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4369 type, sub_type, &label_decoded);
4370 }
4371 if (SAFI_ENCAP == safi) {
4372 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4373 type, sub_type, NULL);
4374 }
28070ee3
PZ
4375#endif
4376
d62a17ae 4377 return 0;
4378 } // End of implicit withdraw
718e3744 4379
d62a17ae 4380 /* Received Logging. */
4381 if (bgp_debug_update(peer, p, NULL, 1)) {
4382 if (!peer->rcvd_attr_printed) {
f70c91dc 4383 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4384 peer->rcvd_attr_str);
4385 peer->rcvd_attr_printed = 1;
4386 }
718e3744 4387
a4d82a8a 4388 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4389 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4390 pfx_buf, sizeof(pfx_buf));
f70c91dc 4391 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4392 }
718e3744 4393
d62a17ae 4394 /* Make new BGP info. */
9bcb3eef 4395 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4396
d62a17ae 4397 /* Update MPLS label */
4398 if (has_valid_label) {
18ee8310 4399 extra = bgp_path_info_extra_get(new);
8ba71050 4400 if (extra->label != label) {
dbd587da
QY
4401 memcpy(&extra->label, label,
4402 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4403 extra->num_labels = num_labels;
4404 }
b57ba6d2
MK
4405 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4406 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4407 }
718e3744 4408
e496b420
HS
4409 /* Update SRv6 SID */
4410 if (safi == SAFI_MPLS_VPN) {
4411 extra = bgp_path_info_extra_get(new);
4412 if (attr->srv6_l3vpn) {
16f3db2d 4413 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4414 extra->num_sids = 1;
cc8f05df 4415
16f3db2d
RS
4416 extra->sid[0].loc_block_len =
4417 attr->srv6_l3vpn->loc_block_len;
4418 extra->sid[0].loc_node_len =
4419 attr->srv6_l3vpn->loc_node_len;
4420 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4421 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4422 extra->sid[0].transposition_len =
4423 attr->srv6_l3vpn->transposition_len;
4424 extra->sid[0].transposition_offset =
4425 attr->srv6_l3vpn->transposition_offset;
e496b420 4426 } else if (attr->srv6_vpn) {
16f3db2d 4427 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4428 extra->num_sids = 1;
4429 }
4430 }
4431
d62a17ae 4432 /* Nexthop reachability check. */
7c312383
AD
4433 if (((afi == AFI_IP || afi == AFI_IP6)
4434 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4435 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4436 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4437 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4438 && !CHECK_FLAG(peer->flags,
4439 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4440 && !CHECK_FLAG(bgp->flags,
4441 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4442 connected = 1;
4443 else
4444 connected = 0;
4445
7c312383
AD
4446 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4447
4053e952 4448 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4449 connected, p)
a4d82a8a 4450 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4451 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4452 else {
4453 if (BGP_DEBUG(nht, NHT)) {
4454 char buf1[INET6_ADDRSTRLEN];
4455 inet_ntop(AF_INET,
4456 (const void *)&attr_new->nexthop,
4457 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4458 zlog_debug("%s(%s): NH unresolved", __func__,
4459 buf1);
d62a17ae 4460 }
9bcb3eef 4461 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4462 }
4463 } else
9bcb3eef 4464 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4465
d62a17ae 4466 /* Addpath ID */
4467 new->addpath_rx_id = addpath_id;
4468
4469 /* Increment prefix */
4470 bgp_aggregate_increment(bgp, p, new, afi, safi);
4471
4472 /* Register new BGP information. */
9bcb3eef 4473 bgp_path_info_add(dest, new);
d62a17ae 4474
4475 /* route_node_get lock */
9bcb3eef 4476 bgp_dest_unlock_node(dest);
558d1fec 4477
49e5a4a0 4478#ifdef ENABLE_BGP_VNC
d62a17ae 4479 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4480 struct bgp_dest *pdest = NULL;
d62a17ae 4481 struct bgp_table *table = NULL;
4482
9bcb3eef
DS
4483 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4484 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4485 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4486
4487 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4488 bgp, prd, table, p, new);
4489 }
9bcb3eef 4490 bgp_dest_unlock_node(pdest);
d62a17ae 4491 }
65efcfce
LB
4492#endif
4493
d62a17ae 4494 /* If this is an EVPN route, process for import. */
7c312383 4495 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4496 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4497
9bcb3eef 4498 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4499
d62a17ae 4500 /* Process change. */
9bcb3eef 4501 bgp_process(bgp, dest, afi, safi);
718e3744 4502
ddb5b488
PZ
4503 if (SAFI_UNICAST == safi
4504 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4505 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4506 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4507 }
4508 if ((SAFI_MPLS_VPN == safi)
4509 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4510
4511 vpn_leak_to_vrf_update(bgp, new);
4512 }
49e5a4a0 4513#ifdef ENABLE_BGP_VNC
d62a17ae 4514 if (SAFI_MPLS_VPN == safi) {
4515 mpls_label_t label_decoded = decode_label(label);
28070ee3 4516
d62a17ae 4517 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4518 sub_type, &label_decoded);
4519 }
4520 if (SAFI_ENCAP == safi) {
4521 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4522 sub_type, NULL);
4523 }
28070ee3
PZ
4524#endif
4525
d62a17ae 4526 return 0;
718e3744 4527
d62a17ae 4528/* This BGP update is filtered. Log the reason then update BGP
4529 entry. */
4530filtered:
9bcb3eef 4531 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4532
d62a17ae 4533 if (bgp_debug_update(peer, p, NULL, 1)) {
4534 if (!peer->rcvd_attr_printed) {
f70c91dc 4535 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4536 peer->rcvd_attr_str);
4537 peer->rcvd_attr_printed = 1;
4538 }
718e3744 4539
a4d82a8a 4540 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4541 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4542 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4543 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4544 peer, pfx_buf, reason);
d62a17ae 4545 }
128ea8ab 4546
40381db7 4547 if (pi) {
d62a17ae 4548 /* If this is an EVPN route, un-import it as it is now filtered.
4549 */
4550 if (safi == SAFI_EVPN)
40381db7 4551 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4552
ddb5b488
PZ
4553 if (SAFI_UNICAST == safi
4554 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4555 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4556
40381db7 4557 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4558 }
4559 if ((SAFI_MPLS_VPN == safi)
4560 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4561
40381db7 4562 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4563 }
4564
9bcb3eef 4565 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4566 }
4567
9bcb3eef 4568 bgp_dest_unlock_node(dest);
558d1fec 4569
49e5a4a0 4570#ifdef ENABLE_BGP_VNC
d62a17ae 4571 /*
4572 * Filtered update is treated as an implicit withdrawal (see
4573 * bgp_rib_remove()
4574 * a few lines above)
4575 */
4576 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4577 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4578 0);
4579 }
97736e32
PZ
4580#endif
4581
d62a17ae 4582 return 0;
718e3744 4583}
4584
26a3ffd6 4585int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4586 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4587 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4588 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4589{
d62a17ae 4590 struct bgp *bgp;
4591 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4592 struct bgp_dest *dest;
40381db7 4593 struct bgp_path_info *pi;
718e3744 4594
49e5a4a0 4595#ifdef ENABLE_BGP_VNC
d62a17ae 4596 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4597 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4598 0);
4599 }
28070ee3
PZ
4600#endif
4601
d62a17ae 4602 bgp = peer->bgp;
4603
4604 /* Lookup node. */
9bcb3eef 4605 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4606
4607 /* If peer is soft reconfiguration enabled. Record input packet for
4608 * further calculation.
4609 *
4610 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4611 * routes that are filtered. This tanks out Quagga RS pretty badly due
4612 * to
4613 * the iteration over all RS clients.
4614 * Since we need to remove the entry from adj_in anyway, do that first
4615 * and
4616 * if there was no entry, we don't need to do anything more.
4617 */
4618 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4619 && peer != bgp->peer_self)
9bcb3eef 4620 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4621 peer->stat_pfx_dup_withdraw++;
4622
d62a17ae 4623 if (bgp_debug_update(peer, p, NULL, 1)) {
4624 bgp_debug_rdpfxpath2str(
a4d82a8a 4625 afi, safi, prd, p, label, num_labels,
6c995628
AD
4626 addpath_id ? 1 : 0, addpath_id, NULL,
4627 pfx_buf, sizeof(pfx_buf));
d62a17ae 4628 zlog_debug(
4629 "%s withdrawing route %s not in adj-in",
4630 peer->host, pfx_buf);
4631 }
9bcb3eef 4632 bgp_dest_unlock_node(dest);
d62a17ae 4633 return 0;
4634 }
cd808e74 4635
d62a17ae 4636 /* Lookup withdrawn route. */
9bcb3eef 4637 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4638 if (pi->peer == peer && pi->type == type
4639 && pi->sub_type == sub_type
4640 && pi->addpath_rx_id == addpath_id)
d62a17ae 4641 break;
4642
4643 /* Logging. */
4644 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4645 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4646 addpath_id ? 1 : 0, addpath_id, NULL,
4647 pfx_buf, sizeof(pfx_buf));
f70c91dc 4648 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4649 pfx_buf);
4650 }
718e3744 4651
d62a17ae 4652 /* Withdraw specified route from routing table. */
40381db7 4653 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4654 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4655 if (SAFI_UNICAST == safi
4656 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4657 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4658 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4659 }
4660 if ((SAFI_MPLS_VPN == safi)
4661 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4662
40381db7 4663 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4664 }
4665 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4666 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4667 addpath_id ? 1 : 0, addpath_id, NULL,
4668 pfx_buf, sizeof(pfx_buf));
d62a17ae 4669 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4670 }
718e3744 4671
d62a17ae 4672 /* Unlock bgp_node_get() lock. */
9bcb3eef 4673 bgp_dest_unlock_node(dest);
d62a17ae 4674
4675 return 0;
718e3744 4676}
6b0655a2 4677
d62a17ae 4678void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4679 int withdraw)
718e3744 4680{
d62a17ae 4681 struct update_subgroup *subgrp;
4682 subgrp = peer_subgroup(peer, afi, safi);
4683 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4684}
6182d65b 4685
718e3744 4686
3f9c7369
DS
4687/*
4688 * bgp_stop_announce_route_timer
4689 */
d62a17ae 4690void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4691{
d62a17ae 4692 if (!paf->t_announce_route)
4693 return;
4694
50478845 4695 thread_cancel(&paf->t_announce_route);
718e3744 4696}
6b0655a2 4697
3f9c7369
DS
4698/*
4699 * bgp_announce_route_timer_expired
4700 *
4701 * Callback that is invoked when the route announcement timer for a
4702 * peer_af expires.
4703 */
cc9f21da 4704static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4705{
d62a17ae 4706 struct peer_af *paf;
4707 struct peer *peer;
558d1fec 4708
d62a17ae 4709 paf = THREAD_ARG(t);
4710 peer = paf->peer;
718e3744 4711
feb17238 4712 if (!peer_established(peer))
cc9f21da 4713 return;
3f9c7369 4714
d62a17ae 4715 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4716 return;
3f9c7369 4717
d62a17ae 4718 peer_af_announce_route(paf, 1);
c5aec50b
MK
4719
4720 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4721 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4722}
4723
3f9c7369
DS
4724/*
4725 * bgp_announce_route
4726 *
4727 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4728 *
4729 * if force is true we will force an update even if the update
4730 * limiting code is attempted to kick in.
3f9c7369 4731 */
e1a32ec1 4732void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4733{
4734 struct peer_af *paf;
4735 struct update_subgroup *subgrp;
4736
4737 paf = peer_af_find(peer, afi, safi);
4738 if (!paf)
4739 return;
4740 subgrp = PAF_SUBGRP(paf);
4741
4742 /*
4743 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4744 * or a refresh has already been triggered.
4745 */
4746 if (!subgrp || paf->t_announce_route)
4747 return;
4748
e1a32ec1
DS
4749 if (force)
4750 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4751
d62a17ae 4752 /*
4753 * Start a timer to stagger/delay the announce. This serves
4754 * two purposes - announcement can potentially be combined for
4755 * multiple peers and the announcement doesn't happen in the
4756 * vty context.
4757 */
4758 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4759 (subgrp->peer_count == 1)
4760 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4761 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4762 &paf->t_announce_route);
3f9c7369
DS
4763}
4764
4765/*
4766 * Announce routes from all AF tables to a peer.
4767 *
4768 * This should ONLY be called when there is a need to refresh the
4769 * routes to the peer based on a policy change for this peer alone
4770 * or a route refresh request received from the peer.
4771 * The operation will result in splitting the peer from its existing
4772 * subgroups and putting it in new subgroups.
4773 */
d62a17ae 4774void bgp_announce_route_all(struct peer *peer)
718e3744 4775{
d62a17ae 4776 afi_t afi;
4777 safi_t safi;
4778
05c7a1cc 4779 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4780 bgp_announce_route(peer, afi, safi, false);
718e3744 4781}
6b0655a2 4782
46aeabed
LS
4783/* Flag or unflag bgp_dest to determine whether it should be treated by
4784 * bgp_soft_reconfig_table_task.
4785 * Flag if flag is true. Unflag if flag is false.
4786 */
4787static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4788{
4789 struct bgp_dest *dest;
4790 struct bgp_adj_in *ain;
4791
4792 if (!table)
4793 return;
4794
4795 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4796 for (ain = dest->adj_in; ain; ain = ain->next) {
4797 if (ain->peer != NULL)
4798 break;
4799 }
4800 if (flag && ain != NULL && ain->peer != NULL)
4801 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4802 else
4803 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4804 }
4805}
4806
4807static int bgp_soft_reconfig_table_update(struct peer *peer,
4808 struct bgp_dest *dest,
4809 struct bgp_adj_in *ain, afi_t afi,
4810 safi_t safi, struct prefix_rd *prd)
4811{
4812 struct bgp_path_info *pi;
4813 uint32_t num_labels = 0;
4814 mpls_label_t *label_pnt = NULL;
4815 struct bgp_route_evpn evpn;
4816
4817 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4818 if (pi->peer == peer)
4819 break;
4820
4821 if (pi && pi->extra)
4822 num_labels = pi->extra->num_labels;
4823 if (num_labels)
4824 label_pnt = &pi->extra->label[0];
4825 if (pi)
4826 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4827 sizeof(evpn));
4828 else
4829 memset(&evpn, 0, sizeof(evpn));
4830
4831 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4832 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4833 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4834 &evpn);
4835}
4836
d62a17ae 4837static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4838 struct bgp_table *table,
4839 struct prefix_rd *prd)
718e3744 4840{
d62a17ae 4841 int ret;
9bcb3eef 4842 struct bgp_dest *dest;
d62a17ae 4843 struct bgp_adj_in *ain;
718e3744 4844
d62a17ae 4845 if (!table)
4846 table = peer->bgp->rib[afi][safi];
718e3744 4847
9bcb3eef
DS
4848 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4849 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4850 if (ain->peer != peer)
4851 continue;
8692c506 4852
46aeabed
LS
4853 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4854 afi, safi, prd);
ea47320b
DL
4855
4856 if (ret < 0) {
9bcb3eef 4857 bgp_dest_unlock_node(dest);
ea47320b 4858 return;
d62a17ae 4859 }
4860 }
718e3744 4861}
4862
46aeabed
LS
4863/* Do soft reconfig table per bgp table.
4864 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4865 * when BGP_NODE_SOFT_RECONFIG is set,
4866 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4867 * Schedule a new thread to continue the job.
4868 * Without splitting the full job into several part,
4869 * vtysh waits for the job to finish before responding to a BGP command
4870 */
cc9f21da 4871static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
4872{
4873 uint32_t iter, max_iter;
4874 int ret;
4875 struct bgp_dest *dest;
4876 struct bgp_adj_in *ain;
4877 struct peer *peer;
4878 struct bgp_table *table;
4879 struct prefix_rd *prd;
4880 struct listnode *node, *nnode;
4881
4882 table = THREAD_ARG(thread);
4883 prd = NULL;
4884
4885 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4886 if (table->soft_reconfig_init) {
4887 /* first call of the function with a new srta structure.
4888 * Don't do any treatment this time on nodes
4889 * in order vtysh to respond quickly
4890 */
4891 max_iter = 0;
4892 }
4893
4894 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4895 dest = bgp_route_next(dest)) {
4896 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4897 continue;
4898
4899 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4900
4901 for (ain = dest->adj_in; ain; ain = ain->next) {
4902 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4903 nnode, peer)) {
4904 if (ain->peer != peer)
4905 continue;
4906
4907 ret = bgp_soft_reconfig_table_update(
4908 peer, dest, ain, table->afi,
4909 table->safi, prd);
4910 iter++;
4911
4912 if (ret < 0) {
4913 bgp_dest_unlock_node(dest);
4914 listnode_delete(
4915 table->soft_reconfig_peers,
4916 peer);
4917 bgp_announce_route(peer, table->afi,
e1a32ec1 4918 table->safi, false);
46aeabed
LS
4919 if (list_isempty(
4920 table->soft_reconfig_peers)) {
4921 list_delete(
4922 &table->soft_reconfig_peers);
4923 bgp_soft_reconfig_table_flag(
4924 table, false);
cc9f21da 4925 return;
46aeabed
LS
4926 }
4927 }
4928 }
4929 }
4930 }
4931
4932 /* we're either starting the initial iteration,
4933 * or we're going to continue an ongoing iteration
4934 */
4935 if (dest || table->soft_reconfig_init) {
4936 table->soft_reconfig_init = false;
4937 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4938 table, 0, &table->soft_reconfig_thread);
cc9f21da 4939 return;
46aeabed
LS
4940 }
4941 /* we're done, clean up the background iteration context info and
4942 schedule route annoucement
4943 */
4944 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4945 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 4946 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
4947 }
4948
4949 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
4950}
4951
4952
4953/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4954 * and peer.
4955 * - bgp cannot be NULL
4956 * - if table and peer are NULL, cancel all threads within the bgp instance
4957 * - if table is NULL and peer is not,
4958 * remove peer in all threads within the bgp instance
4959 * - if peer is NULL, cancel all threads matching table within the bgp instance
4960 */
4961void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4962 const struct bgp_table *table,
4963 const struct peer *peer)
4964{
4965 struct peer *npeer;
4966 struct listnode *node, *nnode;
4967 int afi, safi;
4968 struct bgp_table *ntable;
4969
4970 if (!bgp)
4971 return;
4972
4973 FOREACH_AFI_SAFI (afi, safi) {
4974 ntable = bgp->rib[afi][safi];
4975 if (!ntable)
4976 continue;
4977 if (table && table != ntable)
4978 continue;
4979
4980 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4981 npeer)) {
4982 if (peer && peer != npeer)
4983 continue;
4984 listnode_delete(ntable->soft_reconfig_peers, npeer);
4985 }
4986
4987 if (!ntable->soft_reconfig_peers
4988 || !list_isempty(ntable->soft_reconfig_peers))
4989 continue;
4990
4991 list_delete(&ntable->soft_reconfig_peers);
4992 bgp_soft_reconfig_table_flag(ntable, false);
4993 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4994 }
4995}
4996
d62a17ae 4997void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4998{
9bcb3eef 4999 struct bgp_dest *dest;
d62a17ae 5000 struct bgp_table *table;
46aeabed
LS
5001 struct listnode *node, *nnode;
5002 struct peer *npeer;
5003 struct peer_af *paf;
718e3744 5004
feb17238 5005 if (!peer_established(peer))
d62a17ae 5006 return;
718e3744 5007
d62a17ae 5008 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5009 && (safi != SAFI_EVPN)) {
5010 table = peer->bgp->rib[afi][safi];
5011 if (!table)
5012 return;
5013
5014 table->soft_reconfig_init = true;
5015
5016 if (!table->soft_reconfig_peers)
5017 table->soft_reconfig_peers = list_new();
5018 npeer = NULL;
5019 /* add peer to the table soft_reconfig_peers if not already
5020 * there
5021 */
5022 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5023 npeer)) {
5024 if (peer == npeer)
5025 break;
5026 }
5027 if (peer != npeer)
5028 listnode_add(table->soft_reconfig_peers, peer);
5029
5030 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5031 * on table would start back at the beginning.
5032 */
5033 bgp_soft_reconfig_table_flag(table, true);
5034
5035 if (!table->soft_reconfig_thread)
5036 thread_add_event(bm->master,
5037 bgp_soft_reconfig_table_task, table, 0,
5038 &table->soft_reconfig_thread);
5039 /* Cancel bgp_announce_route_timer_expired threads.
5040 * bgp_announce_route_timer_expired threads have been scheduled
5041 * to announce routes as soon as the soft_reconfigure process
5042 * finishes.
5043 * In this case, soft_reconfigure is also scheduled by using
5044 * a thread but is planned after the
5045 * bgp_announce_route_timer_expired threads. It means that,
5046 * without cancelling the threads, the route announcement task
5047 * would run before the soft reconfiguration one. That would
5048 * useless and would block vtysh during several seconds. Route
5049 * announcements are rescheduled as soon as the soft_reconfigure
5050 * process finishes.
5051 */
5052 paf = peer_af_find(peer, afi, safi);
5053 if (paf)
5054 bgp_stop_announce_route_timer(paf);
5055 } else
9bcb3eef
DS
5056 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5057 dest = bgp_route_next(dest)) {
5058 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5059
b54892e0
DS
5060 if (table == NULL)
5061 continue;
8692c506 5062
9bcb3eef 5063 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5064 struct prefix_rd prd;
5065
5066 prd.family = AF_UNSPEC;
5067 prd.prefixlen = 64;
5068 memcpy(&prd.val, p->u.val, 8);
5069
5070 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5071 }
718e3744 5072}
6b0655a2 5073
228da428 5074
d62a17ae 5075struct bgp_clear_node_queue {
9bcb3eef 5076 struct bgp_dest *dest;
228da428
CC
5077};
5078
d62a17ae 5079static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5080{
d62a17ae 5081 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5082 struct bgp_dest *dest = cnq->dest;
d62a17ae 5083 struct peer *peer = wq->spec.data;
40381db7 5084 struct bgp_path_info *pi;
3103e8d2 5085 struct bgp *bgp;
9bcb3eef
DS
5086 afi_t afi = bgp_dest_table(dest)->afi;
5087 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5088
9bcb3eef 5089 assert(dest && peer);
3103e8d2 5090 bgp = peer->bgp;
d62a17ae 5091
5092 /* It is possible that we have multiple paths for a prefix from a peer
5093 * if that peer is using AddPath.
5094 */
9bcb3eef 5095 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5096 if (pi->peer != peer)
ea47320b
DL
5097 continue;
5098
5099 /* graceful restart STALE flag set. */
9af52ccf
DA
5100 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5101 && peer->nsf[afi][safi])
5102 || CHECK_FLAG(peer->af_sflags[afi][safi],
5103 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5104 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5105 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5106 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5107 else {
5108 /* If this is an EVPN route, process for
5109 * un-import. */
5110 if (safi == SAFI_EVPN)
9bcb3eef
DS
5111 bgp_evpn_unimport_route(
5112 bgp, afi, safi,
5113 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5114 /* Handle withdraw for VRF route-leaking and L3VPN */
5115 if (SAFI_UNICAST == safi
5116 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5117 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5118 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5119 bgp, pi);
960035b2 5120 }
3103e8d2 5121 if (SAFI_MPLS_VPN == safi &&
960035b2 5122 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5123 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5124 }
3103e8d2 5125
9bcb3eef 5126 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5127 }
ea47320b 5128 }
d62a17ae 5129 return WQ_SUCCESS;
200df115 5130}
5131
d62a17ae 5132static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5133{
d62a17ae 5134 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5135 struct bgp_dest *dest = cnq->dest;
5136 struct bgp_table *table = bgp_dest_table(dest);
228da428 5137
9bcb3eef 5138 bgp_dest_unlock_node(dest);
d62a17ae 5139 bgp_table_unlock(table);
5140 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5141}
5142
d62a17ae 5143static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5144{
d62a17ae 5145 struct peer *peer = wq->spec.data;
64e580a7 5146
d62a17ae 5147 /* Tickle FSM to start moving again */
5148 BGP_EVENT_ADD(peer, Clearing_Completed);
5149
5150 peer_unlock(peer); /* bgp_clear_route */
200df115 5151}
718e3744 5152
d62a17ae 5153static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5154{
d62a17ae 5155 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5156
5157 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5158#undef CLEAR_QUEUE_NAME_LEN
5159
0ce1ca80 5160 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5161 peer->clear_node_queue->spec.hold = 10;
5162 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5163 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5164 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5165 peer->clear_node_queue->spec.max_retries = 0;
5166
5167 /* we only 'lock' this peer reference when the queue is actually active
5168 */
5169 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5170}
5171
d62a17ae 5172static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5173 struct bgp_table *table)
65ca75e0 5174{
9bcb3eef 5175 struct bgp_dest *dest;
b6c386bb 5176 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5177
d62a17ae 5178 if (!table)
5179 table = peer->bgp->rib[afi][safi];
dc83d712 5180
d62a17ae 5181 /* If still no table => afi/safi isn't configured at all or smth. */
5182 if (!table)
5183 return;
dc83d712 5184
9bcb3eef 5185 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5186 struct bgp_path_info *pi, *next;
d62a17ae 5187 struct bgp_adj_in *ain;
5188 struct bgp_adj_in *ain_next;
5189
5190 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5191 * queued for every clearing peer, regardless of whether it is
5192 * relevant to the peer at hand.
5193 *
5194 * Overview: There are 3 different indices which need to be
5195 * scrubbed, potentially, when a peer is removed:
5196 *
5197 * 1 peer's routes visible via the RIB (ie accepted routes)
5198 * 2 peer's routes visible by the (optional) peer's adj-in index
5199 * 3 other routes visible by the peer's adj-out index
5200 *
5201 * 3 there is no hurry in scrubbing, once the struct peer is
5202 * removed from bgp->peer, we could just GC such deleted peer's
5203 * adj-outs at our leisure.
5204 *
5205 * 1 and 2 must be 'scrubbed' in some way, at least made
5206 * invisible via RIB index before peer session is allowed to be
5207 * brought back up. So one needs to know when such a 'search' is
5208 * complete.
5209 *
5210 * Ideally:
5211 *
5212 * - there'd be a single global queue or a single RIB walker
5213 * - rather than tracking which route_nodes still need to be
5214 * examined on a peer basis, we'd track which peers still
5215 * aren't cleared
5216 *
5217 * Given that our per-peer prefix-counts now should be reliable,
5218 * this may actually be achievable. It doesn't seem to be a huge
5219 * problem at this time,
5220 *
5221 * It is possible that we have multiple paths for a prefix from
5222 * a peer
5223 * if that peer is using AddPath.
5224 */
9bcb3eef 5225 ain = dest->adj_in;
d62a17ae 5226 while (ain) {
5227 ain_next = ain->next;
5228
6a840fd9 5229 if (ain->peer == peer)
9bcb3eef 5230 bgp_adj_in_remove(dest, ain);
d62a17ae 5231
5232 ain = ain_next;
5233 }
5234
9bcb3eef 5235 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5236 next = pi->next;
5237 if (pi->peer != peer)
d62a17ae 5238 continue;
5239
5240 if (force)
9bcb3eef 5241 bgp_path_info_reap(dest, pi);
d62a17ae 5242 else {
5243 struct bgp_clear_node_queue *cnq;
5244
5245 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5246 bgp_table_lock(bgp_dest_table(dest));
5247 bgp_dest_lock_node(dest);
d62a17ae 5248 cnq = XCALLOC(
5249 MTYPE_BGP_CLEAR_NODE_QUEUE,
5250 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5251 cnq->dest = dest;
d62a17ae 5252 work_queue_add(peer->clear_node_queue, cnq);
5253 break;
5254 }
5255 }
5256 }
5257 return;
5258}
5259
5260void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5261{
9bcb3eef 5262 struct bgp_dest *dest;
d62a17ae 5263 struct bgp_table *table;
5264
5265 if (peer->clear_node_queue == NULL)
5266 bgp_clear_node_queue_init(peer);
5267
5268 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5269 * Idle until it receives a Clearing_Completed event. This protects
5270 * against peers which flap faster than we can we clear, which could
5271 * lead to:
5272 *
5273 * a) race with routes from the new session being installed before
5274 * clear_route_node visits the node (to delete the route of that
5275 * peer)
5276 * b) resource exhaustion, clear_route_node likely leads to an entry
5277 * on the process_main queue. Fast-flapping could cause that queue
5278 * to grow and grow.
5279 */
5280
5281 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5282 * the unlock will happen upon work-queue completion; other wise, the
5283 * unlock happens at the end of this function.
5284 */
5285 if (!peer->clear_node_queue->thread)
5286 peer_lock(peer);
5287
5288 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5289 bgp_clear_route_table(peer, afi, safi, NULL);
5290 else
9bcb3eef
DS
5291 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5292 dest = bgp_route_next(dest)) {
5293 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5294 if (!table)
5295 continue;
5296
5297 bgp_clear_route_table(peer, afi, safi, table);
5298 }
d62a17ae 5299
5300 /* unlock if no nodes got added to the clear-node-queue. */
5301 if (!peer->clear_node_queue->thread)
5302 peer_unlock(peer);
718e3744 5303}
d62a17ae 5304
5305void bgp_clear_route_all(struct peer *peer)
718e3744 5306{
d62a17ae 5307 afi_t afi;
5308 safi_t safi;
718e3744 5309
05c7a1cc
QY
5310 FOREACH_AFI_SAFI (afi, safi)
5311 bgp_clear_route(peer, afi, safi);
65efcfce 5312
49e5a4a0 5313#ifdef ENABLE_BGP_VNC
d62a17ae 5314 rfapiProcessPeerDown(peer);
65efcfce 5315#endif
718e3744 5316}
5317
d62a17ae 5318void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5319{
d62a17ae 5320 struct bgp_table *table;
9bcb3eef 5321 struct bgp_dest *dest;
d62a17ae 5322 struct bgp_adj_in *ain;
5323 struct bgp_adj_in *ain_next;
718e3744 5324
d62a17ae 5325 table = peer->bgp->rib[afi][safi];
718e3744 5326
d62a17ae 5327 /* It is possible that we have multiple paths for a prefix from a peer
5328 * if that peer is using AddPath.
5329 */
9bcb3eef
DS
5330 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5331 ain = dest->adj_in;
43143c8f 5332
d62a17ae 5333 while (ain) {
5334 ain_next = ain->next;
43143c8f 5335
6a840fd9 5336 if (ain->peer == peer)
9bcb3eef 5337 bgp_adj_in_remove(dest, ain);
43143c8f 5338
d62a17ae 5339 ain = ain_next;
5340 }
5341 }
718e3744 5342}
93406d87 5343
1479ed2f
DA
5344/* If any of the routes from the peer have been marked with the NO_LLGR
5345 * community, either as sent by the peer, or as the result of a configured
5346 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5347 * operation of [RFC4271].
5348 */
d62a17ae 5349void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5350{
9bcb3eef 5351 struct bgp_dest *dest;
40381db7 5352 struct bgp_path_info *pi;
d62a17ae 5353 struct bgp_table *table;
5354
9af52ccf 5355 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5356 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5357 dest = bgp_route_next(dest)) {
5358 struct bgp_dest *rm;
d62a17ae 5359
5360 /* look for neighbor in tables */
9bcb3eef 5361 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5362 if (!table)
ea47320b
DL
5363 continue;
5364
5365 for (rm = bgp_table_top(table); rm;
5366 rm = bgp_route_next(rm))
9bcb3eef 5367 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5368 pi = pi->next) {
40381db7 5369 if (pi->peer != peer)
ea47320b 5370 continue;
1479ed2f
DA
5371 if (CHECK_FLAG(
5372 peer->af_sflags[afi][safi],
5373 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5374 bgp_attr_get_community(pi->attr) &&
1479ed2f 5375 !community_include(
9a706b42
DA
5376 bgp_attr_get_community(
5377 pi->attr),
1479ed2f 5378 COMMUNITY_NO_LLGR))
e3015d91 5379 continue;
40381db7 5380 if (!CHECK_FLAG(pi->flags,
1defdda8 5381 BGP_PATH_STALE))
e3015d91 5382 continue;
ea47320b 5383
641065d4
KM
5384 /*
5385 * If this is VRF leaked route
5386 * process for withdraw.
5387 */
5388 if (pi->sub_type ==
5389 BGP_ROUTE_IMPORTED &&
5390 peer->bgp->inst_type ==
5391 BGP_INSTANCE_TYPE_DEFAULT)
5392 vpn_leak_to_vrf_withdraw(
5393 peer->bgp, pi);
5394
40381db7 5395 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5396 break;
5397 }
d62a17ae 5398 }
5399 } else {
9bcb3eef
DS
5400 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5401 dest = bgp_route_next(dest))
5402 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5403 pi = pi->next) {
40381db7 5404 if (pi->peer != peer)
ea47320b 5405 continue;
1479ed2f
DA
5406 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5407 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5408 bgp_attr_get_community(pi->attr) &&
5409 !community_include(
5410 bgp_attr_get_community(pi->attr),
5411 COMMUNITY_NO_LLGR))
e3015d91 5412 continue;
40381db7 5413 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5414 continue;
641065d4
KM
5415 if (safi == SAFI_UNICAST &&
5416 (peer->bgp->inst_type ==
5417 BGP_INSTANCE_TYPE_VRF ||
5418 peer->bgp->inst_type ==
5419 BGP_INSTANCE_TYPE_DEFAULT))
5420 vpn_leak_from_vrf_withdraw(
5421 bgp_get_default(), peer->bgp,
5422 pi);
5423
9bcb3eef 5424 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5425 break;
5426 }
d62a17ae 5427 }
93406d87 5428}
6b0655a2 5429
9af52ccf
DA
5430void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5431{
5432 struct bgp_dest *dest, *ndest;
5433 struct bgp_path_info *pi;
5434 struct bgp_table *table;
5435
5436 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5437 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5438 dest = bgp_route_next(dest)) {
5439 table = bgp_dest_get_bgp_table_info(dest);
5440 if (!table)
5441 continue;
5442
5443 for (ndest = bgp_table_top(table); ndest;
5444 ndest = bgp_route_next(ndest)) {
5445 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5446 pi = pi->next) {
5447 if (pi->peer != peer)
5448 continue;
5449
5450 if ((CHECK_FLAG(
5451 peer->af_sflags[afi][safi],
5452 PEER_STATUS_ENHANCED_REFRESH))
5453 && !CHECK_FLAG(pi->flags,
5454 BGP_PATH_STALE)
5455 && !CHECK_FLAG(
5456 pi->flags,
5457 BGP_PATH_UNUSEABLE)) {
5458 if (bgp_debug_neighbor_events(
5459 peer))
5460 zlog_debug(
5461 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5462 peer->host,
5463 afi2str(afi),
5464 safi2str(safi),
5465 bgp_dest_get_prefix(
5466 ndest));
5467
5468 bgp_path_info_set_flag(
5469 ndest, pi,
5470 BGP_PATH_STALE);
5471 }
5472 }
5473 }
5474 }
5475 } else {
5476 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5477 dest = bgp_route_next(dest)) {
5478 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5479 pi = pi->next) {
5480 if (pi->peer != peer)
5481 continue;
5482
5483 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5484 PEER_STATUS_ENHANCED_REFRESH))
5485 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5486 && !CHECK_FLAG(pi->flags,
5487 BGP_PATH_UNUSEABLE)) {
5488 if (bgp_debug_neighbor_events(peer))
5489 zlog_debug(
5490 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5491 peer->host,
5492 afi2str(afi),
5493 safi2str(safi),
5494 bgp_dest_get_prefix(
5495 dest));
5496
5497 bgp_path_info_set_flag(dest, pi,
5498 BGP_PATH_STALE);
5499 }
5500 }
5501 }
5502 }
5503}
5504
3dc339cd 5505bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5506{
e0df4c04 5507 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5508 return true;
e0df4c04 5509
9dac9fc8
DA
5510 if (peer->sort == BGP_PEER_EBGP
5511 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5512 || FILTER_LIST_OUT_NAME(filter)
5513 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5514 return true;
5515 return false;
9dac9fc8
DA
5516}
5517
3dc339cd 5518bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5519{
e0df4c04 5520 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5521 return true;
e0df4c04 5522
9dac9fc8
DA
5523 if (peer->sort == BGP_PEER_EBGP
5524 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5525 || FILTER_LIST_IN_NAME(filter)
5526 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5527 return true;
5528 return false;
9dac9fc8
DA
5529}
5530
568e10ca 5531static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5532 safi_t safi)
bb86c601 5533{
9bcb3eef 5534 struct bgp_dest *dest;
40381db7 5535 struct bgp_path_info *pi;
4b7e6066 5536 struct bgp_path_info *next;
bb86c601 5537
9bcb3eef
DS
5538 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5539 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5540 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5541
40381db7 5542 next = pi->next;
1b7bb747
CS
5543
5544 /* Unimport EVPN routes from VRFs */
5545 if (safi == SAFI_EVPN)
5546 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5547 SAFI_EVPN, p, pi);
1b7bb747 5548
40381db7
DS
5549 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5550 && pi->type == ZEBRA_ROUTE_BGP
5551 && (pi->sub_type == BGP_ROUTE_NORMAL
5552 || pi->sub_type == BGP_ROUTE_AGGREGATE
5553 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5554
d62a17ae 5555 if (bgp_fibupd_safi(safi))
b54892e0 5556 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5557 }
9514b37d 5558
9bcb3eef 5559 bgp_path_info_reap(dest, pi);
d62a17ae 5560 }
bb86c601
LB
5561}
5562
718e3744 5563/* Delete all kernel routes. */
d62a17ae 5564void bgp_cleanup_routes(struct bgp *bgp)
5565{
5566 afi_t afi;
9bcb3eef 5567 struct bgp_dest *dest;
67009e22 5568 struct bgp_table *table;
d62a17ae 5569
5570 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5571 if (afi == AFI_L2VPN)
5572 continue;
568e10ca 5573 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5574 SAFI_UNICAST);
d62a17ae 5575 /*
5576 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5577 */
5578 if (afi != AFI_L2VPN) {
5579 safi_t safi;
5580 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5581 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5582 dest = bgp_route_next(dest)) {
5583 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5584 if (table != NULL) {
5585 bgp_cleanup_table(bgp, table, safi);
5586 bgp_table_finish(&table);
9bcb3eef
DS
5587 bgp_dest_set_bgp_table_info(dest, NULL);
5588 bgp_dest_unlock_node(dest);
d62a17ae 5589 }
5590 }
5591 safi = SAFI_ENCAP;
9bcb3eef
DS
5592 for (dest = bgp_table_top(bgp->rib[afi][safi]); 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);
5597 bgp_table_finish(&table);
9bcb3eef
DS
5598 bgp_dest_set_bgp_table_info(dest, NULL);
5599 bgp_dest_unlock_node(dest);
d62a17ae 5600 }
5601 }
5602 }
5603 }
9bcb3eef
DS
5604 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5605 dest = bgp_route_next(dest)) {
5606 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5607 if (table != NULL) {
5608 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5609 bgp_table_finish(&table);
9bcb3eef
DS
5610 bgp_dest_set_bgp_table_info(dest, NULL);
5611 bgp_dest_unlock_node(dest);
d62a17ae 5612 }
bb86c601 5613 }
718e3744 5614}
5615
d62a17ae 5616void bgp_reset(void)
718e3744 5617{
d62a17ae 5618 vty_reset();
5619 bgp_zclient_reset();
5620 access_list_reset();
5621 prefix_list_reset();
718e3744 5622}
6b0655a2 5623
be92fc9f 5624bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5625{
d62a17ae 5626 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5627 && CHECK_FLAG(peer->af_cap[afi][safi],
5628 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5629}
5630
718e3744 5631/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5632 value. */
d62a17ae 5633int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5634 struct bgp_nlri *packet)
5635{
d7c0a89a
QY
5636 uint8_t *pnt;
5637 uint8_t *lim;
d62a17ae 5638 struct prefix p;
5639 int psize;
5640 int ret;
5641 afi_t afi;
5642 safi_t safi;
be92fc9f 5643 bool addpath_capable;
d7c0a89a 5644 uint32_t addpath_id;
d62a17ae 5645
d62a17ae 5646 pnt = packet->nlri;
5647 lim = pnt + packet->length;
5648 afi = packet->afi;
5649 safi = packet->safi;
5650 addpath_id = 0;
be92fc9f 5651 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5652
5653 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5654 syntactic validity. If the field is syntactically incorrect,
5655 then the Error Subcode is set to Invalid Network Field. */
5656 for (; pnt < lim; pnt += psize) {
5657 /* Clear prefix structure. */
6006b807 5658 memset(&p, 0, sizeof(p));
d62a17ae 5659
be92fc9f 5660 if (addpath_capable) {
d62a17ae 5661
5662 /* When packet overflow occurs return immediately. */
761ed665 5663 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5664 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5665
a3a850a1 5666 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5667 addpath_id = ntohl(addpath_id);
d62a17ae 5668 pnt += BGP_ADDPATH_ID_LEN;
5669 }
718e3744 5670
d62a17ae 5671 /* Fetch prefix length. */
5672 p.prefixlen = *pnt++;
5673 /* afi/safi validity already verified by caller,
5674 * bgp_update_receive */
5675 p.family = afi2family(afi);
5676
5677 /* Prefix length check. */
5678 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5679 flog_err(
e50f7cfd 5680 EC_BGP_UPDATE_RCV,
14454c9f 5681 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5682 peer->host, p.prefixlen, packet->afi);
513386b5 5683 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5684 }
6b0655a2 5685
d62a17ae 5686 /* Packet size overflow check. */
5687 psize = PSIZE(p.prefixlen);
5688
5689 /* When packet overflow occur return immediately. */
5690 if (pnt + psize > lim) {
af4c2728 5691 flog_err(
e50f7cfd 5692 EC_BGP_UPDATE_RCV,
d62a17ae 5693 "%s [Error] Update packet error (prefix length %d overflows packet)",
5694 peer->host, p.prefixlen);
513386b5 5695 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5696 }
5697
5698 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5699 * prefix for the v4 and v6 afi's and unicast/multicast */
5700 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5701 flog_err(
e50f7cfd 5702 EC_BGP_UPDATE_RCV,
d62a17ae 5703 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5704 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5705 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5706 }
5707
5708 /* Fetch prefix from NLRI packet. */
a85297a7 5709 memcpy(p.u.val, pnt, psize);
d62a17ae 5710
5711 /* Check address. */
5712 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5713 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5714 /* From RFC4271 Section 6.3:
5715 *
5716 * If a prefix in the NLRI field is semantically
5717 * incorrect
5718 * (e.g., an unexpected multicast IP address),
5719 * an error SHOULD
5720 * be logged locally, and the prefix SHOULD be
5721 * ignored.
a4d82a8a 5722 */
af4c2728 5723 flog_err(
e50f7cfd 5724 EC_BGP_UPDATE_RCV,
23d0a753
DA
5725 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5726 peer->host, &p.u.prefix4);
d62a17ae 5727 continue;
5728 }
5729 }
5730
5731 /* Check address. */
5732 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5733 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5734 flog_err(
e50f7cfd 5735 EC_BGP_UPDATE_RCV,
c0d72166
DS
5736 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5737 peer->host, &p.u.prefix6);
d62a17ae 5738
5739 continue;
5740 }
5741 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5742 flog_err(
e50f7cfd 5743 EC_BGP_UPDATE_RCV,
c0d72166
DS
5744 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5745 peer->host, &p.u.prefix6);
d62a17ae 5746
5747 continue;
5748 }
5749 }
5750
5751 /* Normal process. */
5752 if (attr)
5753 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5754 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5755 NULL, NULL, 0, 0, NULL);
d62a17ae 5756 else
5757 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5758 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5759 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5760 NULL);
d62a17ae 5761
513386b5
DA
5762 /* Do not send BGP notification twice when maximum-prefix count
5763 * overflow. */
5764 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5765 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5766
5767 /* Address family configuration mismatch. */
d62a17ae 5768 if (ret < 0)
513386b5 5769 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5770 }
5771
5772 /* Packet length consistency check. */
5773 if (pnt != lim) {
af4c2728 5774 flog_err(
e50f7cfd 5775 EC_BGP_UPDATE_RCV,
d62a17ae 5776 "%s [Error] Update packet error (prefix length mismatch with total length)",
5777 peer->host);
513386b5 5778 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5779 }
6b0655a2 5780
513386b5 5781 return BGP_NLRI_PARSE_OK;
718e3744 5782}
5783
d62a17ae 5784static struct bgp_static *bgp_static_new(void)
718e3744 5785{
d62a17ae 5786 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5787}
5788
d62a17ae 5789static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5790{
0a22ddfb 5791 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5792 route_map_counter_decrement(bgp_static->rmap.map);
5793
0a22ddfb 5794 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5795 XFREE(MTYPE_BGP_STATIC, bgp_static);
5796}
5797
5f040085 5798void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5799 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5800{
9bcb3eef 5801 struct bgp_dest *dest;
40381db7 5802 struct bgp_path_info *pi;
4b7e6066 5803 struct bgp_path_info *new;
40381db7 5804 struct bgp_path_info rmap_path;
d62a17ae 5805 struct attr attr;
5806 struct attr *attr_new;
b68885f9 5807 route_map_result_t ret;
49e5a4a0 5808#ifdef ENABLE_BGP_VNC
d62a17ae 5809 int vnc_implicit_withdraw = 0;
65efcfce 5810#endif
fee0f4c6 5811
d62a17ae 5812 assert(bgp_static);
dd8103a9 5813
9bcb3eef 5814 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5815
0f05ea43 5816 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 5817
d62a17ae 5818 attr.nexthop = bgp_static->igpnexthop;
5819 attr.med = bgp_static->igpmetric;
5820 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5821
d62a17ae 5822 if (bgp_static->atomic)
5823 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5824
d62a17ae 5825 /* Store label index, if required. */
5826 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5827 attr.label_index = bgp_static->label_index;
5828 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5829 }
718e3744 5830
d62a17ae 5831 /* Apply route-map. */
5832 if (bgp_static->rmap.name) {
5833 struct attr attr_tmp = attr;
80ced710 5834
6006b807 5835 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
5836 rmap_path.peer = bgp->peer_self;
5837 rmap_path.attr = &attr_tmp;
fee0f4c6 5838
d62a17ae 5839 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5840
1782514f 5841 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5842
d62a17ae 5843 bgp->peer_self->rmap_type = 0;
718e3744 5844
d62a17ae 5845 if (ret == RMAP_DENYMATCH) {
5846 /* Free uninterned attribute. */
5847 bgp_attr_flush(&attr_tmp);
718e3744 5848
d62a17ae 5849 /* Unintern original. */
5850 aspath_unintern(&attr.aspath);
5851 bgp_static_withdraw(bgp, p, afi, safi);
5852 return;
5853 }
7f323236 5854
637e5ba4 5855 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5856 bgp_attr_add_gshut_community(&attr_tmp);
5857
d62a17ae 5858 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5859 } else {
5860
637e5ba4 5861 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5862 bgp_attr_add_gshut_community(&attr);
5863
d62a17ae 5864 attr_new = bgp_attr_intern(&attr);
7f323236 5865 }
718e3744 5866
9bcb3eef 5867 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5868 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5869 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5870 break;
5871
40381db7
DS
5872 if (pi) {
5873 if (attrhash_cmp(pi->attr, attr_new)
5874 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5875 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5876 bgp_dest_unlock_node(dest);
d62a17ae 5877 bgp_attr_unintern(&attr_new);
5878 aspath_unintern(&attr.aspath);
5879 return;
5880 } else {
5881 /* The attribute is changed. */
9bcb3eef 5882 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5883
5884 /* Rewrite BGP route information. */
40381db7 5885 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5886 bgp_path_info_restore(dest, pi);
d62a17ae 5887 else
40381db7 5888 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5889#ifdef ENABLE_BGP_VNC
d62a17ae 5890 if ((afi == AFI_IP || afi == AFI_IP6)
5891 && (safi == SAFI_UNICAST)) {
40381db7 5892 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5893 /*
5894 * Implicit withdraw case.
40381db7 5895 * We have to do this before pi is
d62a17ae 5896 * changed
5897 */
5898 ++vnc_implicit_withdraw;
40381db7 5899 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5900 vnc_import_bgp_exterior_del_route(
40381db7 5901 bgp, p, pi);
d62a17ae 5902 }
5903 }
65efcfce 5904#endif
40381db7
DS
5905 bgp_attr_unintern(&pi->attr);
5906 pi->attr = attr_new;
5907 pi->uptime = bgp_clock();
49e5a4a0 5908#ifdef ENABLE_BGP_VNC
d62a17ae 5909 if ((afi == AFI_IP || afi == AFI_IP6)
5910 && (safi == SAFI_UNICAST)) {
5911 if (vnc_implicit_withdraw) {
40381db7 5912 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5913 vnc_import_bgp_exterior_add_route(
40381db7 5914 bgp, p, pi);
d62a17ae 5915 }
5916 }
65efcfce 5917#endif
718e3744 5918
d62a17ae 5919 /* Nexthop reachability check. */
892fedb6 5920 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5921 && (safi == SAFI_UNICAST
5922 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5923
5924 struct bgp *bgp_nexthop = bgp;
5925
40381db7
DS
5926 if (pi->extra && pi->extra->bgp_orig)
5927 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5928
5929 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5930 afi, safi, pi, NULL,
654a5978 5931 0, p))
9bcb3eef 5932 bgp_path_info_set_flag(dest, pi,
18ee8310 5933 BGP_PATH_VALID);
d62a17ae 5934 else {
5935 if (BGP_DEBUG(nht, NHT)) {
5936 char buf1[INET6_ADDRSTRLEN];
5937 inet_ntop(p->family,
5938 &p->u.prefix, buf1,
5939 INET6_ADDRSTRLEN);
5940 zlog_debug(
5941 "%s(%s): Route not in table, not advertising",
15569c58 5942 __func__, buf1);
d62a17ae 5943 }
18ee8310 5944 bgp_path_info_unset_flag(
9bcb3eef 5945 dest, pi, BGP_PATH_VALID);
d62a17ae 5946 }
5947 } else {
5948 /* Delete the NHT structure if any, if we're
5949 * toggling between
5950 * enabling/disabling import check. We
5951 * deregister the route
5952 * from NHT to avoid overloading NHT and the
5953 * process interaction
5954 */
40381db7 5955 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5956 bgp_path_info_set_flag(dest, pi,
5957 BGP_PATH_VALID);
d62a17ae 5958 }
5959 /* Process change. */
40381db7 5960 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5961 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5962
5963 if (SAFI_UNICAST == safi
5964 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5965 || bgp->inst_type
5966 == BGP_INSTANCE_TYPE_DEFAULT)) {
5967 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5968 pi);
ddb5b488
PZ
5969 }
5970
9bcb3eef 5971 bgp_dest_unlock_node(dest);
d62a17ae 5972 aspath_unintern(&attr.aspath);
5973 return;
5974 }
718e3744 5975 }
718e3744 5976
d62a17ae 5977 /* Make new BGP info. */
5978 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5979 attr_new, dest);
d62a17ae 5980 /* Nexthop reachability check. */
892fedb6 5981 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5982 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5983 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5984 p))
9bcb3eef 5985 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5986 else {
5987 if (BGP_DEBUG(nht, NHT)) {
5988 char buf1[INET6_ADDRSTRLEN];
5989 inet_ntop(p->family, &p->u.prefix, buf1,
5990 INET6_ADDRSTRLEN);
5991 zlog_debug(
5992 "%s(%s): Route not in table, not advertising",
15569c58 5993 __func__, buf1);
d62a17ae 5994 }
9bcb3eef 5995 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5996 }
5997 } else {
5998 /* Delete the NHT structure if any, if we're toggling between
5999 * enabling/disabling import check. We deregister the route
6000 * from NHT to avoid overloading NHT and the process interaction
6001 */
6002 bgp_unlink_nexthop(new);
6003
9bcb3eef 6004 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6005 }
078430f6 6006
d62a17ae 6007 /* Aggregate address increment. */
6008 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6009
d62a17ae 6010 /* Register new BGP information. */
9bcb3eef 6011 bgp_path_info_add(dest, new);
718e3744 6012
d62a17ae 6013 /* route_node_get lock */
9bcb3eef 6014 bgp_dest_unlock_node(dest);
d62a17ae 6015
6016 /* Process change. */
9bcb3eef 6017 bgp_process(bgp, dest, afi, safi);
d62a17ae 6018
ddb5b488
PZ
6019 if (SAFI_UNICAST == safi
6020 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6021 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6022 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6023 }
6024
d62a17ae 6025 /* Unintern original. */
6026 aspath_unintern(&attr.aspath);
718e3744 6027}
6028
5f040085 6029void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6030 safi_t safi)
718e3744 6031{
9bcb3eef 6032 struct bgp_dest *dest;
40381db7 6033 struct bgp_path_info *pi;
718e3744 6034
9bcb3eef 6035 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6036
d62a17ae 6037 /* Check selected route and self inserted route. */
9bcb3eef 6038 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6039 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6040 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6041 break;
6042
6043 /* Withdraw static BGP route from routing table. */
40381db7 6044 if (pi) {
ddb5b488
PZ
6045 if (SAFI_UNICAST == safi
6046 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6047 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6048 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6049 }
40381db7
DS
6050 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6051 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6052 bgp_path_info_delete(dest, pi);
6053 bgp_process(bgp, dest, afi, safi);
d62a17ae 6054 }
718e3744 6055
d62a17ae 6056 /* Unlock bgp_node_lookup. */
9bcb3eef 6057 bgp_dest_unlock_node(dest);
718e3744 6058}
6059
137446f9
LB
6060/*
6061 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6062 */
5f040085 6063static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6064 afi_t afi, safi_t safi,
6065 struct prefix_rd *prd)
718e3744 6066{
9bcb3eef 6067 struct bgp_dest *dest;
40381db7 6068 struct bgp_path_info *pi;
718e3744 6069
9bcb3eef 6070 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6071
d62a17ae 6072 /* Check selected route and self inserted route. */
9bcb3eef 6073 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6074 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6075 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6076 break;
718e3744 6077
d62a17ae 6078 /* Withdraw static BGP route from routing table. */
40381db7 6079 if (pi) {
49e5a4a0 6080#ifdef ENABLE_BGP_VNC
d62a17ae 6081 rfapiProcessWithdraw(
40381db7 6082 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6083 1); /* Kill, since it is an administrative change */
65efcfce 6084#endif
ddb5b488
PZ
6085 if (SAFI_MPLS_VPN == safi
6086 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6087 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6088 }
40381db7 6089 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6090 bgp_path_info_delete(dest, pi);
6091 bgp_process(bgp, dest, afi, safi);
d62a17ae 6092 }
718e3744 6093
d62a17ae 6094 /* Unlock bgp_node_lookup. */
9bcb3eef 6095 bgp_dest_unlock_node(dest);
718e3744 6096}
6097
5f040085 6098static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6099 struct bgp_static *bgp_static, afi_t afi,
6100 safi_t safi)
137446f9 6101{
9bcb3eef 6102 struct bgp_dest *dest;
4b7e6066 6103 struct bgp_path_info *new;
d62a17ae 6104 struct attr *attr_new;
6105 struct attr attr = {0};
40381db7 6106 struct bgp_path_info *pi;
49e5a4a0 6107#ifdef ENABLE_BGP_VNC
d62a17ae 6108 mpls_label_t label = 0;
65efcfce 6109#endif
d7c0a89a 6110 uint32_t num_labels = 0;
137446f9 6111
d62a17ae 6112 assert(bgp_static);
137446f9 6113
b57ba6d2
MK
6114 if (bgp_static->label != MPLS_INVALID_LABEL)
6115 num_labels = 1;
9bcb3eef
DS
6116 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6117 &bgp_static->prd);
137446f9 6118
0f05ea43 6119 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6120
d62a17ae 6121 attr.nexthop = bgp_static->igpnexthop;
6122 attr.med = bgp_static->igpmetric;
6123 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6124
d62a17ae 6125 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6126 || (safi == SAFI_ENCAP)) {
6127 if (afi == AFI_IP) {
6128 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6129 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6130 }
6131 }
6132 if (afi == AFI_L2VPN) {
b04c1e99
IR
6133 if (bgp_static->gatewayIp.family == AF_INET) {
6134 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6135 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6136 &bgp_static->gatewayIp.u.prefix4,
6137 IPV4_MAX_BYTELEN);
b04c1e99
IR
6138 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6139 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6140 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6141 &bgp_static->gatewayIp.u.prefix6,
6142 IPV6_MAX_BYTELEN);
b04c1e99 6143 }
0a50c248 6144 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6145 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6146 struct bgp_encap_type_vxlan bet;
6006b807 6147 memset(&bet, 0, sizeof(bet));
3714a385 6148 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6149 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6150 }
6151 if (bgp_static->router_mac) {
6152 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6153 }
6154 }
6155 /* Apply route-map. */
6156 if (bgp_static->rmap.name) {
6157 struct attr attr_tmp = attr;
40381db7 6158 struct bgp_path_info rmap_path;
b68885f9 6159 route_map_result_t ret;
137446f9 6160
40381db7
DS
6161 rmap_path.peer = bgp->peer_self;
6162 rmap_path.attr = &attr_tmp;
137446f9 6163
d62a17ae 6164 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6165
1782514f 6166 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6167
d62a17ae 6168 bgp->peer_self->rmap_type = 0;
137446f9 6169
d62a17ae 6170 if (ret == RMAP_DENYMATCH) {
6171 /* Free uninterned attribute. */
6172 bgp_attr_flush(&attr_tmp);
137446f9 6173
d62a17ae 6174 /* Unintern original. */
6175 aspath_unintern(&attr.aspath);
6176 bgp_static_withdraw_safi(bgp, p, afi, safi,
6177 &bgp_static->prd);
6178 return;
6179 }
137446f9 6180
d62a17ae 6181 attr_new = bgp_attr_intern(&attr_tmp);
6182 } else {
6183 attr_new = bgp_attr_intern(&attr);
6184 }
137446f9 6185
9bcb3eef 6186 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6187 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6188 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6189 break;
6190
40381db7 6191 if (pi) {
40381db7 6192 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6193 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6194 bgp_dest_unlock_node(dest);
d62a17ae 6195 bgp_attr_unintern(&attr_new);
6196 aspath_unintern(&attr.aspath);
6197 return;
6198 } else {
6199 /* The attribute is changed. */
9bcb3eef 6200 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6201
6202 /* Rewrite BGP route information. */
40381db7 6203 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6204 bgp_path_info_restore(dest, pi);
d62a17ae 6205 else
40381db7
DS
6206 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6207 bgp_attr_unintern(&pi->attr);
6208 pi->attr = attr_new;
6209 pi->uptime = bgp_clock();
49e5a4a0 6210#ifdef ENABLE_BGP_VNC
40381db7
DS
6211 if (pi->extra)
6212 label = decode_label(&pi->extra->label[0]);
65efcfce 6213#endif
137446f9 6214
d62a17ae 6215 /* Process change. */
40381db7 6216 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6217 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6218
6219 if (SAFI_MPLS_VPN == safi
6220 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6221 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6222 }
49e5a4a0 6223#ifdef ENABLE_BGP_VNC
40381db7
DS
6224 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6225 pi->attr, afi, safi, pi->type,
6226 pi->sub_type, &label);
65efcfce 6227#endif
9bcb3eef 6228 bgp_dest_unlock_node(dest);
d62a17ae 6229 aspath_unintern(&attr.aspath);
6230 return;
6231 }
6232 }
137446f9
LB
6233
6234
d62a17ae 6235 /* Make new BGP info. */
6236 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6237 attr_new, dest);
1defdda8 6238 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6239 bgp_path_info_extra_get(new);
b57ba6d2
MK
6240 if (num_labels) {
6241 new->extra->label[0] = bgp_static->label;
6242 new->extra->num_labels = num_labels;
6243 }
49e5a4a0 6244#ifdef ENABLE_BGP_VNC
d62a17ae 6245 label = decode_label(&bgp_static->label);
65efcfce 6246#endif
137446f9 6247
d62a17ae 6248 /* Aggregate address increment. */
6249 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6250
d62a17ae 6251 /* Register new BGP information. */
9bcb3eef 6252 bgp_path_info_add(dest, new);
d62a17ae 6253 /* route_node_get lock */
9bcb3eef 6254 bgp_dest_unlock_node(dest);
137446f9 6255
d62a17ae 6256 /* Process change. */
9bcb3eef 6257 bgp_process(bgp, dest, afi, safi);
137446f9 6258
ddb5b488
PZ
6259 if (SAFI_MPLS_VPN == safi
6260 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6261 vpn_leak_to_vrf_update(bgp, new);
6262 }
49e5a4a0 6263#ifdef ENABLE_BGP_VNC
d62a17ae 6264 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6265 safi, new->type, new->sub_type, &label);
65efcfce
LB
6266#endif
6267
d62a17ae 6268 /* Unintern original. */
6269 aspath_unintern(&attr.aspath);
137446f9
LB
6270}
6271
718e3744 6272/* Configure static BGP network. When user don't run zebra, static
6273 route should be installed as valid. */
585f1adc
IR
6274static int bgp_static_set(struct vty *vty, const char *negate,
6275 const char *ip_str, afi_t afi, safi_t safi,
6276 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6277{
585f1adc
IR
6278 VTY_DECLVAR_CONTEXT(bgp, bgp);
6279 int ret;
d62a17ae 6280 struct prefix p;
6281 struct bgp_static *bgp_static;
9bcb3eef 6282 struct bgp_dest *dest;
d7c0a89a 6283 uint8_t need_update = 0;
d62a17ae 6284
585f1adc
IR
6285 /* Convert IP prefix string to struct prefix. */
6286 ret = str2prefix(ip_str, &p);
6287 if (!ret) {
6288 vty_out(vty, "%% Malformed prefix\n");
6289 return CMD_WARNING_CONFIG_FAILED;
6290 }
6291 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6292 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6293 return CMD_WARNING_CONFIG_FAILED;
6294 }
6295
d62a17ae 6296 apply_mask(&p);
718e3744 6297
e2a86ad9 6298 if (negate) {
718e3744 6299
e2a86ad9 6300 /* Set BGP static route configuration. */
9bcb3eef 6301 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6302
9bcb3eef 6303 if (!dest) {
585f1adc
IR
6304 vty_out(vty, "%% Can't find static route specified\n");
6305 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6306 }
6307
9bcb3eef 6308 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6309
e2a86ad9
DS
6310 if ((label_index != BGP_INVALID_LABEL_INDEX)
6311 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6312 vty_out(vty,
6313 "%% label-index doesn't match static route\n");
70d9b134 6314 bgp_dest_unlock_node(dest);
585f1adc 6315 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6316 }
d62a17ae 6317
e2a86ad9
DS
6318 if ((rmap && bgp_static->rmap.name)
6319 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6320 vty_out(vty,
6321 "%% route-map name doesn't match static route\n");
70d9b134 6322 bgp_dest_unlock_node(dest);
585f1adc 6323 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6324 }
718e3744 6325
e2a86ad9
DS
6326 /* Update BGP RIB. */
6327 if (!bgp_static->backdoor)
6328 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6329
e2a86ad9
DS
6330 /* Clear configuration. */
6331 bgp_static_free(bgp_static);
9bcb3eef
DS
6332 bgp_dest_set_bgp_static_info(dest, NULL);
6333 bgp_dest_unlock_node(dest);
6334 bgp_dest_unlock_node(dest);
e2a86ad9 6335 } else {
718e3744 6336
e2a86ad9 6337 /* Set BGP static route configuration. */
9bcb3eef
DS
6338 dest = bgp_node_get(bgp->route[afi][safi], &p);
6339 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6340 if (bgp_static) {
e2a86ad9 6341 /* Configuration change. */
e2a86ad9
DS
6342 /* Label index cannot be changed. */
6343 if (bgp_static->label_index != label_index) {
585f1adc
IR
6344 vty_out(vty, "%% cannot change label-index\n");
6345 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6346 }
d62a17ae 6347
e2a86ad9 6348 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6349 if (bgp_static->valid
6350 && bgp_static->backdoor != backdoor)
e2a86ad9 6351 need_update = 1;
718e3744 6352
e2a86ad9 6353 bgp_static->backdoor = backdoor;
718e3744 6354
e2a86ad9 6355 if (rmap) {
0a22ddfb
QY
6356 XFREE(MTYPE_ROUTE_MAP_NAME,
6357 bgp_static->rmap.name);
b4897fa5 6358 route_map_counter_decrement(
6359 bgp_static->rmap.map);
e2a86ad9
DS
6360 bgp_static->rmap.name =
6361 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6362 bgp_static->rmap.map =
6363 route_map_lookup_by_name(rmap);
b4897fa5 6364 route_map_counter_increment(
6365 bgp_static->rmap.map);
e2a86ad9 6366 } else {
0a22ddfb
QY
6367 XFREE(MTYPE_ROUTE_MAP_NAME,
6368 bgp_static->rmap.name);
b4897fa5 6369 route_map_counter_decrement(
6370 bgp_static->rmap.map);
e2a86ad9
DS
6371 bgp_static->rmap.map = NULL;
6372 bgp_static->valid = 0;
6373 }
9bcb3eef 6374 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6375 } else {
6376 /* New configuration. */
6377 bgp_static = bgp_static_new();
6378 bgp_static->backdoor = backdoor;
6379 bgp_static->valid = 0;
6380 bgp_static->igpmetric = 0;
975a328e 6381 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6382 bgp_static->label_index = label_index;
718e3744 6383
e2a86ad9 6384 if (rmap) {
0a22ddfb
QY
6385 XFREE(MTYPE_ROUTE_MAP_NAME,
6386 bgp_static->rmap.name);
b4897fa5 6387 route_map_counter_decrement(
6388 bgp_static->rmap.map);
e2a86ad9
DS
6389 bgp_static->rmap.name =
6390 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6391 bgp_static->rmap.map =
6392 route_map_lookup_by_name(rmap);
b4897fa5 6393 route_map_counter_increment(
6394 bgp_static->rmap.map);
e2a86ad9 6395 }
9bcb3eef 6396 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6397 }
d62a17ae 6398
e2a86ad9
DS
6399 bgp_static->valid = 1;
6400 if (need_update)
6401 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6402
e2a86ad9
DS
6403 if (!bgp_static->backdoor)
6404 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6405 }
d62a17ae 6406
585f1adc 6407 return CMD_SUCCESS;
d62a17ae 6408}
6409
6410void bgp_static_add(struct bgp *bgp)
6411{
6412 afi_t afi;
6413 safi_t safi;
9bcb3eef
DS
6414 struct bgp_dest *dest;
6415 struct bgp_dest *rm;
d62a17ae 6416 struct bgp_table *table;
6417 struct bgp_static *bgp_static;
6418
47fc6261 6419 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6420 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6421 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6422 dest = bgp_route_next(dest)) {
6423 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6424 continue;
ea47320b 6425
05c7a1cc
QY
6426 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6427 || (safi == SAFI_EVPN)) {
9bcb3eef 6428 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6429
6430 for (rm = bgp_table_top(table); rm;
6431 rm = bgp_route_next(rm)) {
a78beeb5 6432 bgp_static =
9bcb3eef 6433 bgp_dest_get_bgp_static_info(
5a8ba9fc 6434 rm);
9bcb3eef
DS
6435 bgp_static_update_safi(
6436 bgp, bgp_dest_get_prefix(rm),
6437 bgp_static, afi, safi);
d62a17ae 6438 }
05c7a1cc 6439 } else {
5a8ba9fc 6440 bgp_static_update(
9bcb3eef
DS
6441 bgp, bgp_dest_get_prefix(dest),
6442 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6443 safi);
ea47320b 6444 }
05c7a1cc 6445 }
47fc6261 6446 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6447}
6448
718e3744 6449/* Called from bgp_delete(). Delete all static routes from the BGP
6450 instance. */
d62a17ae 6451void bgp_static_delete(struct bgp *bgp)
6452{
6453 afi_t afi;
6454 safi_t safi;
9bcb3eef
DS
6455 struct bgp_dest *dest;
6456 struct bgp_dest *rm;
d62a17ae 6457 struct bgp_table *table;
6458 struct bgp_static *bgp_static;
6459
05c7a1cc 6460 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6461 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6462 dest = bgp_route_next(dest)) {
6463 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6464 continue;
ea47320b 6465
05c7a1cc
QY
6466 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6467 || (safi == SAFI_EVPN)) {
9bcb3eef 6468 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6469
6470 for (rm = bgp_table_top(table); rm;
6471 rm = bgp_route_next(rm)) {
a78beeb5 6472 bgp_static =
9bcb3eef 6473 bgp_dest_get_bgp_static_info(
5a8ba9fc 6474 rm);
c7d14ba6
PG
6475 if (!bgp_static)
6476 continue;
6477
05c7a1cc 6478 bgp_static_withdraw_safi(
9bcb3eef 6479 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6480 AFI_IP, safi,
6481 (struct prefix_rd *)
9bcb3eef
DS
6482 bgp_dest_get_prefix(
6483 dest));
ea47320b 6484 bgp_static_free(bgp_static);
811c6797 6485 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6486 NULL);
811c6797 6487 bgp_dest_unlock_node(rm);
d62a17ae 6488 }
05c7a1cc 6489 } else {
9bcb3eef 6490 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6491 bgp_static_withdraw(bgp,
9bcb3eef 6492 bgp_dest_get_prefix(dest),
b54892e0 6493 afi, safi);
05c7a1cc 6494 bgp_static_free(bgp_static);
9bcb3eef
DS
6495 bgp_dest_set_bgp_static_info(dest, NULL);
6496 bgp_dest_unlock_node(dest);
ea47320b 6497 }
05c7a1cc 6498 }
d62a17ae 6499}
6500
6501void bgp_static_redo_import_check(struct bgp *bgp)
6502{
6503 afi_t afi;
6504 safi_t safi;
9bcb3eef
DS
6505 struct bgp_dest *dest;
6506 struct bgp_dest *rm;
d62a17ae 6507 struct bgp_table *table;
6508 struct bgp_static *bgp_static;
6509
6510 /* Use this flag to force reprocessing of the route */
892fedb6 6511 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6512 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6513 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6514 dest = bgp_route_next(dest)) {
6515 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6516 continue;
ea47320b 6517
05c7a1cc
QY
6518 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6519 || (safi == SAFI_EVPN)) {
9bcb3eef 6520 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6521
6522 for (rm = bgp_table_top(table); rm;
6523 rm = bgp_route_next(rm)) {
a78beeb5 6524 bgp_static =
9bcb3eef 6525 bgp_dest_get_bgp_static_info(
5a8ba9fc 6526 rm);
9bcb3eef
DS
6527 bgp_static_update_safi(
6528 bgp, bgp_dest_get_prefix(rm),
6529 bgp_static, afi, safi);
d62a17ae 6530 }
05c7a1cc 6531 } else {
9bcb3eef
DS
6532 bgp_static = bgp_dest_get_bgp_static_info(dest);
6533 bgp_static_update(bgp,
6534 bgp_dest_get_prefix(dest),
6535 bgp_static, afi, safi);
ea47320b 6536 }
05c7a1cc
QY
6537 }
6538 }
892fedb6 6539 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6540}
6541
6542static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6543 safi_t safi)
6544{
6545 struct bgp_table *table;
9bcb3eef 6546 struct bgp_dest *dest;
40381db7 6547 struct bgp_path_info *pi;
d62a17ae 6548
dfb6fd1d
NT
6549 /* Do not install the aggregate route if BGP is in the
6550 * process of termination.
6551 */
892fedb6
DA
6552 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6553 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6554 return;
6555
d62a17ae 6556 table = bgp->rib[afi][safi];
9bcb3eef
DS
6557 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6558 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6559 if (pi->peer == bgp->peer_self
6560 && ((pi->type == ZEBRA_ROUTE_BGP
6561 && pi->sub_type == BGP_ROUTE_STATIC)
6562 || (pi->type != ZEBRA_ROUTE_BGP
6563 && pi->sub_type
d62a17ae 6564 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6565 bgp_aggregate_decrement(
6566 bgp, bgp_dest_get_prefix(dest), pi, afi,
6567 safi);
40381db7 6568 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6569 bgp_path_info_delete(dest, pi);
6570 bgp_process(bgp, dest, afi, safi);
d62a17ae 6571 }
6572 }
6573 }
ad4cbda1 6574}
6575
6576/*
6577 * Purge all networks and redistributed routes from routing table.
6578 * Invoked upon the instance going down.
6579 */
d62a17ae 6580void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6581{
d62a17ae 6582 afi_t afi;
6583 safi_t safi;
ad4cbda1 6584
05c7a1cc
QY
6585 FOREACH_AFI_SAFI (afi, safi)
6586 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6587}
6588
137446f9
LB
6589/*
6590 * gpz 110624
6591 * Currently this is used to set static routes for VPN and ENCAP.
6592 * I think it can probably be factored with bgp_static_set.
6593 */
d62a17ae 6594int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6595 const char *ip_str, const char *rd_str,
6596 const char *label_str, const char *rmap_str,
6597 int evpn_type, const char *esi, const char *gwip,
6598 const char *ethtag, const char *routermac)
6599{
6600 VTY_DECLVAR_CONTEXT(bgp, bgp);
6601 int ret;
6602 struct prefix p;
6603 struct prefix_rd prd;
9bcb3eef
DS
6604 struct bgp_dest *pdest;
6605 struct bgp_dest *dest;
d62a17ae 6606 struct bgp_table *table;
6607 struct bgp_static *bgp_static;
6608 mpls_label_t label = MPLS_INVALID_LABEL;
6609 struct prefix gw_ip;
6610
6611 /* validate ip prefix */
6612 ret = str2prefix(ip_str, &p);
6613 if (!ret) {
6614 vty_out(vty, "%% Malformed prefix\n");
6615 return CMD_WARNING_CONFIG_FAILED;
6616 }
6617 apply_mask(&p);
6618 if ((afi == AFI_L2VPN)
6619 && (bgp_build_evpn_prefix(evpn_type,
6620 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6621 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6622 return CMD_WARNING_CONFIG_FAILED;
6623 }
718e3744 6624
d62a17ae 6625 ret = str2prefix_rd(rd_str, &prd);
6626 if (!ret) {
6627 vty_out(vty, "%% Malformed rd\n");
6628 return CMD_WARNING_CONFIG_FAILED;
6629 }
718e3744 6630
d62a17ae 6631 if (label_str) {
6632 unsigned long label_val;
6633 label_val = strtoul(label_str, NULL, 10);
6634 encode_label(label_val, &label);
6635 }
9bedbb1e 6636
d62a17ae 6637 if (safi == SAFI_EVPN) {
6638 if (esi && str2esi(esi, NULL) == 0) {
6639 vty_out(vty, "%% Malformed ESI\n");
6640 return CMD_WARNING_CONFIG_FAILED;
6641 }
6642 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6643 vty_out(vty, "%% Malformed Router MAC\n");
6644 return CMD_WARNING_CONFIG_FAILED;
6645 }
6646 if (gwip) {
6006b807 6647 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6648 ret = str2prefix(gwip, &gw_ip);
6649 if (!ret) {
6650 vty_out(vty, "%% Malformed GatewayIp\n");
6651 return CMD_WARNING_CONFIG_FAILED;
6652 }
6653 if ((gw_ip.family == AF_INET
3714a385 6654 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6655 (struct prefix_evpn *)&p))
6656 || (gw_ip.family == AF_INET6
3714a385 6657 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6658 (struct prefix_evpn *)&p))) {
6659 vty_out(vty,
6660 "%% GatewayIp family differs with IP prefix\n");
6661 return CMD_WARNING_CONFIG_FAILED;
6662 }
6663 }
6664 }
9bcb3eef
DS
6665 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6666 if (!bgp_dest_has_bgp_path_info_data(pdest))
6667 bgp_dest_set_bgp_table_info(pdest,
67009e22 6668 bgp_table_init(bgp, afi, safi));
9bcb3eef 6669 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6670
9bcb3eef 6671 dest = bgp_node_get(table, &p);
d62a17ae 6672
9bcb3eef 6673 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6674 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6675 bgp_dest_unlock_node(dest);
d62a17ae 6676 } else {
6677 /* New configuration. */
6678 bgp_static = bgp_static_new();
6679 bgp_static->backdoor = 0;
6680 bgp_static->valid = 0;
6681 bgp_static->igpmetric = 0;
975a328e 6682 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6683 bgp_static->label = label;
6684 bgp_static->prd = prd;
6685
6686 if (rmap_str) {
0a22ddfb 6687 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6688 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6689 bgp_static->rmap.name =
6690 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6691 bgp_static->rmap.map =
6692 route_map_lookup_by_name(rmap_str);
b4897fa5 6693 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6694 }
718e3744 6695
d62a17ae 6696 if (safi == SAFI_EVPN) {
6697 if (esi) {
6698 bgp_static->eth_s_id =
6699 XCALLOC(MTYPE_ATTR,
0a50c248 6700 sizeof(esi_t));
d62a17ae 6701 str2esi(esi, bgp_static->eth_s_id);
6702 }
6703 if (routermac) {
6704 bgp_static->router_mac =
28328ea9 6705 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6706 (void)prefix_str2mac(routermac,
6707 bgp_static->router_mac);
d62a17ae 6708 }
6709 if (gwip)
6710 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6711 }
9bcb3eef 6712 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6713
d62a17ae 6714 bgp_static->valid = 1;
6715 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6716 }
718e3744 6717
d62a17ae 6718 return CMD_SUCCESS;
718e3744 6719}
6720
6721/* Configure static BGP network. */
d62a17ae 6722int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6723 const char *ip_str, const char *rd_str,
6724 const char *label_str, int evpn_type, const char *esi,
6725 const char *gwip, const char *ethtag)
6726{
6727 VTY_DECLVAR_CONTEXT(bgp, bgp);
6728 int ret;
6729 struct prefix p;
6730 struct prefix_rd prd;
9bcb3eef
DS
6731 struct bgp_dest *pdest;
6732 struct bgp_dest *dest;
d62a17ae 6733 struct bgp_table *table;
6734 struct bgp_static *bgp_static;
6735 mpls_label_t label = MPLS_INVALID_LABEL;
6736
6737 /* Convert IP prefix string to struct prefix. */
6738 ret = str2prefix(ip_str, &p);
6739 if (!ret) {
6740 vty_out(vty, "%% Malformed prefix\n");
6741 return CMD_WARNING_CONFIG_FAILED;
6742 }
6743 apply_mask(&p);
6744 if ((afi == AFI_L2VPN)
6745 && (bgp_build_evpn_prefix(evpn_type,
6746 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6747 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6748 return CMD_WARNING_CONFIG_FAILED;
6749 }
6750 ret = str2prefix_rd(rd_str, &prd);
6751 if (!ret) {
6752 vty_out(vty, "%% Malformed rd\n");
6753 return CMD_WARNING_CONFIG_FAILED;
6754 }
718e3744 6755
d62a17ae 6756 if (label_str) {
6757 unsigned long label_val;
6758 label_val = strtoul(label_str, NULL, 10);
6759 encode_label(label_val, &label);
6760 }
718e3744 6761
9bcb3eef
DS
6762 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6763 if (!bgp_dest_has_bgp_path_info_data(pdest))
6764 bgp_dest_set_bgp_table_info(pdest,
67009e22 6765 bgp_table_init(bgp, afi, safi));
d62a17ae 6766 else
9bcb3eef
DS
6767 bgp_dest_unlock_node(pdest);
6768 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6769
9bcb3eef 6770 dest = bgp_node_lookup(table, &p);
6b0655a2 6771
9bcb3eef 6772 if (dest) {
d62a17ae 6773 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6774
9bcb3eef 6775 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6776 bgp_static_free(bgp_static);
9bcb3eef
DS
6777 bgp_dest_set_bgp_static_info(dest, NULL);
6778 bgp_dest_unlock_node(dest);
6779 bgp_dest_unlock_node(dest);
d62a17ae 6780 } else
6781 vty_out(vty, "%% Can't find the route\n");
6782
6783 return CMD_SUCCESS;
6784}
6785
6786static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6787 const char *rmap_name)
6788{
6789 VTY_DECLVAR_CONTEXT(bgp, bgp);
6790 struct bgp_rmap *rmap;
6791
6792 rmap = &bgp->table_map[afi][safi];
6793 if (rmap_name) {
0a22ddfb 6794 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6795 route_map_counter_decrement(rmap->map);
d62a17ae 6796 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6797 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6798 route_map_counter_increment(rmap->map);
d62a17ae 6799 } else {
0a22ddfb 6800 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6801 route_map_counter_decrement(rmap->map);
d62a17ae 6802 rmap->map = NULL;
6803 }
73ac8160 6804
d62a17ae 6805 if (bgp_fibupd_safi(safi))
6806 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6807
d62a17ae 6808 return CMD_SUCCESS;
73ac8160
DS
6809}
6810
d62a17ae 6811static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6812 const char *rmap_name)
73ac8160 6813{
d62a17ae 6814 VTY_DECLVAR_CONTEXT(bgp, bgp);
6815 struct bgp_rmap *rmap;
73ac8160 6816
d62a17ae 6817 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6818 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6819 route_map_counter_decrement(rmap->map);
d62a17ae 6820 rmap->map = NULL;
73ac8160 6821
d62a17ae 6822 if (bgp_fibupd_safi(safi))
6823 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6824
d62a17ae 6825 return CMD_SUCCESS;
73ac8160
DS
6826}
6827
2b791107 6828void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6829 safi_t safi)
73ac8160 6830{
d62a17ae 6831 if (bgp->table_map[afi][safi].name) {
d62a17ae 6832 vty_out(vty, " table-map %s\n",
6833 bgp->table_map[afi][safi].name);
6834 }
73ac8160
DS
6835}
6836
73ac8160
DS
6837DEFUN (bgp_table_map,
6838 bgp_table_map_cmd,
6839 "table-map WORD",
6840 "BGP table to RIB route download filter\n"
6841 "Name of the route map\n")
6842{
d62a17ae 6843 int idx_word = 1;
6844 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6845 argv[idx_word]->arg);
73ac8160
DS
6846}
6847DEFUN (no_bgp_table_map,
6848 no_bgp_table_map_cmd,
6849 "no table-map WORD",
3a2d747c 6850 NO_STR
73ac8160
DS
6851 "BGP table to RIB route download filter\n"
6852 "Name of the route map\n")
6853{
d62a17ae 6854 int idx_word = 2;
6855 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6856 argv[idx_word]->arg);
73ac8160
DS
6857}
6858
585f1adc
IR
6859DEFPY(bgp_network,
6860 bgp_network_cmd,
6861 "[no] network \
6862 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 6863 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
6864 backdoor$backdoor}]",
6865 NO_STR
6866 "Specify a network to announce via BGP\n"
6867 "IPv4 prefix\n"
6868 "Network number\n"
6869 "Network mask\n"
6870 "Network mask\n"
6871 "Route-map to modify the attributes\n"
6872 "Name of the route map\n"
6873 "Label index to associate with the prefix\n"
6874 "Label index value\n"
6875 "Specify a BGP backdoor route\n")
6876{
6877 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6878
6879 if (address_str) {
6880 int ret;
718e3744 6881
e2a86ad9 6882 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6883 addr_prefix_str,
6884 sizeof(addr_prefix_str));
e2a86ad9
DS
6885 if (!ret) {
6886 vty_out(vty, "%% Inconsistent address and mask\n");
6887 return CMD_WARNING_CONFIG_FAILED;
6888 }
d62a17ae 6889 }
718e3744 6890
585f1adc
IR
6891 return bgp_static_set(
6892 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6893 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6894 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6895}
6896
585f1adc
IR
6897DEFPY(ipv6_bgp_network,
6898 ipv6_bgp_network_cmd,
6899 "[no] network X:X::X:X/M$prefix \
70dd370f 6900 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
6901 NO_STR
6902 "Specify a network to announce via BGP\n"
6903 "IPv6 prefix\n"
6904 "Route-map to modify the attributes\n"
6905 "Name of the route map\n"
6906 "Label index to associate with the prefix\n"
6907 "Label index value\n")
37a87b8f 6908{
585f1adc
IR
6909 return bgp_static_set(
6910 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6911 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6912}
6913
d62a17ae 6914static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6915{
d62a17ae 6916 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6917}
6918
d62a17ae 6919static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6920{
365ab2e7
RZ
6921 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6922 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6923 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6924 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6925 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6926}
718e3744 6927
365ab2e7
RZ
6928/**
6929 * Helper function to avoid repeated code: prepare variables for a
6930 * `route_map_apply` call.
6931 *
6932 * \returns `true` on route map match, otherwise `false`.
6933 */
6934static bool aggr_suppress_map_test(struct bgp *bgp,
6935 struct bgp_aggregate *aggregate,
6936 struct bgp_path_info *pi)
6937{
6938 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6939 route_map_result_t rmr = RMAP_DENYMATCH;
6940 struct bgp_path_info rmap_path = {};
6941 struct attr attr = {};
6942
6943 /* No route map entries created, just don't match. */
6944 if (aggregate->suppress_map == NULL)
6945 return false;
6946
6947 /* Call route map matching and return result. */
6948 attr.aspath = aspath_empty();
6949 rmap_path.peer = bgp->peer_self;
6950 rmap_path.attr = &attr;
6951
6952 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6953 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6954 bgp->peer_self->rmap_type = 0;
6955
6956 bgp_attr_flush(&attr);
afb254d7 6957 aspath_unintern(&attr.aspath);
365ab2e7
RZ
6958
6959 return rmr == RMAP_PERMITMATCH;
6960}
6961
4056a5f6
RZ
6962/** Test whether the aggregation has suppressed this path or not. */
6963static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6964 struct bgp_path_info *pi)
6965{
6966 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6967 return false;
6968
6969 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6970}
6971
6972/**
6973 * Suppress this path and keep the reference.
6974 *
6975 * \returns `true` if needs processing otherwise `false`.
6976 */
6977static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6978 struct bgp_path_info *pi)
6979{
6980 struct bgp_path_info_extra *pie;
6981
6982 /* Path is already suppressed by this aggregation. */
6983 if (aggr_suppress_exists(aggregate, pi))
6984 return false;
6985
6986 pie = bgp_path_info_extra_get(pi);
6987
6988 /* This is the first suppression, allocate memory and list it. */
6989 if (pie->aggr_suppressors == NULL)
6990 pie->aggr_suppressors = list_new();
6991
6992 listnode_add(pie->aggr_suppressors, aggregate);
6993
6994 /* Only mark for processing if suppressed. */
6995 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6996 if (BGP_DEBUG(update, UPDATE_OUT))
6997 zlog_debug("aggregate-address suppressing: %pFX",
6998 bgp_dest_get_prefix(pi->net));
6999
4056a5f6
RZ
7000 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7001 return true;
7002 }
7003
7004 return false;
7005}
7006
7007/**
7008 * Unsuppress this path and remove the reference.
7009 *
7010 * \returns `true` if needs processing otherwise `false`.
7011 */
7012static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7013 struct bgp_path_info *pi)
7014{
7015 /* Path wasn't suppressed. */
7016 if (!aggr_suppress_exists(aggregate, pi))
7017 return false;
7018
7019 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7020
7021 /* Unsuppress and free extra memory if last item. */
7022 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7023 if (BGP_DEBUG(update, UPDATE_OUT))
7024 zlog_debug("aggregate-address unsuppressing: %pFX",
7025 bgp_dest_get_prefix(pi->net));
7026
4056a5f6
RZ
7027 list_delete(&pi->extra->aggr_suppressors);
7028 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7029 return true;
7030 }
7031
7032 return false;
7033}
7034
3dc339cd
DA
7035static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7036 struct aspath *aspath,
7037 struct community *comm,
7038 struct ecommunity *ecomm,
7039 struct lcommunity *lcomm)
eaaf8adb
DS
7040{
7041 static struct aspath *ae = NULL;
7042
7043 if (!ae)
7044 ae = aspath_empty();
7045
40381db7 7046 if (!pi)
3dc339cd 7047 return false;
eaaf8adb 7048
40381db7 7049 if (origin != pi->attr->origin)
3dc339cd 7050 return false;
eaaf8adb 7051
40381db7 7052 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7053 return false;
29f7d023 7054
9a706b42 7055 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7056 return false;
eaaf8adb 7057
b53e67a3 7058 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7059 return false;
eaaf8adb 7060
1bcf3a96 7061 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7062 return false;
dd18c5a9 7063
40381db7 7064 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7065 return false;
7ce8a8e0 7066
3dc339cd 7067 return true;
eaaf8adb
DS
7068}
7069
5f040085
DS
7070static void bgp_aggregate_install(
7071 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7072 uint8_t origin, struct aspath *aspath, struct community *community,
7073 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7074 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7075{
9bcb3eef 7076 struct bgp_dest *dest;
c701010e 7077 struct bgp_table *table;
6f94b685 7078 struct bgp_path_info *pi, *orig, *new;
20894f50 7079 struct attr *attr;
c701010e
DS
7080
7081 table = bgp->rib[afi][safi];
7082
9bcb3eef 7083 dest = bgp_node_get(table, p);
eaaf8adb 7084
9bcb3eef 7085 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7086 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7087 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7088 break;
7089
6aabb15d
RZ
7090 /*
7091 * If we have paths with different MEDs, then don't install
7092 * (or uninstall) the aggregate route.
7093 */
7094 if (aggregate->match_med && aggregate->med_mismatched)
7095 goto uninstall_aggregate_route;
7096
c701010e 7097 if (aggregate->count > 0) {
eaaf8adb
DS
7098 /*
7099 * If the aggregate information has not changed
7100 * no need to re-install it again.
7101 */
6f94b685 7102 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7103 ecommunity, lcommunity)) {
9bcb3eef 7104 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7105
7106 if (aspath)
7107 aspath_free(aspath);
7108 if (community)
3c1f53de 7109 community_free(&community);
3da2cc32
DS
7110 if (ecommunity)
7111 ecommunity_free(&ecommunity);
dd18c5a9
DS
7112 if (lcommunity)
7113 lcommunity_free(&lcommunity);
eaaf8adb
DS
7114
7115 return;
7116 }
7117
7118 /*
7119 * Mark the old as unusable
7120 */
40381db7 7121 if (pi)
9bcb3eef 7122 bgp_path_info_delete(dest, pi);
eaaf8adb 7123
20894f50
DA
7124 attr = bgp_attr_aggregate_intern(
7125 bgp, origin, aspath, community, ecommunity, lcommunity,
7126 aggregate, atomic_aggregate, p);
7127
7128 if (!attr) {
7129 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7130 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7131 zlog_debug("%s: %pFX null attribute", __func__,
7132 p);
20894f50
DA
7133 return;
7134 }
7135
3da2cc32 7136 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7137 bgp->peer_self, attr, dest);
20894f50 7138
1defdda8 7139 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7140
9bcb3eef
DS
7141 bgp_path_info_add(dest, new);
7142 bgp_process(bgp, dest, afi, safi);
c701010e 7143 } else {
6aabb15d 7144 uninstall_aggregate_route:
6f94b685 7145 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7146 if (pi->peer == bgp->peer_self
7147 && pi->type == ZEBRA_ROUTE_BGP
7148 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7149 break;
7150
7151 /* Withdraw static BGP route from routing table. */
40381db7 7152 if (pi) {
9bcb3eef
DS
7153 bgp_path_info_delete(dest, pi);
7154 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7155 }
7156 }
7157
9bcb3eef 7158 bgp_dest_unlock_node(dest);
c701010e
DS
7159}
7160
6aabb15d
RZ
7161/**
7162 * Check if the current path has different MED than other known paths.
7163 *
7164 * \returns `true` if the MED matched the others else `false`.
7165 */
7166static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7167 struct bgp *bgp, struct bgp_path_info *pi)
7168{
7169 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7170
7171 /* This is the first route being analyzed. */
7172 if (!aggregate->med_initialized) {
7173 aggregate->med_initialized = true;
7174 aggregate->med_mismatched = false;
7175 aggregate->med_matched_value = cur_med;
7176 } else {
7177 /* Check if routes with different MED showed up. */
7178 if (cur_med != aggregate->med_matched_value)
7179 aggregate->med_mismatched = true;
7180 }
7181
7182 return !aggregate->med_mismatched;
7183}
7184
7185/**
7186 * Initializes and tests all routes in the aggregate address path for MED
7187 * values.
7188 *
7189 * \returns `true` if all MEDs are the same otherwise `false`.
7190 */
7191static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7192 struct bgp *bgp, const struct prefix *p,
7193 afi_t afi, safi_t safi)
7194{
7195 struct bgp_table *table = bgp->rib[afi][safi];
7196 const struct prefix *dest_p;
7197 struct bgp_dest *dest, *top;
7198 struct bgp_path_info *pi;
7199 bool med_matched = true;
7200
7201 aggregate->med_initialized = false;
7202
7203 top = bgp_node_get(table, p);
7204 for (dest = bgp_node_get(table, p); dest;
7205 dest = bgp_route_next_until(dest, top)) {
7206 dest_p = bgp_dest_get_prefix(dest);
7207 if (dest_p->prefixlen <= p->prefixlen)
7208 continue;
7209
7210 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7211 if (BGP_PATH_HOLDDOWN(pi))
7212 continue;
7213 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7214 continue;
7215 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7216 med_matched = false;
7217 break;
7218 }
7219 }
7220 if (!med_matched)
7221 break;
7222 }
7223 bgp_dest_unlock_node(top);
7224
7225 return med_matched;
7226}
7227
7228/**
7229 * Toggles the route suppression status for this aggregate address
7230 * configuration.
7231 */
4056a5f6
RZ
7232void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7233 struct bgp *bgp, const struct prefix *p,
7234 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7235{
7236 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7237 const struct prefix *dest_p;
7238 struct bgp_dest *dest, *top;
7239 struct bgp_path_info *pi;
7240 bool toggle_suppression;
7241
7242 /* We've found a different MED we must revert any suppressed routes. */
7243 top = bgp_node_get(table, p);
7244 for (dest = bgp_node_get(table, p); dest;
7245 dest = bgp_route_next_until(dest, top)) {
7246 dest_p = bgp_dest_get_prefix(dest);
7247 if (dest_p->prefixlen <= p->prefixlen)
7248 continue;
7249
7250 toggle_suppression = false;
7251 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7252 if (BGP_PATH_HOLDDOWN(pi))
7253 continue;
7254 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7255 continue;
7256
6aabb15d
RZ
7257 /* We are toggling suppression back. */
7258 if (suppress) {
6aabb15d 7259 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7260 if (aggr_suppress_path(aggregate, pi))
7261 toggle_suppression = true;
6aabb15d
RZ
7262 continue;
7263 }
7264
6aabb15d 7265 /* Install route if there is no more suppression. */
4056a5f6 7266 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7267 toggle_suppression = true;
6aabb15d
RZ
7268 }
7269
7270 if (toggle_suppression)
7271 bgp_process(bgp, dest, afi, safi);
7272 }
7273 bgp_dest_unlock_node(top);
7274}
7275
7276/**
7277 * Aggregate address MED matching incremental test: this function is called
7278 * when the initial aggregation occurred and we are only testing a single
7279 * new path.
7280 *
7281 * In addition to testing and setting the MED validity it also installs back
7282 * suppressed routes (if summary is configured).
7283 *
7284 * Must not be called in `bgp_aggregate_route`.
7285 */
7286static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7287 struct bgp *bgp, const struct prefix *p,
7288 afi_t afi, safi_t safi,
7289 struct bgp_path_info *pi, bool is_adding)
7290{
7291 /* MED matching disabled. */
7292 if (!aggregate->match_med)
7293 return;
7294
7295 /* Aggregation with different MED, nothing to do. */
7296 if (aggregate->med_mismatched)
7297 return;
7298
7299 /*
7300 * Test the current entry:
7301 *
7302 * is_adding == true: if the new entry doesn't match then we must
7303 * install all suppressed routes.
7304 *
7305 * is_adding == false: if the entry being removed was the last
7306 * unmatching entry then we can suppress all routes.
7307 */
7308 if (!is_adding) {
7309 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7310 && aggregate->summary_only)
7311 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7312 safi, true);
7313 } else
7314 bgp_aggregate_med_match(aggregate, bgp, pi);
7315
7316 /* No mismatches, just quit. */
7317 if (!aggregate->med_mismatched)
7318 return;
7319
7320 /* Route summarization is disabled. */
7321 if (!aggregate->summary_only)
7322 return;
7323
7324 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7325}
7326
b5d58c32 7327/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7328void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7329 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7330{
7331 struct bgp_table *table;
9bcb3eef
DS
7332 struct bgp_dest *top;
7333 struct bgp_dest *dest;
d7c0a89a 7334 uint8_t origin;
d62a17ae 7335 struct aspath *aspath = NULL;
d62a17ae 7336 struct community *community = NULL;
3da2cc32 7337 struct ecommunity *ecommunity = NULL;
dd18c5a9 7338 struct lcommunity *lcommunity = NULL;
40381db7 7339 struct bgp_path_info *pi;
d62a17ae 7340 unsigned long match = 0;
d7c0a89a 7341 uint8_t atomic_aggregate = 0;
d62a17ae 7342
9f822fa2
S
7343 /* If the bgp instance is being deleted or self peer is deleted
7344 * then do not create aggregate route
7345 */
892fedb6
DA
7346 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7347 || (bgp->peer_self == NULL))
9f822fa2
S
7348 return;
7349
6aabb15d
RZ
7350 /* Initialize and test routes for MED difference. */
7351 if (aggregate->match_med)
7352 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7353
4056a5f6
RZ
7354 /*
7355 * Reset aggregate count: we might've been called from route map
7356 * update so in that case we must retest all more specific routes.
7357 *
7358 * \see `bgp_route_map_process_update`.
7359 */
7360 aggregate->count = 0;
7361 aggregate->incomplete_origin_count = 0;
7362 aggregate->incomplete_origin_count = 0;
7363 aggregate->egp_origin_count = 0;
7364
d62a17ae 7365 /* ORIGIN attribute: If at least one route among routes that are
7366 aggregated has ORIGIN with the value INCOMPLETE, then the
7367 aggregated route must have the ORIGIN attribute with the value
7368 INCOMPLETE. Otherwise, if at least one route among routes that
7369 are aggregated has ORIGIN with the value EGP, then the aggregated
7370 route must have the origin attribute with the value EGP. In all
7371 other case the value of the ORIGIN attribute of the aggregated
7372 route is INTERNAL. */
7373 origin = BGP_ORIGIN_IGP;
718e3744 7374
d62a17ae 7375 table = bgp->rib[afi][safi];
718e3744 7376
d62a17ae 7377 top = bgp_node_get(table, p);
9bcb3eef
DS
7378 for (dest = bgp_node_get(table, p); dest;
7379 dest = bgp_route_next_until(dest, top)) {
7380 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7381
9bcb3eef 7382 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7383 continue;
d62a17ae 7384
a77e2f4b
S
7385 /* If suppress fib is enabled and route not installed
7386 * in FIB, skip the route
7387 */
7388 if (!bgp_check_advertise(bgp, dest))
7389 continue;
7390
c2ff8b3e 7391 match = 0;
d62a17ae 7392
9bcb3eef 7393 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7394 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7395 continue;
718e3744 7396
40381db7 7397 if (pi->attr->flag
c2ff8b3e
DS
7398 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7399 atomic_aggregate = 1;
d62a17ae 7400
40381db7 7401 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7402 continue;
d62a17ae 7403
f273fef1
DS
7404 /*
7405 * summary-only aggregate route suppress
7406 * aggregated route announcements.
6aabb15d
RZ
7407 *
7408 * MED matching:
7409 * Don't create summaries if MED didn't match
7410 * otherwise neither the specific routes and the
7411 * aggregation will be announced.
f273fef1 7412 */
6aabb15d
RZ
7413 if (aggregate->summary_only
7414 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7415 if (aggr_suppress_path(aggregate, pi))
7416 match++;
d62a17ae 7417 }
c2ff8b3e 7418
365ab2e7
RZ
7419 /*
7420 * Suppress more specific routes that match the route
7421 * map results.
7422 *
7423 * MED matching:
7424 * Don't suppress routes if MED matching is enabled and
7425 * it mismatched otherwise we might end up with no
7426 * routes for this path.
7427 */
7428 if (aggregate->suppress_map_name
7429 && AGGREGATE_MED_VALID(aggregate)
7430 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7431 if (aggr_suppress_path(aggregate, pi))
7432 match++;
d62a17ae 7433 }
c2ff8b3e
DS
7434
7435 aggregate->count++;
7436
f273fef1
DS
7437 /*
7438 * If at least one route among routes that are
7439 * aggregated has ORIGIN with the value INCOMPLETE,
7440 * then the aggregated route MUST have the ORIGIN
7441 * attribute with the value INCOMPLETE. Otherwise, if
7442 * at least one route among routes that are aggregated
7443 * has ORIGIN with the value EGP, then the aggregated
7444 * route MUST have the ORIGIN attribute with the value
7445 * EGP.
7446 */
fc968841
NT
7447 switch (pi->attr->origin) {
7448 case BGP_ORIGIN_INCOMPLETE:
7449 aggregate->incomplete_origin_count++;
7450 break;
7451 case BGP_ORIGIN_EGP:
7452 aggregate->egp_origin_count++;
7453 break;
7454 default:
7455 /*Do nothing.
7456 */
7457 break;
7458 }
c2ff8b3e
DS
7459
7460 if (!aggregate->as_set)
7461 continue;
7462
f273fef1
DS
7463 /*
7464 * as-set aggregate route generate origin, as path,
7465 * and community aggregation.
7466 */
fc968841
NT
7467 /* Compute aggregate route's as-path.
7468 */
ef51a7d8 7469 bgp_compute_aggregate_aspath_hash(aggregate,
7470 pi->attr->aspath);
c2ff8b3e 7471
fc968841
NT
7472 /* Compute aggregate route's community.
7473 */
9a706b42 7474 if (bgp_attr_get_community(pi->attr))
21fec674 7475 bgp_compute_aggregate_community_hash(
9a706b42
DA
7476 aggregate,
7477 bgp_attr_get_community(pi->attr));
dd18c5a9 7478
fc968841
NT
7479 /* Compute aggregate route's extended community.
7480 */
b53e67a3 7481 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7482 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7483 aggregate,
7484 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7485
7486 /* Compute aggregate route's large community.
7487 */
1bcf3a96 7488 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7489 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7490 aggregate,
7491 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7492 }
c2ff8b3e 7493 if (match)
9bcb3eef 7494 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7495 }
21fec674 7496 if (aggregate->as_set) {
ef51a7d8 7497 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7498 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7499 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7500 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7501 }
7502
f1eb1f05 7503
9bcb3eef 7504 bgp_dest_unlock_node(top);
718e3744 7505
718e3744 7506
fc968841
NT
7507 if (aggregate->incomplete_origin_count > 0)
7508 origin = BGP_ORIGIN_INCOMPLETE;
7509 else if (aggregate->egp_origin_count > 0)
7510 origin = BGP_ORIGIN_EGP;
d62a17ae 7511
229757f1
DA
7512 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7513 origin = aggregate->origin;
7514
fc968841
NT
7515 if (aggregate->as_set) {
7516 if (aggregate->aspath)
7517 /* Retrieve aggregate route's as-path.
7518 */
7519 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7520
fc968841
NT
7521 if (aggregate->community)
7522 /* Retrieve aggregate route's community.
7523 */
7524 community = community_dup(aggregate->community);
3da2cc32 7525
fc968841
NT
7526 if (aggregate->ecommunity)
7527 /* Retrieve aggregate route's ecommunity.
7528 */
7529 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7530
fc968841
NT
7531 if (aggregate->lcommunity)
7532 /* Retrieve aggregate route's lcommunity.
7533 */
7534 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7535 }
718e3744 7536
c701010e 7537 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7538 ecommunity, lcommunity, atomic_aggregate,
7539 aggregate);
718e3744 7540}
7541
5f040085
DS
7542void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7543 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7544{
7545 struct bgp_table *table;
9bcb3eef
DS
7546 struct bgp_dest *top;
7547 struct bgp_dest *dest;
40381db7 7548 struct bgp_path_info *pi;
3b7db173
DS
7549 unsigned long match;
7550
7551 table = bgp->rib[afi][safi];
7552
7553 /* If routes exists below this node, generate aggregate routes. */
7554 top = bgp_node_get(table, p);
9bcb3eef
DS
7555 for (dest = bgp_node_get(table, p); dest;
7556 dest = bgp_route_next_until(dest, top)) {
7557 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7558
9bcb3eef 7559 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7560 continue;
7561 match = 0;
7562
9bcb3eef 7563 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7564 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7565 continue;
7566
40381db7 7567 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7568 continue;
7569
92b175bd
RZ
7570 /*
7571 * This route is suppressed: attempt to unsuppress it.
7572 *
7573 * `aggr_unsuppress_path` will fail if this particular
7574 * aggregate route was not the suppressor.
7575 */
7576 if (pi->extra && pi->extra->aggr_suppressors &&
7577 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7578 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7579 match++;
3b7db173 7580 }
365ab2e7 7581
3b7db173 7582 aggregate->count--;
fc968841
NT
7583
7584 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7585 aggregate->incomplete_origin_count--;
7586 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7587 aggregate->egp_origin_count--;
7588
7589 if (aggregate->as_set) {
7590 /* Remove as-path from aggregate.
7591 */
ef51a7d8 7592 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7593 aggregate,
7594 pi->attr->aspath);
7595
9a706b42 7596 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7597 /* Remove community from aggregate.
7598 */
21fec674 7599 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7600 aggregate,
7601 bgp_attr_get_community(
7602 pi->attr));
fc968841 7603
b53e67a3 7604 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7605 /* Remove ecommunity from aggregate.
7606 */
4edd83f9 7607 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7608 aggregate,
7609 bgp_attr_get_ecommunity(
7610 pi->attr));
fc968841 7611
1bcf3a96 7612 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7613 /* Remove lcommunity from aggregate.
7614 */
f1eb1f05 7615 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7616 aggregate,
7617 bgp_attr_get_lcommunity(
7618 pi->attr));
fc968841 7619 }
3b7db173
DS
7620 }
7621
7622 /* If this node was suppressed, process the change. */
7623 if (match)
9bcb3eef 7624 bgp_process(bgp, dest, afi, safi);
3b7db173 7625 }
f1eb1f05 7626 if (aggregate->as_set) {
ef51a7d8 7627 aspath_free(aggregate->aspath);
7628 aggregate->aspath = NULL;
21fec674 7629 if (aggregate->community)
7630 community_free(&aggregate->community);
4edd83f9 7631 if (aggregate->ecommunity)
7632 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7633 if (aggregate->lcommunity)
7634 lcommunity_free(&aggregate->lcommunity);
7635 }
7636
9bcb3eef 7637 bgp_dest_unlock_node(top);
3b7db173 7638}
718e3744 7639
5f040085
DS
7640static void bgp_add_route_to_aggregate(struct bgp *bgp,
7641 const struct prefix *aggr_p,
fc968841
NT
7642 struct bgp_path_info *pinew, afi_t afi,
7643 safi_t safi,
7644 struct bgp_aggregate *aggregate)
7645{
7646 uint8_t origin;
7647 struct aspath *aspath = NULL;
7648 uint8_t atomic_aggregate = 0;
7649 struct community *community = NULL;
7650 struct ecommunity *ecommunity = NULL;
7651 struct lcommunity *lcommunity = NULL;
7652
a4559740 7653 /* If the bgp instance is being deleted or self peer is deleted
7654 * then do not create aggregate route
7655 */
7656 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7657 || (bgp->peer_self == NULL))
7658 return;
7659
fc968841
NT
7660 /* ORIGIN attribute: If at least one route among routes that are
7661 * aggregated has ORIGIN with the value INCOMPLETE, then the
7662 * aggregated route must have the ORIGIN attribute with the value
7663 * INCOMPLETE. Otherwise, if at least one route among routes that
7664 * are aggregated has ORIGIN with the value EGP, then the aggregated
7665 * route must have the origin attribute with the value EGP. In all
7666 * other case the value of the ORIGIN attribute of the aggregated
7667 * route is INTERNAL.
7668 */
7669 origin = BGP_ORIGIN_IGP;
7670
7671 aggregate->count++;
7672
6aabb15d
RZ
7673 /*
7674 * This must be called before `summary` check to avoid
7675 * "suppressing" twice.
7676 */
7677 if (aggregate->match_med)
7678 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7679 pinew, true);
7680
7681 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7682 aggr_suppress_path(aggregate, pinew);
fc968841 7683
365ab2e7
RZ
7684 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7685 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7686 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7687
7688 switch (pinew->attr->origin) {
7689 case BGP_ORIGIN_INCOMPLETE:
7690 aggregate->incomplete_origin_count++;
7691 break;
7692 case BGP_ORIGIN_EGP:
7693 aggregate->egp_origin_count++;
7694 break;
7695 default:
7696 /* Do nothing.
7697 */
7698 break;
7699 }
7700
7701 if (aggregate->incomplete_origin_count > 0)
7702 origin = BGP_ORIGIN_INCOMPLETE;
7703 else if (aggregate->egp_origin_count > 0)
7704 origin = BGP_ORIGIN_EGP;
7705
229757f1
DA
7706 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7707 origin = aggregate->origin;
7708
fc968841
NT
7709 if (aggregate->as_set) {
7710 /* Compute aggregate route's as-path.
7711 */
7712 bgp_compute_aggregate_aspath(aggregate,
7713 pinew->attr->aspath);
7714
7715 /* Compute aggregate route's community.
7716 */
9a706b42 7717 if (bgp_attr_get_community(pinew->attr))
fc968841 7718 bgp_compute_aggregate_community(
9a706b42 7719 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7720
7721 /* Compute aggregate route's extended community.
7722 */
b53e67a3 7723 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7724 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7725 aggregate,
7726 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7727
7728 /* Compute aggregate route's large community.
7729 */
1bcf3a96 7730 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7731 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7732 aggregate,
7733 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7734
7735 /* Retrieve aggregate route's as-path.
7736 */
7737 if (aggregate->aspath)
7738 aspath = aspath_dup(aggregate->aspath);
7739
7740 /* Retrieve aggregate route's community.
7741 */
7742 if (aggregate->community)
7743 community = community_dup(aggregate->community);
7744
7745 /* Retrieve aggregate route's ecommunity.
7746 */
7747 if (aggregate->ecommunity)
7748 ecommunity = ecommunity_dup(aggregate->ecommunity);
7749
7750 /* Retrieve aggregate route's lcommunity.
7751 */
7752 if (aggregate->lcommunity)
7753 lcommunity = lcommunity_dup(aggregate->lcommunity);
7754 }
7755
7756 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7757 aspath, community, ecommunity,
7758 lcommunity, atomic_aggregate, aggregate);
7759}
7760
7761static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7762 safi_t safi,
7763 struct bgp_path_info *pi,
7764 struct bgp_aggregate *aggregate,
5f040085 7765 const struct prefix *aggr_p)
fc968841
NT
7766{
7767 uint8_t origin;
7768 struct aspath *aspath = NULL;
7769 uint8_t atomic_aggregate = 0;
7770 struct community *community = NULL;
7771 struct ecommunity *ecommunity = NULL;
7772 struct lcommunity *lcommunity = NULL;
7773 unsigned long match = 0;
7774
a4559740 7775 /* If the bgp instance is being deleted or self peer is deleted
7776 * then do not create aggregate route
7777 */
7778 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7779 || (bgp->peer_self == NULL))
7780 return;
7781
fc968841
NT
7782 if (BGP_PATH_HOLDDOWN(pi))
7783 return;
7784
7785 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7786 return;
7787
4056a5f6
RZ
7788 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7789 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7790 match++;
fc968841 7791
365ab2e7 7792 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7793 && aggr_suppress_map_test(bgp, aggregate, pi))
7794 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7795 match++;
fc968841 7796
6aabb15d 7797 /*
365ab2e7 7798 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7799 * "unsuppressing" twice.
7800 */
7801 if (aggregate->match_med)
7802 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7803 true);
7804
fc968841
NT
7805 if (aggregate->count > 0)
7806 aggregate->count--;
7807
7808 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7809 aggregate->incomplete_origin_count--;
7810 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7811 aggregate->egp_origin_count--;
7812
7813 if (aggregate->as_set) {
7814 /* Remove as-path from aggregate.
7815 */
7816 bgp_remove_aspath_from_aggregate(aggregate,
7817 pi->attr->aspath);
7818
9a706b42 7819 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7820 /* Remove community from aggregate.
7821 */
7822 bgp_remove_community_from_aggregate(
9a706b42 7823 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7824
b53e67a3 7825 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7826 /* Remove ecommunity from aggregate.
7827 */
7828 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7829 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7830
1bcf3a96 7831 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7832 /* Remove lcommunity from aggregate.
7833 */
7834 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7835 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7836 }
7837
7838 /* If this node was suppressed, process the change. */
7839 if (match)
7840 bgp_process(bgp, pi->net, afi, safi);
7841
7842 origin = BGP_ORIGIN_IGP;
7843 if (aggregate->incomplete_origin_count > 0)
7844 origin = BGP_ORIGIN_INCOMPLETE;
7845 else if (aggregate->egp_origin_count > 0)
7846 origin = BGP_ORIGIN_EGP;
7847
229757f1
DA
7848 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7849 origin = aggregate->origin;
7850
fc968841
NT
7851 if (aggregate->as_set) {
7852 /* Retrieve aggregate route's as-path.
7853 */
7854 if (aggregate->aspath)
7855 aspath = aspath_dup(aggregate->aspath);
7856
7857 /* Retrieve aggregate route's community.
7858 */
7859 if (aggregate->community)
7860 community = community_dup(aggregate->community);
7861
7862 /* Retrieve aggregate route's ecommunity.
7863 */
7864 if (aggregate->ecommunity)
7865 ecommunity = ecommunity_dup(aggregate->ecommunity);
7866
7867 /* Retrieve aggregate route's lcommunity.
7868 */
7869 if (aggregate->lcommunity)
7870 lcommunity = lcommunity_dup(aggregate->lcommunity);
7871 }
7872
7873 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7874 aspath, community, ecommunity,
7875 lcommunity, atomic_aggregate, aggregate);
7876}
7877
5a1ae2c2 7878void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7879 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7880{
9bcb3eef
DS
7881 struct bgp_dest *child;
7882 struct bgp_dest *dest;
d62a17ae 7883 struct bgp_aggregate *aggregate;
7884 struct bgp_table *table;
718e3744 7885
d62a17ae 7886 table = bgp->aggregate[afi][safi];
f018db83 7887
d62a17ae 7888 /* No aggregates configured. */
7889 if (bgp_table_top_nolock(table) == NULL)
7890 return;
f018db83 7891
d62a17ae 7892 if (p->prefixlen == 0)
7893 return;
718e3744 7894
40381db7 7895 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7896 return;
718e3744 7897
a77e2f4b
S
7898 /* If suppress fib is enabled and route not installed
7899 * in FIB, do not update the aggregate route
7900 */
7901 if (!bgp_check_advertise(bgp, pi->net))
7902 return;
7903
d62a17ae 7904 child = bgp_node_get(table, p);
718e3744 7905
d62a17ae 7906 /* Aggregate address configuration check. */
9bcb3eef
DS
7907 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7908 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7909
9bcb3eef
DS
7910 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7911 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7912 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7913 aggregate);
d62a17ae 7914 }
b1e62edd 7915 }
9bcb3eef 7916 bgp_dest_unlock_node(child);
718e3744 7917}
7918
5a1ae2c2 7919void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7920 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7921{
9bcb3eef
DS
7922 struct bgp_dest *child;
7923 struct bgp_dest *dest;
d62a17ae 7924 struct bgp_aggregate *aggregate;
7925 struct bgp_table *table;
718e3744 7926
d62a17ae 7927 table = bgp->aggregate[afi][safi];
718e3744 7928
d62a17ae 7929 /* No aggregates configured. */
7930 if (bgp_table_top_nolock(table) == NULL)
7931 return;
718e3744 7932
d62a17ae 7933 if (p->prefixlen == 0)
7934 return;
718e3744 7935
d62a17ae 7936 child = bgp_node_get(table, p);
718e3744 7937
d62a17ae 7938 /* Aggregate address configuration check. */
9bcb3eef
DS
7939 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7940 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7941
9bcb3eef
DS
7942 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7943 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7944 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7945 aggregate, dest_p);
d62a17ae 7946 }
b1e62edd 7947 }
9bcb3eef 7948 bgp_dest_unlock_node(child);
d62a17ae 7949}
718e3744 7950
718e3744 7951/* Aggregate route attribute. */
7952#define AGGREGATE_SUMMARY_ONLY 1
7953#define AGGREGATE_AS_SET 1
fb29348a 7954#define AGGREGATE_AS_UNSET 0
718e3744 7955
229757f1
DA
7956static const char *bgp_origin2str(uint8_t origin)
7957{
7958 switch (origin) {
7959 case BGP_ORIGIN_IGP:
7960 return "igp";
7961 case BGP_ORIGIN_EGP:
7962 return "egp";
7963 case BGP_ORIGIN_INCOMPLETE:
7964 return "incomplete";
7965 }
7966 return "n/a";
7967}
7968
fdeb5a81 7969static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7970{
7971 switch (v_state) {
fdeb5a81
DS
7972 case RPKI_NOT_BEING_USED:
7973 return "not used";
7974 case RPKI_VALID:
b5b99af8 7975 return "valid";
fdeb5a81 7976 case RPKI_NOTFOUND:
b5b99af8 7977 return "not found";
fdeb5a81 7978 case RPKI_INVALID:
b5b99af8 7979 return "invalid";
b5b99af8 7980 }
fdeb5a81
DS
7981
7982 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7983 return "ERROR";
7984}
7985
585f1adc
IR
7986static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7987 afi_t afi, safi_t safi)
718e3744 7988{
585f1adc
IR
7989 VTY_DECLVAR_CONTEXT(bgp, bgp);
7990 int ret;
7991 struct prefix p;
9bcb3eef 7992 struct bgp_dest *dest;
d62a17ae 7993 struct bgp_aggregate *aggregate;
718e3744 7994
585f1adc
IR
7995 /* Convert string to prefix structure. */
7996 ret = str2prefix(prefix_str, &p);
7997 if (!ret) {
7998 vty_out(vty, "Malformed prefix\n");
7999 return CMD_WARNING_CONFIG_FAILED;
8000 }
8001 apply_mask(&p);
a4559740 8002
d62a17ae 8003 /* Old configuration check. */
585f1adc 8004 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8005 if (!dest) {
585f1adc
IR
8006 vty_out(vty,
8007 "%% There is no aggregate-address configuration.\n");
8008 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8009 }
f6269b4f 8010
9bcb3eef 8011 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8012 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8013 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8014 NULL, NULL, 0, aggregate);
d62a17ae 8015
8016 /* Unlock aggregate address configuration. */
9bcb3eef 8017 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8018
8019 if (aggregate->community)
8020 community_free(&aggregate->community);
8021
8022 if (aggregate->community_hash) {
8023 /* Delete all communities in the hash.
8024 */
8025 hash_clean(aggregate->community_hash,
8026 bgp_aggr_community_remove);
8027 /* Free up the community_hash.
8028 */
8029 hash_free(aggregate->community_hash);
8030 }
8031
8032 if (aggregate->ecommunity)
8033 ecommunity_free(&aggregate->ecommunity);
8034
8035 if (aggregate->ecommunity_hash) {
8036 /* Delete all ecommunities in the hash.
8037 */
8038 hash_clean(aggregate->ecommunity_hash,
8039 bgp_aggr_ecommunity_remove);
8040 /* Free up the ecommunity_hash.
8041 */
8042 hash_free(aggregate->ecommunity_hash);
8043 }
8044
8045 if (aggregate->lcommunity)
8046 lcommunity_free(&aggregate->lcommunity);
8047
8048 if (aggregate->lcommunity_hash) {
8049 /* Delete all lcommunities in the hash.
8050 */
8051 hash_clean(aggregate->lcommunity_hash,
8052 bgp_aggr_lcommunity_remove);
8053 /* Free up the lcommunity_hash.
8054 */
8055 hash_free(aggregate->lcommunity_hash);
8056 }
8057
8058 if (aggregate->aspath)
8059 aspath_free(aggregate->aspath);
8060
8061 if (aggregate->aspath_hash) {
8062 /* Delete all as-paths in the hash.
8063 */
8064 hash_clean(aggregate->aspath_hash,
8065 bgp_aggr_aspath_remove);
8066 /* Free up the aspath_hash.
8067 */
8068 hash_free(aggregate->aspath_hash);
8069 }
8070
d62a17ae 8071 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8072 bgp_dest_unlock_node(dest);
8073 bgp_dest_unlock_node(dest);
d62a17ae 8074
585f1adc 8075 return CMD_SUCCESS;
d62a17ae 8076}
8077
585f1adc
IR
8078static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8079 safi_t safi, const char *rmap,
8080 uint8_t summary_only, uint8_t as_set,
8081 uint8_t origin, bool match_med,
8082 const char *suppress_map)
d62a17ae 8083{
585f1adc 8084 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8085 int ret;
585f1adc 8086 struct prefix p;
9bcb3eef 8087 struct bgp_dest *dest;
d62a17ae 8088 struct bgp_aggregate *aggregate;
fb29348a 8089 uint8_t as_set_new = as_set;
d62a17ae 8090
365ab2e7 8091 if (suppress_map && summary_only) {
585f1adc 8092 vty_out(vty,
365ab2e7 8093 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8094 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8095 }
8096
585f1adc
IR
8097 /* Convert string to prefix structure. */
8098 ret = str2prefix(prefix_str, &p);
8099 if (!ret) {
8100 vty_out(vty, "Malformed prefix\n");
8101 return CMD_WARNING_CONFIG_FAILED;
8102 }
8103 apply_mask(&p);
d62a17ae 8104
585f1adc
IR
8105 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8106 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8107 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8108 prefix_str);
8109 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8110 }
8111
d62a17ae 8112 /* Old configuration check. */
585f1adc 8113 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8114 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8115
20894f50 8116 if (aggregate) {
585f1adc 8117 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8118 /* try to remove the old entry */
585f1adc 8119 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8120 if (ret) {
585f1adc 8121 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8122 bgp_dest_unlock_node(dest);
585f1adc 8123 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8124 }
8125 }
718e3744 8126
d62a17ae 8127 /* Make aggregate address structure. */
8128 aggregate = bgp_aggregate_new();
8129 aggregate->summary_only = summary_only;
6aabb15d 8130 aggregate->match_med = match_med;
fb29348a
DA
8131
8132 /* Network operators MUST NOT locally generate any new
8133 * announcements containing AS_SET or AS_CONFED_SET. If they have
8134 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8135 * SHOULD withdraw those routes and re-announce routes for the
8136 * aggregate or component prefixes (i.e., the more-specific routes
8137 * subsumed by the previously aggregated route) without AS_SET
8138 * or AS_CONFED_SET in the updates.
8139 */
7f972cd8 8140 if (bgp->reject_as_sets) {
fb29348a
DA
8141 if (as_set == AGGREGATE_AS_SET) {
8142 as_set_new = AGGREGATE_AS_UNSET;
8143 zlog_warn(
63efca0e 8144 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8145 __func__);
585f1adc 8146 vty_out(vty,
fb29348a
DA
8147 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8148 }
8149 }
8150
8151 aggregate->as_set = as_set_new;
d62a17ae 8152 aggregate->safi = safi;
229757f1
DA
8153 /* Override ORIGIN attribute if defined.
8154 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8155 * to IGP which is not what rfc4271 says.
8156 * This enables the same behavior, optionally.
8157 */
8158 aggregate->origin = origin;
20894f50
DA
8159
8160 if (rmap) {
8161 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8162 route_map_counter_decrement(aggregate->rmap.map);
8163 aggregate->rmap.name =
8164 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8165 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8166 route_map_counter_increment(aggregate->rmap.map);
8167 }
365ab2e7
RZ
8168
8169 if (suppress_map) {
8170 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8171 route_map_counter_decrement(aggregate->suppress_map);
8172
8173 aggregate->suppress_map_name =
8174 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8175 aggregate->suppress_map =
8176 route_map_lookup_by_name(aggregate->suppress_map_name);
8177 route_map_counter_increment(aggregate->suppress_map);
8178 }
8179
9bcb3eef 8180 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8181
d62a17ae 8182 /* Aggregate address insert into BGP routing table. */
585f1adc 8183 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8184
585f1adc 8185 return CMD_SUCCESS;
718e3744 8186}
8187
585f1adc
IR
8188DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8189 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8190 "as-set$as_set_s"
8191 "|summary-only$summary_only"
cacba915 8192 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8193 "|origin <egp|igp|incomplete>$origin_s"
8194 "|matching-MED-only$match_med"
cacba915 8195 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8196 "}]",
8197 NO_STR
8198 "Configure BGP aggregate entries\n"
764402fe
DA
8199 "Aggregate prefix\n"
8200 "Aggregate address\n"
8201 "Aggregate mask\n"
585f1adc
IR
8202 "Generate AS set path information\n"
8203 "Filter more specific routes from updates\n"
8204 "Apply route map to aggregate network\n"
8205 "Route map name\n"
8206 "BGP origin code\n"
8207 "Remote EGP\n"
8208 "Local IGP\n"
8209 "Unknown heritage\n"
8210 "Only aggregate routes with matching MED\n"
8211 "Suppress the selected more specific routes\n"
8212 "Route map with the route selectors\n")
8213{
8214 const char *prefix_s = NULL;
554b3b10 8215 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8216 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8217 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8218 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8219
554b3b10 8220 if (addr_str) {
7533cad7
QY
8221 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8222 sizeof(prefix_buf))
554b3b10
RZ
8223 == 0) {
8224 vty_out(vty, "%% Inconsistent address and mask\n");
8225 return CMD_WARNING_CONFIG_FAILED;
8226 }
585f1adc
IR
8227 prefix_s = prefix_buf;
8228 } else
8229 prefix_s = prefix_str;
37a87b8f 8230
585f1adc
IR
8231 if (origin_s) {
8232 if (strcmp(origin_s, "egp") == 0)
8233 origin = BGP_ORIGIN_EGP;
8234 else if (strcmp(origin_s, "igp") == 0)
8235 origin = BGP_ORIGIN_IGP;
8236 else if (strcmp(origin_s, "incomplete") == 0)
8237 origin = BGP_ORIGIN_INCOMPLETE;
8238 }
90e21f35 8239
585f1adc
IR
8240 if (as_set_s)
8241 as_set = AGGREGATE_AS_SET;
554b3b10 8242
585f1adc 8243 /* Handle configuration removal, otherwise installation. */
554b3b10 8244 if (no)
585f1adc
IR
8245 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8246
8247 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8248 summary_only != NULL, as_set, origin,
8249 match_med != NULL, suppress_map);
8250}
8251
8252DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8253 "[no] aggregate-address X:X::X:X/M$prefix [{"
8254 "as-set$as_set_s"
8255 "|summary-only$summary_only"
cacba915 8256 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8257 "|origin <egp|igp|incomplete>$origin_s"
8258 "|matching-MED-only$match_med"
cacba915 8259 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8260 "}]",
8261 NO_STR
8262 "Configure BGP aggregate entries\n"
8263 "Aggregate prefix\n"
8264 "Generate AS set path information\n"
8265 "Filter more specific routes from updates\n"
8266 "Apply route map to aggregate network\n"
8267 "Route map name\n"
8268 "BGP origin code\n"
8269 "Remote EGP\n"
8270 "Local IGP\n"
8271 "Unknown heritage\n"
8272 "Only aggregate routes with matching MED\n"
8273 "Suppress the selected more specific routes\n"
8274 "Route map with the route selectors\n")
8275{
8276 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8277 int as_set = AGGREGATE_AS_UNSET;
8278
8279 if (origin_s) {
8280 if (strcmp(origin_s, "egp") == 0)
8281 origin = BGP_ORIGIN_EGP;
8282 else if (strcmp(origin_s, "igp") == 0)
8283 origin = BGP_ORIGIN_IGP;
8284 else if (strcmp(origin_s, "incomplete") == 0)
8285 origin = BGP_ORIGIN_INCOMPLETE;
8286 }
8287
8288 if (as_set_s)
8289 as_set = AGGREGATE_AS_SET;
8290
8291 /* Handle configuration removal, otherwise installation. */
554b3b10 8292 if (no)
585f1adc
IR
8293 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8294 SAFI_UNICAST);
554b3b10 8295
585f1adc
IR
8296 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8297 rmap_name, summary_only != NULL, as_set,
8298 origin, match_med != NULL, suppress_map);
718e3744 8299}
8300
718e3744 8301/* Redistribute route treatment. */
d62a17ae 8302void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8303 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8304 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8305 enum blackhole_type bhtype, uint32_t metric,
8306 uint8_t type, unsigned short instance,
8307 route_tag_t tag)
d62a17ae 8308{
4b7e6066 8309 struct bgp_path_info *new;
40381db7
DS
8310 struct bgp_path_info *bpi;
8311 struct bgp_path_info rmap_path;
9bcb3eef 8312 struct bgp_dest *bn;
d62a17ae 8313 struct attr attr;
8314 struct attr *new_attr;
8315 afi_t afi;
b68885f9 8316 route_map_result_t ret;
d62a17ae 8317 struct bgp_redist *red;
8318
8319 /* Make default attribute. */
0f05ea43 8320 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8321 /*
8322 * This must not be NULL to satisfy Coverity SA
8323 */
8324 assert(attr.aspath);
9de1f7ff 8325
a4d82a8a 8326 switch (nhtype) {
9de1f7ff
DS
8327 case NEXTHOP_TYPE_IFINDEX:
8328 break;
8329 case NEXTHOP_TYPE_IPV4:
8330 case NEXTHOP_TYPE_IPV4_IFINDEX:
8331 attr.nexthop = nexthop->ipv4;
8332 break;
8333 case NEXTHOP_TYPE_IPV6:
8334 case NEXTHOP_TYPE_IPV6_IFINDEX:
8335 attr.mp_nexthop_global = nexthop->ipv6;
8336 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8337 break;
8338 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8339 switch (p->family) {
8340 case AF_INET:
9de1f7ff 8341 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8342 break;
8343 case AF_INET6:
9de1f7ff
DS
8344 memset(&attr.mp_nexthop_global, 0,
8345 sizeof(attr.mp_nexthop_global));
74489921 8346 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8347 break;
74489921 8348 }
0789eb69 8349 attr.bh_type = bhtype;
9de1f7ff 8350 break;
d62a17ae 8351 }
0789eb69 8352 attr.nh_type = nhtype;
74489921 8353 attr.nh_ifindex = ifindex;
f04a80a5 8354
d62a17ae 8355 attr.med = metric;
957f74c3 8356 attr.distance = distance;
d62a17ae 8357 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8358 attr.tag = tag;
718e3744 8359
d62a17ae 8360 afi = family2afi(p->family);
6aeb9e78 8361
d62a17ae 8362 red = bgp_redist_lookup(bgp, afi, type, instance);
8363 if (red) {
8364 struct attr attr_new;
718e3744 8365
d62a17ae 8366 /* Copy attribute for modification. */
6f4f49b2 8367 attr_new = attr;
718e3744 8368
d62a17ae 8369 if (red->redist_metric_flag)
8370 attr_new.med = red->redist_metric;
718e3744 8371
d62a17ae 8372 /* Apply route-map. */
8373 if (red->rmap.name) {
6006b807 8374 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8375 rmap_path.peer = bgp->peer_self;
8376 rmap_path.attr = &attr_new;
718e3744 8377
d62a17ae 8378 SET_FLAG(bgp->peer_self->rmap_type,
8379 PEER_RMAP_TYPE_REDISTRIBUTE);
8380
1782514f 8381 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8382
8383 bgp->peer_self->rmap_type = 0;
8384
8385 if (ret == RMAP_DENYMATCH) {
8386 /* Free uninterned attribute. */
8387 bgp_attr_flush(&attr_new);
8388
8389 /* Unintern original. */
8390 aspath_unintern(&attr.aspath);
8391 bgp_redistribute_delete(bgp, p, type, instance);
8392 return;
8393 }
8394 }
8395
637e5ba4 8396 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8397 bgp_attr_add_gshut_community(&attr_new);
8398
d62a17ae 8399 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8400 SAFI_UNICAST, p, NULL);
8401
8402 new_attr = bgp_attr_intern(&attr_new);
8403
9bcb3eef 8404 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8405 if (bpi->peer == bgp->peer_self
8406 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8407 break;
8408
40381db7 8409 if (bpi) {
d62a17ae 8410 /* Ensure the (source route) type is updated. */
40381db7
DS
8411 bpi->type = type;
8412 if (attrhash_cmp(bpi->attr, new_attr)
8413 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8414 bgp_attr_unintern(&new_attr);
8415 aspath_unintern(&attr.aspath);
9bcb3eef 8416 bgp_dest_unlock_node(bn);
d62a17ae 8417 return;
8418 } else {
8419 /* The attribute is changed. */
40381db7 8420 bgp_path_info_set_flag(bn, bpi,
18ee8310 8421 BGP_PATH_ATTR_CHANGED);
d62a17ae 8422
8423 /* Rewrite BGP route information. */
40381db7
DS
8424 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8425 bgp_path_info_restore(bn, bpi);
d62a17ae 8426 else
40381db7
DS
8427 bgp_aggregate_decrement(
8428 bgp, p, bpi, afi, SAFI_UNICAST);
8429 bgp_attr_unintern(&bpi->attr);
8430 bpi->attr = new_attr;
8431 bpi->uptime = bgp_clock();
d62a17ae 8432
8433 /* Process change. */
40381db7 8434 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8435 SAFI_UNICAST);
8436 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8437 bgp_dest_unlock_node(bn);
d62a17ae 8438 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8439
8440 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8441 || (bgp->inst_type
8442 == BGP_INSTANCE_TYPE_DEFAULT)) {
8443
8444 vpn_leak_from_vrf_update(
40381db7 8445 bgp_get_default(), bgp, bpi);
ddb5b488 8446 }
d62a17ae 8447 return;
8448 }
8449 }
8450
8451 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8452 bgp->peer_self, new_attr, bn);
1defdda8 8453 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8454
8455 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8456 bgp_path_info_add(bn, new);
9bcb3eef 8457 bgp_dest_unlock_node(bn);
be785e35 8458 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8459 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8460
8461 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8462 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8463
8464 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8465 }
d62a17ae 8466 }
8467
8468 /* Unintern original. */
8469 aspath_unintern(&attr.aspath);
718e3744 8470}
8471
d7c0a89a
QY
8472void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8473 unsigned short instance)
718e3744 8474{
d62a17ae 8475 afi_t afi;
9bcb3eef 8476 struct bgp_dest *dest;
40381db7 8477 struct bgp_path_info *pi;
d62a17ae 8478 struct bgp_redist *red;
718e3744 8479
d62a17ae 8480 afi = family2afi(p->family);
718e3744 8481
d62a17ae 8482 red = bgp_redist_lookup(bgp, afi, type, instance);
8483 if (red) {
9bcb3eef
DS
8484 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8485 SAFI_UNICAST, p, NULL);
d62a17ae 8486
9bcb3eef 8487 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8488 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8489 break;
8490
40381db7 8491 if (pi) {
ddb5b488
PZ
8492 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8493 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8494
8495 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8496 bgp, pi);
ddb5b488 8497 }
40381db7 8498 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8499 bgp_path_info_delete(dest, pi);
8500 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8501 }
9bcb3eef 8502 bgp_dest_unlock_node(dest);
d62a17ae 8503 }
8504}
8505
8506/* Withdraw specified route type's route. */
8507void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8508 unsigned short instance)
d62a17ae 8509{
9bcb3eef 8510 struct bgp_dest *dest;
40381db7 8511 struct bgp_path_info *pi;
d62a17ae 8512 struct bgp_table *table;
8513
8514 table = bgp->rib[afi][SAFI_UNICAST];
8515
9bcb3eef
DS
8516 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8517 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8518 if (pi->peer == bgp->peer_self && pi->type == type
8519 && pi->instance == instance)
d62a17ae 8520 break;
8521
40381db7 8522 if (pi) {
ddb5b488
PZ
8523 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8524 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8525
8526 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8527 bgp, pi);
ddb5b488 8528 }
9bcb3eef 8529 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8530 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8531 bgp_path_info_delete(dest, pi);
8532 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8533 }
718e3744 8534 }
718e3744 8535}
6b0655a2 8536
718e3744 8537/* Static function to display route. */
7d3cae70
DA
8538static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8539 struct vty *vty, json_object *json, bool wide)
718e3744 8540{
be054588 8541 int len = 0;
d62a17ae 8542 char buf[BUFSIZ];
718e3744 8543
d62a17ae 8544 if (p->family == AF_INET) {
c6462ff4 8545 if (!json) {
8228a9a7 8546 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8547 } else {
8548 json_object_string_add(json, "prefix",
8549 inet_ntop(p->family,
8550 &p->u.prefix, buf,
8551 BUFSIZ));
8552 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8553 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8554 json_object_int_add(json, "version", dest->version);
c6462ff4 8555 }
d62a17ae 8556 } else if (p->family == AF_ETHERNET) {
8228a9a7 8557 len = vty_out(vty, "%pFX", p);
b03b8898 8558 } else if (p->family == AF_EVPN) {
57f7feb6 8559 if (!json)
2dbe669b 8560 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8561 else
60466a63 8562 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8563 } else if (p->family == AF_FLOWSPEC) {
8564 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8565 json ?
8566 NLRI_STRING_FORMAT_JSON_SIMPLE :
8567 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8568 } else {
c6462ff4 8569 if (!json)
8228a9a7 8570 len = vty_out(vty, "%pFX", p);
50e05855
AD
8571 else {
8572 json_object_string_add(json, "prefix",
8573 inet_ntop(p->family,
8574 &p->u.prefix, buf,
8575 BUFSIZ));
8576 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8577 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8578 json_object_int_add(json, "version", dest->version);
37d4e0df 8579 }
9c92b5f7 8580 }
d62a17ae 8581
9c92b5f7 8582 if (!json) {
ae248832 8583 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8584 if (len < 1)
8585 vty_out(vty, "\n%*s", 20, " ");
8586 else
8587 vty_out(vty, "%*s", len, " ");
8588 }
718e3744 8589}
8590
d62a17ae 8591enum bgp_display_type {
8592 normal_list,
718e3744 8593};
8594
1d7260a1 8595const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8596{
8597 switch (reason) {
8598 case bgp_path_selection_none:
8599 return "Nothing to Select";
8600 case bgp_path_selection_first:
8601 return "First path received";
8602 case bgp_path_selection_evpn_sticky_mac:
8603 return "EVPN Sticky Mac";
8604 case bgp_path_selection_evpn_seq:
8605 return "EVPN sequence number";
8606 case bgp_path_selection_evpn_lower_ip:
8607 return "EVPN lower IP";
8608 case bgp_path_selection_evpn_local_path:
8609 return "EVPN local ES path";
8610 case bgp_path_selection_evpn_non_proxy:
8611 return "EVPN non proxy";
8612 case bgp_path_selection_weight:
8613 return "Weight";
8614 case bgp_path_selection_local_pref:
8615 return "Local Pref";
8616 case bgp_path_selection_local_route:
8617 return "Local Route";
8618 case bgp_path_selection_confed_as_path:
8619 return "Confederation based AS Path";
8620 case bgp_path_selection_as_path:
8621 return "AS Path";
8622 case bgp_path_selection_origin:
8623 return "Origin";
8624 case bgp_path_selection_med:
8625 return "MED";
8626 case bgp_path_selection_peer:
8627 return "Peer Type";
8628 case bgp_path_selection_confed:
8629 return "Confed Peer Type";
8630 case bgp_path_selection_igp_metric:
8631 return "IGP Metric";
8632 case bgp_path_selection_older:
8633 return "Older Path";
8634 case bgp_path_selection_router_id:
8635 return "Router ID";
8636 case bgp_path_selection_cluster_length:
bcab253c 8637 return "Cluster length";
bbb46eb5
DA
8638 case bgp_path_selection_stale:
8639 return "Path Staleness";
8640 case bgp_path_selection_local_configured:
8641 return "Locally configured route";
8642 case bgp_path_selection_neighbor_ip:
8643 return "Neighbor IP";
8644 case bgp_path_selection_default:
8645 return "Nothing left to compare";
8646 }
8647 return "Invalid (internal error)";
8648}
8649
18ee8310 8650/* Print the short form route status for a bgp_path_info */
4b7e6066 8651static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8652 struct bgp_path_info *path,
82c298be 8653 const struct prefix *p,
d62a17ae 8654 json_object *json_path)
718e3744 8655{
82c298be
DA
8656 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8657
d62a17ae 8658 if (json_path) {
b05a1c8b 8659
d62a17ae 8660 /* Route status display. */
9b6d8fcf 8661 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8662 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8663
9b6d8fcf 8664 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8665 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8666
4056a5f6 8667 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8668 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8669
9b6d8fcf
DS
8670 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8671 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8672 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8673
d62a17ae 8674 /* Selected */
9b6d8fcf 8675 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8676 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8677
9b6d8fcf 8678 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8679 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8680
bbb46eb5 8681 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8682 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8683 json_object_string_add(json_path, "selectionReason",
8684 bgp_path_selection_reason2str(
8685 path->net->reason));
8686 }
b05a1c8b 8687
9b6d8fcf 8688 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8689 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8690
d62a17ae 8691 /* Internal route. */
9b6d8fcf
DS
8692 if ((path->peer->as)
8693 && (path->peer->as == path->peer->local_as))
d62a17ae 8694 json_object_string_add(json_path, "pathFrom",
8695 "internal");
8696 else
8697 json_object_string_add(json_path, "pathFrom",
8698 "external");
b05a1c8b 8699
d62a17ae 8700 return;
8701 }
b05a1c8b 8702
82c298be
DA
8703 /* RPKI validation state */
8704 rpki_state =
8705 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8706
8707 if (rpki_state == RPKI_VALID)
8708 vty_out(vty, "V");
8709 else if (rpki_state == RPKI_INVALID)
8710 vty_out(vty, "I");
8711 else if (rpki_state == RPKI_NOTFOUND)
8712 vty_out(vty, "N");
8713
d62a17ae 8714 /* Route status display. */
9b6d8fcf 8715 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8716 vty_out(vty, "R");
9b6d8fcf 8717 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8718 vty_out(vty, "S");
4056a5f6 8719 else if (bgp_path_suppressed(path))
d62a17ae 8720 vty_out(vty, "s");
9b6d8fcf
DS
8721 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8722 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8723 vty_out(vty, "*");
8724 else
8725 vty_out(vty, " ");
8726
8727 /* Selected */
9b6d8fcf 8728 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8729 vty_out(vty, "h");
9b6d8fcf 8730 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8731 vty_out(vty, "d");
9b6d8fcf 8732 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8733 vty_out(vty, ">");
9b6d8fcf 8734 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8735 vty_out(vty, "=");
8736 else
8737 vty_out(vty, " ");
718e3744 8738
d62a17ae 8739 /* Internal route. */
9b6d8fcf
DS
8740 if (path->peer && (path->peer->as)
8741 && (path->peer->as == path->peer->local_as))
d62a17ae 8742 vty_out(vty, "i");
8743 else
8744 vty_out(vty, " ");
b40d939b 8745}
8746
2ba93fd6
DA
8747static char *bgp_nexthop_hostname(struct peer *peer,
8748 struct bgp_nexthop_cache *bnc)
25b5da8d 8749{
892fedb6 8750 if (peer->hostname
aef999a2 8751 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8752 return peer->hostname;
8753 return NULL;
8754}
8755
b40d939b 8756/* called from terminal list command */
bd494ec5 8757void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8758 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8759 json_object *json_paths, bool wide)
d62a17ae 8760{
aef999a2 8761 int len;
515c2602 8762 struct attr *attr = path->attr;
d62a17ae 8763 json_object *json_path = NULL;
8764 json_object *json_nexthops = NULL;
8765 json_object *json_nexthop_global = NULL;
8766 json_object *json_nexthop_ll = NULL;
6f214dd3 8767 json_object *json_ext_community = NULL;
9df8b37c 8768 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8769 bool nexthop_self =
9b6d8fcf 8770 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8771 bool nexthop_othervrf = false;
43089216 8772 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8773 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8774 char *nexthop_hostname =
8775 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8776 char esi_buf[ESI_STR_LEN];
d62a17ae 8777
8778 if (json_paths)
8779 json_path = json_object_new_object();
8780
8781 /* short status lead text */
82c298be 8782 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8783
8784 if (!json_paths) {
8785 /* print prefix and mask */
8786 if (!display)
7d3cae70 8787 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8788 else
ae248832 8789 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8790 } else {
7d3cae70 8791 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8792 }
47fc97cc 8793
9df8b37c
PZ
8794 /*
8795 * If vrf id of nexthop is different from that of prefix,
8796 * set up printable string to append
8797 */
9b6d8fcf 8798 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8799 const char *self = "";
8800
8801 if (nexthop_self)
8802 self = "<";
8803
8804 nexthop_othervrf = true;
9b6d8fcf 8805 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8806
9b6d8fcf 8807 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8808 snprintf(vrf_id_str, sizeof(vrf_id_str),
8809 "@%s%s", VRFID_NONE_STR, self);
8810 else
8811 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8812 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8813
9b6d8fcf
DS
8814 if (path->extra->bgp_orig->inst_type
8815 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8816
9b6d8fcf 8817 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8818 } else {
8819 const char *self = "";
8820
8821 if (nexthop_self)
8822 self = "<";
8823
8824 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8825 }
8826
445c2480
DS
8827 /*
8828 * For ENCAP and EVPN routes, nexthop address family is not
8829 * neccessarily the same as the prefix address family.
8830 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8831 * EVPN routes are also exchanged with a MP nexthop. Currently,
8832 * this
8833 * is only IPv4, the value will be present in either
8834 * attr->nexthop or
8835 * attr->mp_nexthop_global_in
8836 */
8837 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8838 char buf[BUFSIZ];
8839 char nexthop[128];
8840 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8841
8842 switch (af) {
8843 case AF_INET:
772270f3
QY
8844 snprintf(nexthop, sizeof(nexthop), "%s",
8845 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8846 BUFSIZ));
445c2480
DS
8847 break;
8848 case AF_INET6:
772270f3
QY
8849 snprintf(nexthop, sizeof(nexthop), "%s",
8850 inet_ntop(af, &attr->mp_nexthop_global, buf,
8851 BUFSIZ));
445c2480
DS
8852 break;
8853 default:
772270f3 8854 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8855 break;
d62a17ae 8856 }
d62a17ae 8857
445c2480
DS
8858 if (json_paths) {
8859 json_nexthop_global = json_object_new_object();
8860
515c2602
DA
8861 json_object_string_add(json_nexthop_global, "ip",
8862 nexthop);
8863
939a97f4 8864 if (path->peer->hostname)
515c2602
DA
8865 json_object_string_add(json_nexthop_global,
8866 "hostname",
939a97f4 8867 path->peer->hostname);
515c2602
DA
8868
8869 json_object_string_add(json_nexthop_global, "afi",
8870 (af == AF_INET) ? "ipv4"
8871 : "ipv6");
445c2480
DS
8872 json_object_boolean_true_add(json_nexthop_global,
8873 "used");
aef999a2
DA
8874 } else {
8875 if (nexthop_hostname)
8876 len = vty_out(vty, "%s(%s)%s", nexthop,
8877 nexthop_hostname, vrf_id_str);
8878 else
8879 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8880
ae248832 8881 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8882 if (len < 1)
8883 vty_out(vty, "\n%*s", 36, " ");
8884 else
8885 vty_out(vty, "%*s", len, " ");
8886 }
445c2480
DS
8887 } else if (safi == SAFI_EVPN) {
8888 if (json_paths) {
8889 json_nexthop_global = json_object_new_object();
8890
c949c771
DA
8891 json_object_string_addf(json_nexthop_global, "ip",
8892 "%pI4", &attr->nexthop);
515c2602 8893
939a97f4 8894 if (path->peer->hostname)
515c2602
DA
8895 json_object_string_add(json_nexthop_global,
8896 "hostname",
939a97f4 8897 path->peer->hostname);
515c2602 8898
a4d82a8a
PZ
8899 json_object_string_add(json_nexthop_global, "afi",
8900 "ipv4");
445c2480
DS
8901 json_object_boolean_true_add(json_nexthop_global,
8902 "used");
aef999a2
DA
8903 } else {
8904 if (nexthop_hostname)
8905 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8906 nexthop_hostname, vrf_id_str);
8907 else
8908 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8909 vrf_id_str);
8910
ae248832 8911 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8912 if (len < 1)
8913 vty_out(vty, "\n%*s", 36, " ");
8914 else
8915 vty_out(vty, "%*s", len, " ");
8916 }
d33fc23b 8917 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8918 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8919 if (json_paths) {
8920 json_nexthop_global = json_object_new_object();
515c2602 8921
026b914a
PG
8922 json_object_string_add(json_nexthop_global,
8923 "afi", "ipv4");
c949c771
DA
8924 json_object_string_addf(json_nexthop_global,
8925 "ip", "%pI4",
8926 &attr->nexthop);
515c2602 8927
939a97f4 8928 if (path->peer->hostname)
515c2602
DA
8929 json_object_string_add(
8930 json_nexthop_global, "hostname",
939a97f4 8931 path->peer->hostname);
515c2602 8932
50e05855
AD
8933 json_object_boolean_true_add(
8934 json_nexthop_global,
026b914a
PG
8935 "used");
8936 } else {
aef999a2
DA
8937 if (nexthop_hostname)
8938 len = vty_out(vty, "%pI4(%s)%s",
8939 &attr->nexthop,
8940 nexthop_hostname,
8941 vrf_id_str);
8942 else
8943 len = vty_out(vty, "%pI4%s",
8944 &attr->nexthop,
8945 vrf_id_str);
8946
ae248832 8947 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8948 if (len < 1)
8949 vty_out(vty, "\n%*s", 36, " ");
8950 else
8951 vty_out(vty, "%*s", len, " ");
026b914a
PG
8952 }
8953 }
d33fc23b 8954 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8955 if (json_paths) {
8956 json_nexthop_global = json_object_new_object();
d62a17ae 8957
c949c771
DA
8958 json_object_string_addf(json_nexthop_global, "ip",
8959 "%pI4", &attr->nexthop);
515c2602 8960
939a97f4 8961 if (path->peer->hostname)
515c2602
DA
8962 json_object_string_add(json_nexthop_global,
8963 "hostname",
939a97f4 8964 path->peer->hostname);
445c2480 8965
a4d82a8a
PZ
8966 json_object_string_add(json_nexthop_global, "afi",
8967 "ipv4");
445c2480
DS
8968 json_object_boolean_true_add(json_nexthop_global,
8969 "used");
8970 } else {
aef999a2
DA
8971 if (nexthop_hostname)
8972 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8973 nexthop_hostname, vrf_id_str);
8974 else
8975 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8976 vrf_id_str);
9df8b37c 8977
ae248832 8978 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8979 if (len < 1)
8980 vty_out(vty, "\n%*s", 36, " ");
8981 else
8982 vty_out(vty, "%*s", len, " ");
d62a17ae 8983 }
445c2480 8984 }
b05a1c8b 8985
445c2480 8986 /* IPv6 Next Hop */
a4d82a8a 8987 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8988 if (json_paths) {
8989 json_nexthop_global = json_object_new_object();
c949c771
DA
8990 json_object_string_addf(json_nexthop_global, "ip",
8991 "%pI6",
8992 &attr->mp_nexthop_global);
515c2602 8993
939a97f4 8994 if (path->peer->hostname)
515c2602
DA
8995 json_object_string_add(json_nexthop_global,
8996 "hostname",
939a97f4 8997 path->peer->hostname);
515c2602 8998
a4d82a8a
PZ
8999 json_object_string_add(json_nexthop_global, "afi",
9000 "ipv6");
9001 json_object_string_add(json_nexthop_global, "scope",
9002 "global");
445c2480
DS
9003
9004 /* We display both LL & GL if both have been
9005 * received */
0606039c
DA
9006 if ((attr->mp_nexthop_len
9007 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9008 || (path->peer->conf_if)) {
a4d82a8a 9009 json_nexthop_ll = json_object_new_object();
c949c771
DA
9010 json_object_string_addf(
9011 json_nexthop_ll, "ip", "%pI6",
9012 &attr->mp_nexthop_local);
515c2602 9013
939a97f4 9014 if (path->peer->hostname)
515c2602
DA
9015 json_object_string_add(
9016 json_nexthop_ll, "hostname",
939a97f4 9017 path->peer->hostname);
515c2602 9018
a4d82a8a
PZ
9019 json_object_string_add(json_nexthop_ll, "afi",
9020 "ipv6");
9021 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9022 "link-local");
d62a17ae 9023
a4d82a8a
PZ
9024 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9025 &attr->mp_nexthop_local)
445c2480
DS
9026 != 0)
9027 && !attr->mp_nexthop_prefer_global)
d62a17ae 9028 json_object_boolean_true_add(
a4d82a8a 9029 json_nexthop_ll, "used");
445c2480
DS
9030 else
9031 json_object_boolean_true_add(
a4d82a8a 9032 json_nexthop_global, "used");
445c2480
DS
9033 } else
9034 json_object_boolean_true_add(
9035 json_nexthop_global, "used");
9036 } else {
9037 /* Display LL if LL/Global both in table unless
9038 * prefer-global is set */
0606039c
DA
9039 if (((attr->mp_nexthop_len
9040 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9041 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9042 || (path->peer->conf_if)) {
9043 if (path->peer->conf_if) {
a4d82a8a 9044 len = vty_out(vty, "%s",
9b6d8fcf 9045 path->peer->conf_if);
ae248832
MK
9046 /* len of IPv6 addr + max len of def
9047 * ifname */
9048 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9049
9050 if (len < 1)
a4d82a8a 9051 vty_out(vty, "\n%*s", 36, " ");
445c2480 9052 else
a4d82a8a 9053 vty_out(vty, "%*s", len, " ");
d62a17ae 9054 } else {
aef999a2
DA
9055 if (nexthop_hostname)
9056 len = vty_out(
9057 vty, "%pI6(%s)%s",
9058 &attr->mp_nexthop_local,
9059 nexthop_hostname,
9060 vrf_id_str);
9061 else
9062 len = vty_out(
9063 vty, "%pI6%s",
9064 &attr->mp_nexthop_local,
9065 vrf_id_str);
9066
ae248832 9067 len = wide ? (41 - len) : (16 - len);
d62a17ae 9068
9069 if (len < 1)
a4d82a8a 9070 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9071 else
a4d82a8a 9072 vty_out(vty, "%*s", len, " ");
d62a17ae 9073 }
445c2480 9074 } else {
aef999a2
DA
9075 if (nexthop_hostname)
9076 len = vty_out(vty, "%pI6(%s)%s",
9077 &attr->mp_nexthop_global,
9078 nexthop_hostname,
9079 vrf_id_str);
9080 else
9081 len = vty_out(vty, "%pI6%s",
9082 &attr->mp_nexthop_global,
9083 vrf_id_str);
9084
ae248832 9085 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9086
9087 if (len < 1)
9088 vty_out(vty, "\n%*s", 36, " ");
9089 else
9090 vty_out(vty, "%*s", len, " ");
d62a17ae 9091 }
9092 }
445c2480 9093 }
718e3744 9094
445c2480
DS
9095 /* MED/Metric */
9096 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9097 if (json_paths)
50e05855 9098 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9099 else if (wide)
9100 vty_out(vty, "%7u", attr->med);
0fbac0b4 9101 else
445c2480 9102 vty_out(vty, "%10u", attr->med);
ae248832
MK
9103 else if (!json_paths) {
9104 if (wide)
9105 vty_out(vty, "%*s", 7, " ");
9106 else
9107 vty_out(vty, "%*s", 10, " ");
9108 }
d62a17ae 9109
445c2480
DS
9110 /* Local Pref */
9111 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9112 if (json_paths)
50e05855 9113 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9114 attr->local_pref);
9115 else
445c2480
DS
9116 vty_out(vty, "%7u", attr->local_pref);
9117 else if (!json_paths)
9118 vty_out(vty, " ");
d62a17ae 9119
445c2480
DS
9120 if (json_paths)
9121 json_object_int_add(json_path, "weight", attr->weight);
9122 else
9123 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9124
445c2480
DS
9125 if (json_paths) {
9126 char buf[BUFSIZ];
a4d82a8a
PZ
9127 json_object_string_add(
9128 json_path, "peerId",
9b6d8fcf 9129 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 9130 }
b05a1c8b 9131
445c2480
DS
9132 /* Print aspath */
9133 if (attr->aspath) {
0fbac0b4 9134 if (json_paths)
50e05855 9135 json_object_string_add(json_path, "path",
0fbac0b4
DA
9136 attr->aspath->str);
9137 else
445c2480 9138 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9139 }
f1aa5d8a 9140
445c2480
DS
9141 /* Print origin */
9142 if (json_paths)
a4d82a8a
PZ
9143 json_object_string_add(json_path, "origin",
9144 bgp_origin_long_str[attr->origin]);
445c2480
DS
9145 else
9146 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9147
9df8b37c 9148 if (json_paths) {
d071f237 9149 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9150 json_object_string_add(json_path, "esi",
9151 esi_to_str(&attr->esi,
9152 esi_buf, sizeof(esi_buf)));
9153 }
6f214dd3
CS
9154 if (safi == SAFI_EVPN &&
9155 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9156 json_ext_community = json_object_new_object();
b53e67a3
DA
9157 json_object_string_add(
9158 json_ext_community, "string",
9159 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9160 json_object_object_add(json_path,
9161 "extendedCommunity",
9162 json_ext_community);
9163 }
9164
9df8b37c
PZ
9165 if (nexthop_self)
9166 json_object_boolean_true_add(json_path,
9167 "announceNexthopSelf");
9168 if (nexthop_othervrf) {
9169 json_object_string_add(json_path, "nhVrfName",
9170 nexthop_vrfname);
9171
9172 json_object_int_add(json_path, "nhVrfId",
9173 ((nexthop_vrfid == VRF_UNKNOWN)
9174 ? -1
9175 : (int)nexthop_vrfid));
9176 }
9177 }
9178
d62a17ae 9179 if (json_paths) {
9180 if (json_nexthop_global || json_nexthop_ll) {
9181 json_nexthops = json_object_new_array();
f1aa5d8a 9182
d62a17ae 9183 if (json_nexthop_global)
9184 json_object_array_add(json_nexthops,
9185 json_nexthop_global);
f1aa5d8a 9186
d62a17ae 9187 if (json_nexthop_ll)
9188 json_object_array_add(json_nexthops,
9189 json_nexthop_ll);
f1aa5d8a 9190
d62a17ae 9191 json_object_object_add(json_path, "nexthops",
9192 json_nexthops);
9193 }
9194
9195 json_object_array_add(json_paths, json_path);
9196 } else {
9197 vty_out(vty, "\n");
6f214dd3 9198
b5e140c8 9199 if (safi == SAFI_EVPN) {
d071f237 9200 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9201 /* XXX - add these params to the json out */
b5e140c8 9202 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9203 vty_out(vty, "ESI:%s",
9204 esi_to_str(&attr->esi, esi_buf,
9205 sizeof(esi_buf)));
60605cbc 9206
229587fb 9207 vty_out(vty, "\n");
b5e140c8
AK
9208 }
9209 if (attr->flag &
9210 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9211 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9212 vty_out(vty, "%s\n",
9213 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9214 }
6f214dd3
CS
9215 }
9216
49e5a4a0 9217#ifdef ENABLE_BGP_VNC
d62a17ae 9218 /* prints an additional line, indented, with VNC info, if
9219 * present */
9220 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9221 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9222#endif
d62a17ae 9223 }
9224}
718e3744 9225
9226/* called from terminal list command */
7d3cae70
DA
9227void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9228 const struct prefix *p, struct attr *attr, safi_t safi,
9229 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9230{
9231 json_object *json_status = NULL;
9232 json_object *json_net = NULL;
aef999a2 9233 int len;
d62a17ae 9234 char buff[BUFSIZ];
dc387b0f 9235
d62a17ae 9236 /* Route status display. */
9237 if (use_json) {
9238 json_status = json_object_new_object();
9239 json_net = json_object_new_object();
9240 } else {
9241 vty_out(vty, "*");
9242 vty_out(vty, ">");
9243 vty_out(vty, " ");
9244 }
718e3744 9245
d62a17ae 9246 /* print prefix and mask */
50e05855 9247 if (use_json) {
dc387b0f
LK
9248 if (safi == SAFI_EVPN)
9249 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9250 else if (p->family == AF_INET || p->family == AF_INET6) {
9251 json_object_string_add(
9252 json_net, "addrPrefix",
9253 inet_ntop(p->family, &p->u.prefix, buff,
9254 BUFSIZ));
9255 json_object_int_add(json_net, "prefixLen",
9256 p->prefixlen);
67d7e256 9257 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9258 }
50e05855 9259 } else
7d3cae70 9260 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9261
9262 /* Print attribute */
9263 if (attr) {
9264 if (use_json) {
9265 if (p->family == AF_INET
9266 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9267 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9268 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9269 json_object_string_addf(
9270 json_net, "nextHop", "%pI4",
9271 &attr->mp_nexthop_global_in);
d62a17ae 9272 else
c949c771
DA
9273 json_object_string_addf(
9274 json_net, "nextHop", "%pI4",
9275 &attr->nexthop);
d62a17ae 9276 } else if (p->family == AF_INET6
9277 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9278 json_object_string_addf(
9279 json_net, "nextHopGlobal", "%pI6",
9280 &attr->mp_nexthop_global);
23d0a753
DA
9281 } else if (p->family == AF_EVPN
9282 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9283 json_object_string_addf(
9284 json_net, "nextHop", "%pI4",
9285 &attr->mp_nexthop_global_in);
23d0a753 9286 }
d62a17ae 9287
9288 if (attr->flag
9289 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9290 json_object_int_add(json_net, "metric",
9291 attr->med);
9292
0fbac0b4 9293 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9294 json_object_int_add(json_net, "locPrf",
0fbac0b4 9295 attr->local_pref);
d62a17ae 9296
9297 json_object_int_add(json_net, "weight", attr->weight);
9298
9299 /* Print aspath */
0fbac0b4 9300 if (attr->aspath)
50e05855 9301 json_object_string_add(json_net, "path",
0fbac0b4 9302 attr->aspath->str);
d62a17ae 9303
9304 /* Print origin */
9305 json_object_string_add(json_net, "bgpOriginCode",
9306 bgp_origin_str[attr->origin]);
9307 } else {
9308 if (p->family == AF_INET
9309 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9310 || safi == SAFI_EVPN
9311 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9312 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9313 || safi == SAFI_EVPN)
23d0a753
DA
9314 vty_out(vty, "%-16pI4",
9315 &attr->mp_nexthop_global_in);
ae248832 9316 else if (wide)
23d0a753 9317 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9318 else
23d0a753 9319 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9320 } else if (p->family == AF_INET6
9321 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9322 char buf[BUFSIZ];
9323
9324 len = vty_out(
9325 vty, "%s",
9326 inet_ntop(AF_INET6,
9327 &attr->mp_nexthop_global, buf,
9328 BUFSIZ));
ae248832 9329 len = wide ? (41 - len) : (16 - len);
d62a17ae 9330 if (len < 1)
9331 vty_out(vty, "\n%*s", 36, " ");
9332 else
9333 vty_out(vty, "%*s", len, " ");
9334 }
9335 if (attr->flag
9336 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9337 if (wide)
9338 vty_out(vty, "%7u", attr->med);
9339 else
9340 vty_out(vty, "%10u", attr->med);
9341 else if (wide)
9342 vty_out(vty, " ");
d62a17ae 9343 else
9344 vty_out(vty, " ");
718e3744 9345
d62a17ae 9346 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9347 vty_out(vty, "%7u", attr->local_pref);
9348 else
9349 vty_out(vty, " ");
9350
9351 vty_out(vty, "%7u ", attr->weight);
9352
9353 /* Print aspath */
9354 if (attr->aspath)
9355 aspath_print_vty(vty, "%s", attr->aspath, " ");
9356
9357 /* Print origin */
9358 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9359 }
9360 }
9361 if (use_json) {
9362 json_object_boolean_true_add(json_status, "*");
9363 json_object_boolean_true_add(json_status, ">");
9364 json_object_object_add(json_net, "appliedStatusSymbols",
9365 json_status);
1608ff77 9366
dc387b0f
LK
9367 prefix2str(p, buff, PREFIX_STRLEN);
9368 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9369 } else
9370 vty_out(vty, "\n");
9371}
9372
bd494ec5 9373void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9374 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9375 json_object *json)
9376{
9377 json_object *json_out = NULL;
9378 struct attr *attr;
9379 mpls_label_t label = MPLS_INVALID_LABEL;
9380
9b6d8fcf 9381 if (!path->extra)
d62a17ae 9382 return;
9383
9384 if (json)
9385 json_out = json_object_new_object();
9386
9387 /* short status lead text */
82c298be 9388 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9389
9390 /* print prefix and mask */
9391 if (json == NULL) {
9392 if (!display)
7d3cae70 9393 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9394 else
9395 vty_out(vty, "%*s", 17, " ");
9396 }
9397
9398 /* Print attribute */
9b6d8fcf 9399 attr = path->attr;
05864da7
DS
9400 if (((p->family == AF_INET)
9401 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9402 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9403 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9404 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9405 || safi == SAFI_EVPN) {
9406 if (json)
c949c771
DA
9407 json_object_string_addf(
9408 json_out, "mpNexthopGlobalIn", "%pI4",
9409 &attr->mp_nexthop_global_in);
05864da7 9410 else
23d0a753
DA
9411 vty_out(vty, "%-16pI4",
9412 &attr->mp_nexthop_global_in);
05864da7
DS
9413 } else {
9414 if (json)
c949c771
DA
9415 json_object_string_addf(json_out, "nexthop",
9416 "%pI4", &attr->nexthop);
05864da7 9417 else
23d0a753 9418 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9419 }
9420 } else if (((p->family == AF_INET6)
9421 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9422 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9423 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9424 char buf_a[512];
9425
9426 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9427 if (json)
c949c771
DA
9428 json_object_string_addf(
9429 json_out, "mpNexthopGlobalIn", "%pI6",
9430 &attr->mp_nexthop_global);
05864da7
DS
9431 else
9432 vty_out(vty, "%s",
9433 inet_ntop(AF_INET6,
9434 &attr->mp_nexthop_global,
9435 buf_a, sizeof(buf_a)));
9436 } else if (attr->mp_nexthop_len
9437 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9438 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9439 &attr->mp_nexthop_global,
9440 &attr->mp_nexthop_local);
9441 if (json)
9442 json_object_string_add(json_out,
9443 "mpNexthopGlobalLocal",
9444 buf_a);
9445 else
9446 vty_out(vty, "%s", buf_a);
d62a17ae 9447 }
9448 }
9449
9b6d8fcf 9450 label = decode_label(&path->extra->label[0]);
d62a17ae 9451
9452 if (bgp_is_valid_label(&label)) {
9453 if (json) {
9454 json_object_int_add(json_out, "notag", label);
9455 json_object_array_add(json, json_out);
9456 } else {
9457 vty_out(vty, "notag/%d", label);
9458 vty_out(vty, "\n");
9459 }
700ddfed
PG
9460 } else if (!json)
9461 vty_out(vty, "\n");
d62a17ae 9462}
718e3744 9463
bd494ec5 9464void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9465 struct bgp_path_info *path, int display,
d62a17ae 9466 json_object *json_paths)
718e3744 9467{
d62a17ae 9468 struct attr *attr;
d62a17ae 9469 json_object *json_path = NULL;
14f51eba
LK
9470 json_object *json_nexthop = NULL;
9471 json_object *json_overlay = NULL;
856ca177 9472
9b6d8fcf 9473 if (!path->extra)
d62a17ae 9474 return;
718e3744 9475
14f51eba
LK
9476 if (json_paths) {
9477 json_path = json_object_new_object();
9478 json_overlay = json_object_new_object();
9479 json_nexthop = json_object_new_object();
9480 }
9481
d62a17ae 9482 /* short status lead text */
82c298be 9483 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9484
d62a17ae 9485 /* print prefix and mask */
9486 if (!display)
7d3cae70 9487 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9488 else
9489 vty_out(vty, "%*s", 17, " ");
9490
9491 /* Print attribute */
9b6d8fcf 9492 attr = path->attr;
05864da7 9493 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9494
05864da7
DS
9495 switch (af) {
9496 case AF_INET:
05864da7 9497 if (!json_path) {
db66cf7c 9498 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9499 } else {
db66cf7c
DA
9500 json_object_string_addf(json_nexthop, "ip", "%pI4",
9501 &attr->mp_nexthop_global_in);
14f51eba 9502
05864da7 9503 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9504
05864da7
DS
9505 json_object_object_add(json_path, "nexthop",
9506 json_nexthop);
9507 }
9508 break;
9509 case AF_INET6:
05864da7 9510 if (!json_path) {
db66cf7c
DA
9511 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9512 &attr->mp_nexthop_local);
05864da7 9513 } else {
db66cf7c
DA
9514 json_object_string_addf(json_nexthop, "ipv6Global",
9515 "%pI6",
9516 &attr->mp_nexthop_global);
14f51eba 9517
db66cf7c
DA
9518 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9519 "%pI6",
9520 &attr->mp_nexthop_local);
14f51eba 9521
05864da7 9522 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9523
05864da7
DS
9524 json_object_object_add(json_path, "nexthop",
9525 json_nexthop);
9526 }
9527 break;
9528 default:
9529 if (!json_path) {
9530 vty_out(vty, "?");
9531 } else {
9532 json_object_string_add(json_nexthop, "Error",
9533 "Unsupported address-family");
77a2f8e5
DA
9534 json_object_string_add(json_nexthop, "error",
9535 "Unsupported address-family");
d62a17ae 9536 }
05864da7 9537 }
988258b4 9538
6c924775
DS
9539 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9540
05864da7 9541 if (!json_path)
db66cf7c 9542 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9543 else
db66cf7c 9544 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9545
b53e67a3 9546 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9547 char *mac = NULL;
9548 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9549 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9550 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9551
9552 if (routermac)
9553 mac = ecom_mac2str((char *)routermac->val);
9554 if (mac) {
9555 if (!json_path) {
c4efd0f4 9556 vty_out(vty, "/%s", mac);
05864da7
DS
9557 } else {
9558 json_object_string_add(json_overlay, "rmac",
9559 mac);
988258b4 9560 }
05864da7 9561 XFREE(MTYPE_TMP, mac);
988258b4 9562 }
05864da7 9563 }
718e3744 9564
05864da7
DS
9565 if (!json_path) {
9566 vty_out(vty, "\n");
9567 } else {
9568 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9569
05864da7 9570 json_object_array_add(json_paths, json_path);
14f51eba 9571 }
d62a17ae 9572}
718e3744 9573
d62a17ae 9574/* dampening route */
5f040085
DS
9575static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9576 struct bgp_path_info *path, int display,
9577 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9578 json_object *json_paths)
d62a17ae 9579{
e5be8c1d 9580 struct attr *attr = path->attr;
d62a17ae 9581 int len;
9582 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9583 json_object *json_path = NULL;
9584
9585 if (use_json)
9586 json_path = json_object_new_object();
d62a17ae 9587
9588 /* short status lead text */
e5be8c1d 9589 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9590
9591 /* print prefix and mask */
9592 if (!use_json) {
9593 if (!display)
7d3cae70 9594 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9595 else
9596 vty_out(vty, "%*s", 17, " ");
d62a17ae 9597
e5be8c1d
DA
9598 len = vty_out(vty, "%s", path->peer->host);
9599 len = 17 - len;
9600
9601 if (len < 1)
d62a17ae 9602 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9603 else
9604 vty_out(vty, "%*s", len, " ");
d62a17ae 9605
9b6d8fcf
DS
9606 vty_out(vty, "%s ",
9607 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9608 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9609 use_json, NULL));
d62a17ae 9610
e5be8c1d 9611 if (attr->aspath)
05864da7 9612 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9613
05864da7
DS
9614 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9615
d62a17ae 9616 vty_out(vty, "\n");
e5be8c1d
DA
9617 } else {
9618 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9619 safi, use_json, json_path);
9620
9621 if (attr->aspath)
9622 json_object_string_add(json_path, "asPath",
9623 attr->aspath->str);
9624
9625 json_object_string_add(json_path, "origin",
9626 bgp_origin_str[attr->origin]);
9627 json_object_string_add(json_path, "peerHost", path->peer->host);
9628
9629 json_object_array_add(json_paths, json_path);
9630 }
d62a17ae 9631}
718e3744 9632
d62a17ae 9633/* flap route */
5f040085
DS
9634static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9635 struct bgp_path_info *path, int display,
9636 afi_t afi, safi_t safi, bool use_json,
31258046 9637 json_object *json_paths)
784d3a42 9638{
31258046 9639 struct attr *attr = path->attr;
d62a17ae 9640 struct bgp_damp_info *bdi;
9641 char timebuf[BGP_UPTIME_LEN];
9642 int len;
31258046 9643 json_object *json_path = NULL;
784d3a42 9644
9b6d8fcf 9645 if (!path->extra)
d62a17ae 9646 return;
784d3a42 9647
31258046
DA
9648 if (use_json)
9649 json_path = json_object_new_object();
9650
9b6d8fcf 9651 bdi = path->extra->damp_info;
784d3a42 9652
d62a17ae 9653 /* short status lead text */
31258046 9654 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9655
d62a17ae 9656 if (!use_json) {
9657 if (!display)
7d3cae70 9658 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9659 else
9660 vty_out(vty, "%*s", 17, " ");
784d3a42 9661
31258046
DA
9662 len = vty_out(vty, "%s", path->peer->host);
9663 len = 16 - len;
9664 if (len < 1)
d62a17ae 9665 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9666 else
9667 vty_out(vty, "%*s", len, " ");
784d3a42 9668
31258046
DA
9669 len = vty_out(vty, "%d", bdi->flap);
9670 len = 5 - len;
9671 if (len < 1)
d62a17ae 9672 vty_out(vty, " ");
d62a17ae 9673 else
9674 vty_out(vty, "%*s", len, " ");
d62a17ae 9675
996c9314
LB
9676 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9677 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9678
31258046
DA
9679 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9680 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9681 vty_out(vty, "%s ",
9b6d8fcf 9682 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9683 BGP_UPTIME_LEN, afi,
31258046
DA
9684 safi, use_json, NULL));
9685 else
d62a17ae 9686 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9687
31258046 9688 if (attr->aspath)
05864da7 9689 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9690
05864da7
DS
9691 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9692
d62a17ae 9693 vty_out(vty, "\n");
31258046
DA
9694 } else {
9695 json_object_string_add(json_path, "peerHost", path->peer->host);
9696 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9697
9698 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9699 json_path);
9700
9701 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9702 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9703 bgp_damp_reuse_time_vty(vty, path, timebuf,
9704 BGP_UPTIME_LEN, afi, safi,
9705 use_json, json_path);
9706
9707 if (attr->aspath)
9708 json_object_string_add(json_path, "asPath",
9709 attr->aspath->str);
9710
9711 json_object_string_add(json_path, "origin",
9712 bgp_origin_str[attr->origin]);
9713
9714 json_object_array_add(json_paths, json_path);
9715 }
d62a17ae 9716}
9717
9718static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9719 int *first, const char *header,
9720 json_object *json_adv_to)
9721{
9722 char buf1[INET6_ADDRSTRLEN];
9723 json_object *json_peer = NULL;
9724
9725 if (json_adv_to) {
9726 /* 'advertised-to' is a dictionary of peers we have advertised
9727 * this
9728 * prefix too. The key is the peer's IP or swpX, the value is
9729 * the
9730 * hostname if we know it and "" if not.
9731 */
9732 json_peer = json_object_new_object();
9733
9734 if (peer->hostname)
9735 json_object_string_add(json_peer, "hostname",
9736 peer->hostname);
9737
9738 if (peer->conf_if)
9739 json_object_object_add(json_adv_to, peer->conf_if,
9740 json_peer);
9741 else
9742 json_object_object_add(
9743 json_adv_to,
9744 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9745 json_peer);
9746 } else {
9747 if (*first) {
9748 vty_out(vty, "%s", header);
9749 *first = 0;
9750 }
9751
9752 if (peer->hostname
892fedb6 9753 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9754 if (peer->conf_if)
9755 vty_out(vty, " %s(%s)", peer->hostname,
9756 peer->conf_if);
9757 else
9758 vty_out(vty, " %s(%s)", peer->hostname,
9759 sockunion2str(&peer->su, buf1,
9760 SU_ADDRSTRLEN));
9761 } else {
9762 if (peer->conf_if)
9763 vty_out(vty, " %s", peer->conf_if);
9764 else
9765 vty_out(vty, " %s",
9766 sockunion2str(&peer->su, buf1,
9767 SU_ADDRSTRLEN));
9768 }
9769 }
784d3a42
PG
9770}
9771
dcc68b5e
MS
9772static void route_vty_out_tx_ids(struct vty *vty,
9773 struct bgp_addpath_info_data *d)
9774{
9775 int i;
9776
9777 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9778 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9779 d->addpath_tx_id[i],
9780 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9781 }
9782}
9783
5e4d4c8a 9784static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9785 struct bgp_path_info *pi,
9786 struct attr *attr,
9787 json_object *json_path)
5e4d4c8a
AK
9788{
9789 char esi_buf[ESI_STR_LEN];
9790 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9791 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9792 ATTR_ES_PEER_ROUTER);
9793 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9794 ATTR_ES_PEER_ACTIVE);
9795 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9796 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9797 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9798 if (json_path) {
9799 json_object *json_es_info = NULL;
9800
9801 json_object_string_add(
9802 json_path, "esi",
9803 esi_buf);
9804 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9805 json_es_info = json_object_new_object();
9806 if (es_local)
9807 json_object_boolean_true_add(
9808 json_es_info, "localEs");
9809 if (peer_active)
9810 json_object_boolean_true_add(
9811 json_es_info, "peerActive");
9812 if (peer_proxy)
9813 json_object_boolean_true_add(
9814 json_es_info, "peerProxy");
9815 if (peer_router)
9816 json_object_boolean_true_add(
9817 json_es_info, "peerRouter");
9818 if (attr->mm_sync_seqnum)
9819 json_object_int_add(
9820 json_es_info, "peerSeq",
9821 attr->mm_sync_seqnum);
9822 json_object_object_add(
9823 json_path, "es_info",
9824 json_es_info);
9825 }
9826 } else {
9827 if (bgp_evpn_attr_is_sync(attr))
9828 vty_out(vty,
9829 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9830 esi_buf,
9831 es_local ? "local-es":"",
9832 peer_proxy ? "proxy " : "",
9833 peer_active ? "active ":"",
9834 peer_router ? "router ":"",
9835 attr->mm_sync_seqnum);
9836 else
9837 vty_out(vty, " ESI %s %s\n",
9838 esi_buf,
9839 es_local ? "local-es":"");
9840 }
9841}
9842
4933eaaf
DS
9843void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9844 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9845 enum rpki_states rpki_curr_state,
9846 json_object *json_paths)
d62a17ae 9847{
9848 char buf[INET6_ADDRSTRLEN];
9849 char buf1[BUFSIZ];
515c2602 9850 struct attr *attr = path->attr;
d62a17ae 9851 time_t tbuf;
9852 json_object *json_bestpath = NULL;
9853 json_object *json_cluster_list = NULL;
9854 json_object *json_cluster_list_list = NULL;
9855 json_object *json_ext_community = NULL;
9856 json_object *json_last_update = NULL;
7fd077aa 9857 json_object *json_pmsi = NULL;
d62a17ae 9858 json_object *json_nexthop_global = NULL;
9859 json_object *json_nexthop_ll = NULL;
9860 json_object *json_nexthops = NULL;
9861 json_object *json_path = NULL;
9862 json_object *json_peer = NULL;
9863 json_object *json_string = NULL;
9864 json_object *json_adv_to = NULL;
9865 int first = 0;
9866 struct listnode *node, *nnode;
9867 struct peer *peer;
be92fc9f 9868 bool addpath_capable;
d62a17ae 9869 int has_adj;
9870 unsigned int first_as;
1defdda8 9871 bool nexthop_self =
9b6d8fcf 9872 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9873 int i;
2ba93fd6
DA
9874 char *nexthop_hostname =
9875 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
9876 uint32_t ttl = 0;
9877 uint32_t bos = 0;
9878 uint32_t exp = 0;
9879 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 9880
9881 if (json_paths) {
9882 json_path = json_object_new_object();
9883 json_peer = json_object_new_object();
9884 json_nexthop_global = json_object_new_object();
9885 }
9886
8304dabf
AD
9887 if (safi == SAFI_EVPN) {
9888 if (!json_paths)
9889 vty_out(vty, " Route %pRN", bn);
9890 }
9891
44c69747 9892 if (path->extra) {
b57ba6d2 9893 char tag_buf[30];
d62a17ae 9894
d62a17ae 9895 tag_buf[0] = '\0';
9b6d8fcf
DS
9896 if (path->extra && path->extra->num_labels) {
9897 bgp_evpn_label2str(path->extra->label,
9898 path->extra->num_labels, tag_buf,
a4d82a8a 9899 sizeof(tag_buf));
d62a17ae 9900 }
d7325ee7 9901 if (safi == SAFI_EVPN) {
44c69747 9902 if (!json_paths) {
44c69747
LK
9903 if (tag_buf[0] != '\0')
9904 vty_out(vty, " VNI %s", tag_buf);
44c69747 9905 } else {
77a2f8e5 9906 if (tag_buf[0]) {
44c69747
LK
9907 json_object_string_add(json_path, "VNI",
9908 tag_buf);
77a2f8e5
DA
9909 json_object_string_add(json_path, "vni",
9910 tag_buf);
9911 }
44c69747 9912 }
d7325ee7
DD
9913 }
9914
44c69747 9915 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9916 struct bgp_path_info *parent_ri;
9bcb3eef 9917 struct bgp_dest *dest, *pdest;
d62a17ae 9918
9b6d8fcf 9919 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9920 dest = parent_ri->net;
9921 if (dest && dest->pdest) {
9922 pdest = dest->pdest;
9923 prefix_rd2str(
9924 (struct prefix_rd *)bgp_dest_get_prefix(
9925 pdest),
9926 buf1, sizeof(buf1));
d7325ee7 9927 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9928 vty_out(vty,
58bff4d1 9929 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9930 buf1,
9931 (struct prefix_evpn *)
9932 bgp_dest_get_prefix(
9933 dest),
9934 tag_buf);
58bff4d1
AK
9935 if (attr->es_flags & ATTR_ES_L3_NHG)
9936 vty_out(vty, ", L3NHG %s",
9937 (attr->es_flags
9938 & ATTR_ES_L3_NHG_ACTIVE)
9939 ? "active"
9940 : "inactive");
9941 vty_out(vty, "\n");
9942
d7325ee7 9943 } else
2dbe669b
DA
9944 vty_out(vty,
9945 " Imported from %s:%pFX\n",
9946 buf1,
9947 (struct prefix_evpn *)
9948 bgp_dest_get_prefix(
9949 dest));
d62a17ae 9950 }
9951 }
9952 }
d62a17ae 9953
8304dabf
AD
9954 if (safi == SAFI_EVPN
9955 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9956 char gwip_buf[INET6_ADDRSTRLEN];
9957
860e740b
IR
9958 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
9959 sizeof(gwip_buf));
8304dabf
AD
9960
9961 if (json_paths)
9962 json_object_string_add(json_path, "gatewayIP",
9963 gwip_buf);
9964 else
9965 vty_out(vty, " Gateway IP %s", gwip_buf);
9966 }
9967
9968 if (safi == SAFI_EVPN)
9969 vty_out(vty, "\n");
9970
05864da7
DS
9971 /* Line1 display AS-path, Aggregator */
9972 if (attr->aspath) {
9973 if (json_paths) {
9974 if (!attr->aspath->json)
9975 aspath_str_update(attr->aspath, true);
9976 json_object_lock(attr->aspath->json);
9977 json_object_object_add(json_path, "aspath",
9978 attr->aspath->json);
9979 } else {
9980 if (attr->aspath->segments)
9981 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9982 else
05864da7 9983 vty_out(vty, " Local");
d62a17ae 9984 }
05864da7 9985 }
d62a17ae 9986
05864da7
DS
9987 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9988 if (json_paths)
9989 json_object_boolean_true_add(json_path, "removed");
9990 else
9991 vty_out(vty, ", (removed)");
9992 }
d62a17ae 9993
05864da7
DS
9994 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9995 if (json_paths)
9996 json_object_boolean_true_add(json_path, "stale");
9997 else
9998 vty_out(vty, ", (stale)");
9999 }
d62a17ae 10000
05864da7
DS
10001 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10002 if (json_paths) {
10003 json_object_int_add(json_path, "aggregatorAs",
10004 attr->aggregator_as);
c949c771
DA
10005 json_object_string_addf(json_path, "aggregatorId",
10006 "%pI4", &attr->aggregator_addr);
05864da7 10007 } else {
88d495a9
DA
10008 vty_out(vty, ", (aggregated by %u %pI4)",
10009 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10010 }
05864da7 10011 }
d62a17ae 10012
05864da7
DS
10013 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10014 PEER_FLAG_REFLECTOR_CLIENT)) {
10015 if (json_paths)
10016 json_object_boolean_true_add(json_path,
10017 "rxedFromRrClient");
10018 else
10019 vty_out(vty, ", (Received from a RR-client)");
10020 }
d62a17ae 10021
05864da7
DS
10022 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10023 PEER_FLAG_RSERVER_CLIENT)) {
10024 if (json_paths)
10025 json_object_boolean_true_add(json_path,
10026 "rxedFromRsClient");
10027 else
10028 vty_out(vty, ", (Received from a RS-client)");
10029 }
d62a17ae 10030
05864da7
DS
10031 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10032 if (json_paths)
10033 json_object_boolean_true_add(json_path,
10034 "dampeningHistoryEntry");
10035 else
10036 vty_out(vty, ", (history entry)");
10037 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10038 if (json_paths)
10039 json_object_boolean_true_add(json_path,
10040 "dampeningSuppressed");
10041 else
10042 vty_out(vty, ", (suppressed due to dampening)");
10043 }
d62a17ae 10044
05864da7
DS
10045 if (!json_paths)
10046 vty_out(vty, "\n");
d62a17ae 10047
05864da7
DS
10048 /* Line2 display Next-hop, Neighbor, Router-id */
10049 /* Display the nexthop */
9bcb3eef 10050 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10051
10052 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10053 || bn_p->family == AF_EVPN)
05864da7
DS
10054 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10055 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10056 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10057 || safi == SAFI_EVPN) {
515c2602 10058 if (json_paths) {
c949c771
DA
10059 json_object_string_addf(
10060 json_nexthop_global, "ip", "%pI4",
10061 &attr->mp_nexthop_global_in);
515c2602 10062
939a97f4 10063 if (path->peer->hostname)
515c2602
DA
10064 json_object_string_add(
10065 json_nexthop_global, "hostname",
939a97f4 10066 path->peer->hostname);
aef999a2
DA
10067 } else {
10068 if (nexthop_hostname)
10069 vty_out(vty, " %pI4(%s)",
10070 &attr->mp_nexthop_global_in,
10071 nexthop_hostname);
10072 else
10073 vty_out(vty, " %pI4",
10074 &attr->mp_nexthop_global_in);
10075 }
d62a17ae 10076 } else {
515c2602 10077 if (json_paths) {
c949c771
DA
10078 json_object_string_addf(json_nexthop_global,
10079 "ip", "%pI4",
10080 &attr->nexthop);
515c2602 10081
939a97f4 10082 if (path->peer->hostname)
515c2602
DA
10083 json_object_string_add(
10084 json_nexthop_global, "hostname",
939a97f4 10085 path->peer->hostname);
aef999a2
DA
10086 } else {
10087 if (nexthop_hostname)
10088 vty_out(vty, " %pI4(%s)",
10089 &attr->nexthop,
10090 nexthop_hostname);
10091 else
10092 vty_out(vty, " %pI4",
10093 &attr->nexthop);
10094 }
d62a17ae 10095 }
10096
05864da7
DS
10097 if (json_paths)
10098 json_object_string_add(json_nexthop_global, "afi",
10099 "ipv4");
10100 } else {
10101 if (json_paths) {
c949c771
DA
10102 json_object_string_addf(json_nexthop_global, "ip",
10103 "%pI6",
10104 &attr->mp_nexthop_global);
515c2602 10105
939a97f4 10106 if (path->peer->hostname)
515c2602
DA
10107 json_object_string_add(json_nexthop_global,
10108 "hostname",
939a97f4 10109 path->peer->hostname);
515c2602 10110
05864da7
DS
10111 json_object_string_add(json_nexthop_global, "afi",
10112 "ipv6");
10113 json_object_string_add(json_nexthop_global, "scope",
10114 "global");
10115 } else {
aef999a2
DA
10116 if (nexthop_hostname)
10117 vty_out(vty, " %pI6(%s)",
10118 &attr->mp_nexthop_global,
10119 nexthop_hostname);
10120 else
10121 vty_out(vty, " %pI6",
10122 &attr->mp_nexthop_global);
d62a17ae 10123 }
05864da7 10124 }
d62a17ae 10125
05864da7
DS
10126 /* Display the IGP cost or 'inaccessible' */
10127 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10128 if (json_paths)
10129 json_object_boolean_false_add(json_nexthop_global,
10130 "accessible");
10131 else
10132 vty_out(vty, " (inaccessible)");
10133 } else {
10134 if (path->extra && path->extra->igpmetric) {
d62a17ae 10135 if (json_paths)
05864da7
DS
10136 json_object_int_add(json_nexthop_global,
10137 "metric",
10138 path->extra->igpmetric);
d62a17ae 10139 else
05864da7
DS
10140 vty_out(vty, " (metric %u)",
10141 path->extra->igpmetric);
d62a17ae 10142 }
10143
05864da7 10144 /* IGP cost is 0, display this only for json */
d62a17ae 10145 else {
d62a17ae 10146 if (json_paths)
05864da7
DS
10147 json_object_int_add(json_nexthop_global,
10148 "metric", 0);
d62a17ae 10149 }
d62a17ae 10150
05864da7
DS
10151 if (json_paths)
10152 json_object_boolean_true_add(json_nexthop_global,
10153 "accessible");
10154 }
d62a17ae 10155
05864da7
DS
10156 /* Display peer "from" output */
10157 /* This path was originated locally */
10158 if (path->peer == bgp->peer_self) {
d62a17ae 10159
05864da7 10160 if (safi == SAFI_EVPN
b54892e0 10161 || (bn_p->family == AF_INET
05864da7 10162 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10163 if (json_paths)
05864da7
DS
10164 json_object_string_add(json_peer, "peerId",
10165 "0.0.0.0");
d62a17ae 10166 else
05864da7
DS
10167 vty_out(vty, " from 0.0.0.0 ");
10168 } else {
d62a17ae 10169 if (json_paths)
05864da7
DS
10170 json_object_string_add(json_peer, "peerId",
10171 "::");
d62a17ae 10172 else
05864da7 10173 vty_out(vty, " from :: ");
d62a17ae 10174 }
d62a17ae 10175
4e9a9863 10176 if (json_paths)
c949c771
DA
10177 json_object_string_addf(json_peer, "routerId", "%pI4",
10178 &bgp->router_id);
4e9a9863 10179 else
23d0a753 10180 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10181 }
d62a17ae 10182
05864da7
DS
10183 /* We RXed this path from one of our peers */
10184 else {
10185
10186 if (json_paths) {
10187 json_object_string_add(json_peer, "peerId",
10188 sockunion2str(&path->peer->su,
10189 buf,
10190 SU_ADDRSTRLEN));
c949c771
DA
10191 json_object_string_addf(json_peer, "routerId", "%pI4",
10192 &path->peer->remote_id);
05864da7
DS
10193
10194 if (path->peer->hostname)
10195 json_object_string_add(json_peer, "hostname",
10196 path->peer->hostname);
10197
10198 if (path->peer->domainname)
10199 json_object_string_add(json_peer, "domainname",
10200 path->peer->domainname);
10201
10202 if (path->peer->conf_if)
10203 json_object_string_add(json_peer, "interface",
10204 path->peer->conf_if);
10205 } else {
10206 if (path->peer->conf_if) {
10207 if (path->peer->hostname
892fedb6
DA
10208 && CHECK_FLAG(path->peer->bgp->flags,
10209 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10210 vty_out(vty, " from %s(%s)",
10211 path->peer->hostname,
10212 path->peer->conf_if);
d62a17ae 10213 else
05864da7 10214 vty_out(vty, " from %s",
9b6d8fcf 10215 path->peer->conf_if);
d62a17ae 10216 } else {
05864da7 10217 if (path->peer->hostname
892fedb6
DA
10218 && CHECK_FLAG(path->peer->bgp->flags,
10219 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10220 vty_out(vty, " from %s(%s)",
10221 path->peer->hostname,
10222 path->peer->host);
d62a17ae 10223 else
05864da7
DS
10224 vty_out(vty, " from %s",
10225 sockunion2str(&path->peer->su,
10226 buf,
10227 SU_ADDRSTRLEN));
d62a17ae 10228 }
d62a17ae 10229
05864da7 10230 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10231 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10232 else
10233 vty_out(vty, " (%s)",
10234 inet_ntop(AF_INET,
10235 &path->peer->remote_id, buf1,
10236 sizeof(buf1)));
d62a17ae 10237 }
05864da7 10238 }
9df8b37c 10239
05864da7
DS
10240 /*
10241 * Note when vrfid of nexthop is different from that of prefix
10242 */
10243 if (path->extra && path->extra->bgp_orig) {
10244 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10245
05864da7
DS
10246 if (json_paths) {
10247 const char *vn;
9df8b37c 10248
05864da7
DS
10249 if (path->extra->bgp_orig->inst_type
10250 == BGP_INSTANCE_TYPE_DEFAULT)
10251 vn = VRF_DEFAULT_NAME;
10252 else
10253 vn = path->extra->bgp_orig->name;
9df8b37c 10254
05864da7 10255 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10256
05864da7
DS
10257 if (nexthop_vrfid == VRF_UNKNOWN) {
10258 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10259 } else {
05864da7
DS
10260 json_object_int_add(json_path, "nhVrfId",
10261 (int)nexthop_vrfid);
9df8b37c 10262 }
05864da7
DS
10263 } else {
10264 if (nexthop_vrfid == VRF_UNKNOWN)
10265 vty_out(vty, " vrf ?");
137147c6
DS
10266 else {
10267 struct vrf *vrf;
10268
10269 vrf = vrf_lookup_by_id(nexthop_vrfid);
10270 vty_out(vty, " vrf %s(%u)",
10271 VRF_LOGNAME(vrf), nexthop_vrfid);
10272 }
9df8b37c 10273 }
05864da7 10274 }
9df8b37c 10275
05864da7
DS
10276 if (nexthop_self) {
10277 if (json_paths) {
10278 json_object_boolean_true_add(json_path,
10279 "announceNexthopSelf");
10280 } else {
10281 vty_out(vty, " announce-nh-self");
9df8b37c 10282 }
05864da7 10283 }
9df8b37c 10284
05864da7
DS
10285 if (!json_paths)
10286 vty_out(vty, "\n");
d62a17ae 10287
05864da7
DS
10288 /* display the link-local nexthop */
10289 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10290 if (json_paths) {
10291 json_nexthop_ll = json_object_new_object();
c949c771
DA
10292 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10293 &attr->mp_nexthop_local);
515c2602 10294
939a97f4 10295 if (path->peer->hostname)
515c2602
DA
10296 json_object_string_add(json_nexthop_ll,
10297 "hostname",
939a97f4 10298 path->peer->hostname);
515c2602 10299
05864da7
DS
10300 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10301 json_object_string_add(json_nexthop_ll, "scope",
10302 "link-local");
d62a17ae 10303
05864da7
DS
10304 json_object_boolean_true_add(json_nexthop_ll,
10305 "accessible");
d62a17ae 10306
05864da7 10307 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10308 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10309 "used");
10310 else
10311 json_object_boolean_true_add(
10312 json_nexthop_global, "used");
10313 } else {
10314 vty_out(vty, " (%s) %s\n",
10315 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10316 buf, INET6_ADDRSTRLEN),
10317 attr->mp_nexthop_prefer_global
10318 ? "(prefer-global)"
10319 : "(used)");
d62a17ae 10320 }
05864da7
DS
10321 }
10322 /* If we do not have a link-local nexthop then we must flag the
10323 global as "used" */
10324 else {
10325 if (json_paths)
10326 json_object_boolean_true_add(json_nexthop_global,
10327 "used");
10328 }
d62a17ae 10329
b5e140c8 10330 if (safi == SAFI_EVPN &&
5e4d4c8a 10331 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10332 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10333 }
10334
05864da7
DS
10335 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10336 * Int/Ext/Local, Atomic, best */
10337 if (json_paths)
10338 json_object_string_add(json_path, "origin",
10339 bgp_origin_long_str[attr->origin]);
10340 else
10341 vty_out(vty, " Origin %s",
10342 bgp_origin_long_str[attr->origin]);
9df8b37c 10343
05864da7 10344 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10345 if (json_paths)
05864da7 10346 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10347 else
05864da7
DS
10348 vty_out(vty, ", metric %u", attr->med);
10349 }
9df8b37c 10350
05864da7
DS
10351 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10352 if (json_paths)
0fbac0b4 10353 json_object_int_add(json_path, "locPrf",
05864da7
DS
10354 attr->local_pref);
10355 else
10356 vty_out(vty, ", localpref %u", attr->local_pref);
10357 }
9df8b37c 10358
05864da7
DS
10359 if (attr->weight != 0) {
10360 if (json_paths)
10361 json_object_int_add(json_path, "weight", attr->weight);
10362 else
10363 vty_out(vty, ", weight %u", attr->weight);
10364 }
9df8b37c 10365
05864da7
DS
10366 if (attr->tag != 0) {
10367 if (json_paths)
10368 json_object_int_add(json_path, "tag", attr->tag);
10369 else
10370 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10371 }
9df8b37c 10372
05864da7
DS
10373 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10374 if (json_paths)
10375 json_object_boolean_false_add(json_path, "valid");
10376 else
10377 vty_out(vty, ", invalid");
10378 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10379 if (json_paths)
10380 json_object_boolean_true_add(json_path, "valid");
10381 else
10382 vty_out(vty, ", valid");
10383 }
9df8b37c 10384
7d3cae70
DA
10385 if (json_paths)
10386 json_object_int_add(json_path, "version", bn->version);
10387
05864da7
DS
10388 if (path->peer != bgp->peer_self) {
10389 if (path->peer->as == path->peer->local_as) {
10390 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10391 if (json_paths)
10392 json_object_string_add(
10393 json_peer, "type",
10394 "confed-internal");
d62a17ae 10395 else
05864da7 10396 vty_out(vty, ", confed-internal");
d62a17ae 10397 } else {
05864da7
DS
10398 if (json_paths)
10399 json_object_string_add(
10400 json_peer, "type", "internal");
10401 else
10402 vty_out(vty, ", internal");
9df8b37c 10403 }
05864da7
DS
10404 } else {
10405 if (bgp_confederation_peers_check(bgp,
10406 path->peer->as)) {
10407 if (json_paths)
10408 json_object_string_add(
10409 json_peer, "type",
10410 "confed-external");
d62a17ae 10411 else
05864da7 10412 vty_out(vty, ", confed-external");
d62a17ae 10413 } else {
05864da7
DS
10414 if (json_paths)
10415 json_object_string_add(
10416 json_peer, "type", "external");
10417 else
10418 vty_out(vty, ", external");
d62a17ae 10419 }
10420 }
05864da7
DS
10421 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10422 if (json_paths) {
10423 json_object_boolean_true_add(json_path, "aggregated");
10424 json_object_boolean_true_add(json_path, "local");
10425 } else {
10426 vty_out(vty, ", aggregated, local");
10427 }
10428 } else if (path->type != ZEBRA_ROUTE_BGP) {
10429 if (json_paths)
10430 json_object_boolean_true_add(json_path, "sourced");
10431 else
10432 vty_out(vty, ", sourced");
10433 } else {
10434 if (json_paths) {
10435 json_object_boolean_true_add(json_path, "sourced");
10436 json_object_boolean_true_add(json_path, "local");
10437 } else {
10438 vty_out(vty, ", sourced, local");
d62a17ae 10439 }
05864da7 10440 }
718e3744 10441
05864da7 10442 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10443 if (json_paths)
05864da7
DS
10444 json_object_boolean_true_add(json_path,
10445 "atomicAggregate");
d62a17ae 10446 else
05864da7
DS
10447 vty_out(vty, ", atomic-aggregate");
10448 }
d62a17ae 10449
05864da7
DS
10450 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10451 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10452 && bgp_path_info_mpath_count(path))) {
10453 if (json_paths)
10454 json_object_boolean_true_add(json_path, "multipath");
10455 else
10456 vty_out(vty, ", multipath");
10457 }
50e05855 10458
05864da7
DS
10459 // Mark the bestpath(s)
10460 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10461 first_as = aspath_get_first_as(attr->aspath);
718e3744 10462
05864da7
DS
10463 if (json_paths) {
10464 if (!json_bestpath)
10465 json_bestpath = json_object_new_object();
10466 json_object_int_add(json_bestpath, "bestpathFromAs",
10467 first_as);
10468 } else {
10469 if (first_as)
10470 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10471 else
05864da7 10472 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10473 }
05864da7 10474 }
718e3744 10475
05864da7
DS
10476 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10477 if (json_paths) {
10478 if (!json_bestpath)
10479 json_bestpath = json_object_new_object();
10480 json_object_boolean_true_add(json_bestpath, "overall");
10481 json_object_string_add(
10482 json_bestpath, "selectionReason",
10483 bgp_path_selection_reason2str(bn->reason));
10484 } else {
10485 vty_out(vty, ", best");
10486 vty_out(vty, " (%s)",
10487 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10488 }
05864da7 10489 }
718e3744 10490
4027d19b 10491 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10492 if (json_paths)
10493 json_object_string_add(
10494 json_path, "rpkiValidationState",
4027d19b 10495 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10496 else
1d327209 10497 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10498 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10499 }
10500
05864da7
DS
10501 if (json_bestpath)
10502 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10503
05864da7
DS
10504 if (!json_paths)
10505 vty_out(vty, "\n");
10506
10507 /* Line 4 display Community */
29e72930 10508 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10509 if (json_paths) {
9a706b42
DA
10510 if (!bgp_attr_get_community(attr)->json)
10511 community_str(bgp_attr_get_community(attr),
c0945b78 10512 true, true);
9a706b42
DA
10513 json_object_lock(bgp_attr_get_community(attr)->json);
10514 json_object_object_add(
10515 json_path, "community",
10516 bgp_attr_get_community(attr)->json);
05864da7
DS
10517 } else {
10518 vty_out(vty, " Community: %s\n",
9a706b42 10519 bgp_attr_get_community(attr)->str);
d62a17ae 10520 }
05864da7 10521 }
718e3744 10522
05864da7
DS
10523 /* Line 5 display Extended-community */
10524 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10525 if (json_paths) {
10526 json_ext_community = json_object_new_object();
b53e67a3
DA
10527 json_object_string_add(
10528 json_ext_community, "string",
10529 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10530 json_object_object_add(json_path, "extendedCommunity",
10531 json_ext_community);
d62a17ae 10532 } else {
05864da7 10533 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10534 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10535 }
05864da7 10536 }
718e3744 10537
05864da7
DS
10538 /* Line 6 display Large community */
10539 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10540 if (json_paths) {
1bcf3a96
DA
10541 if (!bgp_attr_get_lcommunity(attr)->json)
10542 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10543 true, true);
1bcf3a96
DA
10544 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10545 json_object_object_add(
10546 json_path, "largeCommunity",
10547 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10548 } else {
10549 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10550 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10551 }
05864da7 10552 }
718e3744 10553
05864da7
DS
10554 /* Line 7 display Originator, Cluster-id */
10555 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10556 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10557 char buf[BUFSIZ] = {0};
10558
05864da7 10559 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10560 if (json_paths)
c949c771
DA
10561 json_object_string_addf(json_path,
10562 "originatorId", "%pI4",
10563 &attr->originator_id);
d62a17ae 10564 else
23d0a753
DA
10565 vty_out(vty, " Originator: %pI4",
10566 &attr->originator_id);
d62a17ae 10567 }
856ca177 10568
05864da7 10569 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10570 struct cluster_list *cluster =
10571 bgp_attr_get_cluster(attr);
05864da7 10572 int i;
d62a17ae 10573
10574 if (json_paths) {
05864da7
DS
10575 json_cluster_list = json_object_new_object();
10576 json_cluster_list_list =
10577 json_object_new_array();
10578
779fee93 10579 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10580 json_string = json_object_new_string(
779fee93
DS
10581 inet_ntop(AF_INET,
10582 &cluster->list[i],
10583 buf, sizeof(buf)));
05864da7
DS
10584 json_object_array_add(
10585 json_cluster_list_list,
10586 json_string);
10587 }
718e3744 10588
05864da7
DS
10589 /*
10590 * struct cluster_list does not have
10591 * "str" variable like aspath and community
10592 * do. Add this someday if someone asks
10593 * for it.
10594 * json_object_string_add(json_cluster_list,
779fee93 10595 * "string", cluster->str);
05864da7
DS
10596 */
10597 json_object_object_add(json_cluster_list,
10598 "list",
10599 json_cluster_list_list);
10600 json_object_object_add(json_path, "clusterList",
10601 json_cluster_list);
0dc8ee70 10602 } else {
05864da7
DS
10603 vty_out(vty, ", Cluster list: ");
10604
779fee93 10605 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10606 vty_out(vty, "%pI4 ",
779fee93 10607 &cluster->list[i]);
05864da7 10608 }
0dc8ee70 10609 }
d62a17ae 10610 }
718e3744 10611
d62a17ae 10612 if (!json_paths)
10613 vty_out(vty, "\n");
05864da7 10614 }
d62a17ae 10615
05864da7 10616 if (path->extra && path->extra->damp_info)
b4f7f45b 10617 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10618
05864da7
DS
10619 /* Remote Label */
10620 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10621 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10622 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10623 &bos);
d62a17ae 10624
05864da7
DS
10625 if (json_paths)
10626 json_object_int_add(json_path, "remoteLabel", label);
10627 else
10628 vty_out(vty, " Remote label: %d\n", label);
10629 }
d62a17ae 10630
e496b420
HS
10631 /* Remote SID */
10632 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10633 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10634 if (json_paths)
10635 json_object_string_add(json_path, "remoteSid", buf);
10636 else
10637 vty_out(vty, " Remote SID: %s\n", buf);
10638 }
10639
05864da7
DS
10640 /* Label Index */
10641 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10642 if (json_paths)
10643 json_object_int_add(json_path, "labelIndex",
10644 attr->label_index);
10645 else
10646 vty_out(vty, " Label Index: %d\n",
10647 attr->label_index);
10648 }
d62a17ae 10649
05864da7
DS
10650 /* Line 8 display Addpath IDs */
10651 if (path->addpath_rx_id
10652 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10653 if (json_paths) {
10654 json_object_int_add(json_path, "addpathRxId",
10655 path->addpath_rx_id);
d62a17ae 10656
05864da7
DS
10657 /* Keep backwards compatibility with the old API
10658 * by putting TX All's ID in the old field
10659 */
10660 json_object_int_add(
10661 json_path, "addpathTxId",
10662 path->tx_addpath
10663 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10664
05864da7
DS
10665 /* ... but create a specific field for each
10666 * strategy
10667 */
10668 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10669 json_object_int_add(
10670 json_path,
10671 bgp_addpath_names(i)->id_json_name,
10672 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10673 }
05864da7
DS
10674 } else {
10675 vty_out(vty, " AddPath ID: RX %u, ",
10676 path->addpath_rx_id);
d62a17ae 10677
05864da7 10678 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10679 }
05864da7 10680 }
520d5d76 10681
05864da7
DS
10682 /* If we used addpath to TX a non-bestpath we need to display
10683 * "Advertised to" on a path-by-path basis
10684 */
10685 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10686 first = 1;
dcc68b5e 10687
05864da7
DS
10688 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10689 addpath_capable =
10690 bgp_addpath_encode_tx(peer, afi, safi);
10691 has_adj = bgp_adj_out_lookup(
10692 peer, path->net,
10693 bgp_addpath_id_for_peer(peer, afi, safi,
10694 &path->tx_addpath));
10695
10696 if ((addpath_capable && has_adj)
10697 || (!addpath_capable && has_adj
10698 && CHECK_FLAG(path->flags,
10699 BGP_PATH_SELECTED))) {
10700 if (json_path && !json_adv_to)
10701 json_adv_to = json_object_new_object();
dcc68b5e 10702
05864da7
DS
10703 route_vty_out_advertised_to(
10704 vty, peer, &first,
10705 " Advertised to:", json_adv_to);
d62a17ae 10706 }
10707 }
718e3744 10708
05864da7
DS
10709 if (json_path) {
10710 if (json_adv_to) {
10711 json_object_object_add(
10712 json_path, "advertisedTo", json_adv_to);
d62a17ae 10713 }
05864da7
DS
10714 } else {
10715 if (!first) {
10716 vty_out(vty, "\n");
d62a17ae 10717 }
10718 }
05864da7 10719 }
b05a1c8b 10720
05864da7
DS
10721 /* Line 9 display Uptime */
10722 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10723 if (json_paths) {
10724 json_last_update = json_object_new_object();
10725 json_object_int_add(json_last_update, "epoch", tbuf);
10726 json_object_string_add(json_last_update, "string",
10727 ctime(&tbuf));
10728 json_object_object_add(json_path, "lastUpdate",
10729 json_last_update);
10730 } else
10731 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10732
05864da7
DS
10733 /* Line 10 display PMSI tunnel attribute, if present */
10734 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10735 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10736 bgp_attr_get_pmsi_tnl_type(attr),
10737 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10738
05864da7
DS
10739 if (json_paths) {
10740 json_pmsi = json_object_new_object();
10741 json_object_string_add(json_pmsi, "tunnelType", str);
10742 json_object_int_add(json_pmsi, "label",
10743 label2vni(&attr->label));
10744 json_object_object_add(json_path, "pmsi", json_pmsi);
10745 } else
10746 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10747 str, label2vni(&attr->label));
d62a17ae 10748 }
f1aa5d8a 10749
848e8cf6
DA
10750 if (path->peer->t_gr_restart &&
10751 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10752 unsigned long gr_remaining =
10753 thread_timer_remain_second(path->peer->t_gr_restart);
10754
10755 if (json_paths) {
10756 json_object_int_add(json_path,
10757 "gracefulRestartSecondsRemaining",
10758 gr_remaining);
10759 } else
10760 vty_out(vty,
10761 " Time until Graceful Restart stale route deleted: %lu\n",
10762 gr_remaining);
10763 }
10764
9a706b42
DA
10765 if (path->peer->t_llgr_stale[afi][safi] &&
10766 bgp_attr_get_community(attr) &&
10767 community_include(bgp_attr_get_community(attr),
10768 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10769 unsigned long llgr_remaining = thread_timer_remain_second(
10770 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10771
48ebba04
DA
10772 if (json_paths) {
10773 json_object_int_add(json_path, "llgrSecondsRemaining",
10774 llgr_remaining);
10775 } else
10776 vty_out(vty,
10777 " Time until Long-lived stale route deleted: %lu\n",
10778 llgr_remaining);
10779 }
10780
92269aa2
DS
10781 /* Output some debug about internal state of the dest flags */
10782 if (json_paths) {
10783 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10784 json_object_boolean_true_add(json_path, "processScheduled");
10785 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10786 json_object_boolean_true_add(json_path, "userCleared");
10787 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10788 json_object_boolean_true_add(json_path, "labelChanged");
10789 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10790 json_object_boolean_true_add(json_path, "registeredForLabel");
10791 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10792 json_object_boolean_true_add(json_path, "selectDefered");
10793 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10794 json_object_boolean_true_add(json_path, "fibInstalled");
10795 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10796 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10797
d62a17ae 10798 if (json_nexthop_global || json_nexthop_ll) {
10799 json_nexthops = json_object_new_array();
f1aa5d8a 10800
d62a17ae 10801 if (json_nexthop_global)
10802 json_object_array_add(json_nexthops,
10803 json_nexthop_global);
f1aa5d8a 10804
d62a17ae 10805 if (json_nexthop_ll)
10806 json_object_array_add(json_nexthops,
10807 json_nexthop_ll);
f1aa5d8a 10808
d62a17ae 10809 json_object_object_add(json_path, "nexthops",
10810 json_nexthops);
10811 }
10812
10813 json_object_object_add(json_path, "peer", json_peer);
10814 json_object_array_add(json_paths, json_path);
05864da7 10815 }
b366b518
BB
10816}
10817
96ade3ed 10818#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10819#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10820#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10821
a4d82a8a 10822static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10823 afi_t afi, safi_t safi, enum bgp_show_type type,
10824 bool use_json);
7f323236
DW
10825static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10826 const char *comstr, int exact, afi_t afi,
96c81f66 10827 safi_t safi, uint16_t show_flags);
d62a17ae 10828
1ae44dfc 10829static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10830 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10831 void *output_arg, const char *rd, int is_last,
96f3485c 10832 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10833 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10834 enum rpki_states rpki_target_state)
d62a17ae 10835{
40381db7 10836 struct bgp_path_info *pi;
9bcb3eef 10837 struct bgp_dest *dest;
2aad8c42
MS
10838 bool header = true;
10839 bool json_detail_header = false;
d62a17ae 10840 int display;
1ae44dfc
LB
10841 unsigned long output_count = 0;
10842 unsigned long total_count = 0;
d62a17ae 10843 struct prefix *p;
d62a17ae 10844 json_object *json_paths = NULL;
10845 int first = 1;
96f3485c
MK
10846 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10847 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10848 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10849
1ae44dfc 10850 if (output_cum && *output_cum != 0)
2aad8c42 10851 header = false;
1ae44dfc 10852
9386b588 10853 if (use_json && !*json_header_depth) {
96f3485c
MK
10854 if (all)
10855 *json_header_depth = 1;
10856 else {
10857 vty_out(vty, "{\n");
10858 *json_header_depth = 2;
10859 }
10860
d62a17ae 10861 vty_out(vty,
23d0a753
DA
10862 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10863 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10864 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10865 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10866 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10867 ? VRF_DEFAULT_NAME
10868 : bgp->name,
10869 table->version, &bgp->router_id,
01eced22 10870 bgp->default_local_pref, bgp->as);
9386b588 10871 if (rd) {
445c2480 10872 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10873 ++*json_header_depth;
10874 }
d62a17ae 10875 }
718e3744 10876
445c2480
DS
10877 if (use_json && rd) {
10878 vty_out(vty, " \"%s\" : { ", rd);
10879 }
10880
2aad8c42
MS
10881 /* Check for 'json detail', where we need header output once per dest */
10882 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10883 type != bgp_show_type_dampend_paths &&
10884 type != bgp_show_type_damp_neighbor &&
10885 type != bgp_show_type_flap_statistics &&
10886 type != bgp_show_type_flap_neighbor)
10887 json_detail_header = true;
10888
d62a17ae 10889 /* Start processing of routes. */
9bcb3eef
DS
10890 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10891 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10892 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10893 bool json_detail = json_detail_header;
b54892e0 10894
9bcb3eef 10895 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10896 if (pi == NULL)
98ce9a06 10897 continue;
d62a17ae 10898
98ce9a06 10899 display = 0;
98ce9a06
DS
10900 if (use_json)
10901 json_paths = json_object_new_array();
10902 else
10903 json_paths = NULL;
d62a17ae 10904
6f94b685 10905 for (; pi; pi = pi->next) {
9a706b42
DA
10906 struct community *picomm = NULL;
10907
10908 picomm = bgp_attr_get_community(pi->attr);
10909
98ce9a06 10910 total_count++;
1e2ce4f1 10911
7d3cae70
DA
10912 if (type == bgp_show_type_prefix_version) {
10913 uint32_t version =
10914 strtoul(output_arg, NULL, 10);
10915 if (dest->version < version)
10916 continue;
10917 }
10918
a70a28a5
DA
10919 if (type == bgp_show_type_community_alias) {
10920 char *alias = output_arg;
10921 char **communities;
10922 int num;
10923 bool found = false;
10924
9a706b42
DA
10925 if (picomm) {
10926 frrstr_split(picomm->str, " ",
10927 &communities, &num);
a70a28a5
DA
10928 for (int i = 0; i < num; i++) {
10929 const char *com2alias =
10930 bgp_community2alias(
10931 communities[i]);
cd9cc0e6
IR
10932 if (!found
10933 && strcmp(alias, com2alias)
10934 == 0)
a70a28a5 10935 found = true;
cd9cc0e6
IR
10936 XFREE(MTYPE_TMP,
10937 communities[i]);
a70a28a5 10938 }
cd9cc0e6 10939 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10940 }
10941
1bcf3a96
DA
10942 if (!found &&
10943 bgp_attr_get_lcommunity(pi->attr)) {
10944 frrstr_split(bgp_attr_get_lcommunity(
10945 pi->attr)
10946 ->str,
a70a28a5
DA
10947 " ", &communities, &num);
10948 for (int i = 0; i < num; i++) {
10949 const char *com2alias =
10950 bgp_community2alias(
10951 communities[i]);
cd9cc0e6
IR
10952 if (!found
10953 && strcmp(alias, com2alias)
10954 == 0)
a70a28a5 10955 found = true;
cd9cc0e6
IR
10956 XFREE(MTYPE_TMP,
10957 communities[i]);
a70a28a5 10958 }
cd9cc0e6 10959 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10960 }
10961
10962 if (!found)
10963 continue;
10964 }
10965
1e2ce4f1
DS
10966 if (type == bgp_show_type_rpki) {
10967 if (dest_p->family == AF_INET
10968 || dest_p->family == AF_INET6)
4027d19b 10969 rpki_curr_state = hook_call(
1e2ce4f1
DS
10970 bgp_rpki_prefix_status,
10971 pi->peer, pi->attr, dest_p);
4027d19b
DS
10972 if (rpki_target_state != RPKI_NOT_BEING_USED
10973 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10974 continue;
10975 }
10976
98ce9a06
DS
10977 if (type == bgp_show_type_flap_statistics
10978 || type == bgp_show_type_flap_neighbor
10979 || type == bgp_show_type_dampend_paths
10980 || type == bgp_show_type_damp_neighbor) {
40381db7 10981 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10982 continue;
10983 }
10984 if (type == bgp_show_type_regexp) {
10985 regex_t *regex = output_arg;
d62a17ae 10986
40381db7 10987 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10988 == REG_NOMATCH)
10989 continue;
10990 }
10991 if (type == bgp_show_type_prefix_list) {
10992 struct prefix_list *plist = output_arg;
d62a17ae 10993
9bcb3eef 10994 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10995 != PREFIX_PERMIT)
10996 continue;
10997 }
10998 if (type == bgp_show_type_filter_list) {
10999 struct as_list *as_list = output_arg;
d62a17ae 11000
40381db7 11001 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11002 != AS_FILTER_PERMIT)
11003 continue;
11004 }
11005 if (type == bgp_show_type_route_map) {
11006 struct route_map *rmap = output_arg;
9b6d8fcf 11007 struct bgp_path_info path;
98ce9a06 11008 struct attr dummy_attr;
b68885f9 11009 route_map_result_t ret;
d62a17ae 11010
6f4f49b2 11011 dummy_attr = *pi->attr;
d62a17ae 11012
40381db7 11013 path.peer = pi->peer;
9b6d8fcf 11014 path.attr = &dummy_attr;
d62a17ae 11015
1782514f 11016 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11017 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11018 if (ret == RMAP_DENYMATCH)
11019 continue;
11020 }
11021 if (type == bgp_show_type_neighbor
11022 || type == bgp_show_type_flap_neighbor
11023 || type == bgp_show_type_damp_neighbor) {
11024 union sockunion *su = output_arg;
11025
40381db7
DS
11026 if (pi->peer == NULL
11027 || pi->peer->su_remote == NULL
11028 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11029 continue;
11030 }
11031 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11032 uint32_t destination;
d62a17ae 11033
9bcb3eef 11034 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11035 if (IN_CLASSC(destination)
9bcb3eef 11036 && dest_p->prefixlen == 24)
98ce9a06
DS
11037 continue;
11038 if (IN_CLASSB(destination)
9bcb3eef 11039 && dest_p->prefixlen == 16)
98ce9a06
DS
11040 continue;
11041 if (IN_CLASSA(destination)
9bcb3eef 11042 && dest_p->prefixlen == 8)
98ce9a06
DS
11043 continue;
11044 }
11045 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11046 p = output_arg;
9bcb3eef 11047 if (!prefix_match(p, dest_p))
98ce9a06
DS
11048 continue;
11049 }
11050 if (type == bgp_show_type_community_all) {
9a706b42 11051 if (!picomm)
98ce9a06
DS
11052 continue;
11053 }
11054 if (type == bgp_show_type_community) {
11055 struct community *com = output_arg;
d62a17ae 11056
9a706b42 11057 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11058 continue;
11059 }
11060 if (type == bgp_show_type_community_exact) {
11061 struct community *com = output_arg;
d62a17ae 11062
9a706b42 11063 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11064 continue;
11065 }
11066 if (type == bgp_show_type_community_list) {
11067 struct community_list *list = output_arg;
d62a17ae 11068
9a706b42 11069 if (!community_list_match(picomm, list))
98ce9a06
DS
11070 continue;
11071 }
a4d82a8a 11072 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11073 struct community_list *list = output_arg;
d62a17ae 11074
9a706b42 11075 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11076 continue;
11077 }
11078 if (type == bgp_show_type_lcommunity) {
11079 struct lcommunity *lcom = output_arg;
d62a17ae 11080
1bcf3a96
DA
11081 if (!bgp_attr_get_lcommunity(pi->attr) ||
11082 !lcommunity_match(
11083 bgp_attr_get_lcommunity(pi->attr),
11084 lcom))
98ce9a06
DS
11085 continue;
11086 }
36a206db 11087
11088 if (type == bgp_show_type_lcommunity_exact) {
11089 struct lcommunity *lcom = output_arg;
11090
1bcf3a96
DA
11091 if (!bgp_attr_get_lcommunity(pi->attr) ||
11092 !lcommunity_cmp(
11093 bgp_attr_get_lcommunity(pi->attr),
11094 lcom))
36a206db 11095 continue;
11096 }
98ce9a06
DS
11097 if (type == bgp_show_type_lcommunity_list) {
11098 struct community_list *list = output_arg;
d62a17ae 11099
1bcf3a96
DA
11100 if (!lcommunity_list_match(
11101 bgp_attr_get_lcommunity(pi->attr),
11102 list))
98ce9a06
DS
11103 continue;
11104 }
36a206db 11105 if (type
11106 == bgp_show_type_lcommunity_list_exact) {
11107 struct community_list *list = output_arg;
11108
11109 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11110 bgp_attr_get_lcommunity(pi->attr),
11111 list))
36a206db 11112 continue;
11113 }
98ce9a06 11114 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11115 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11116 continue;
11117 }
11118 if (type == bgp_show_type_dampend_paths
11119 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11120 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11121 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11122 continue;
11123 }
11124
11125 if (!use_json && header) {
23d0a753
DA
11126 vty_out(vty,
11127 "BGP table version is %" PRIu64
11128 ", local router ID is %pI4, vrf id ",
11129 table->version, &bgp->router_id);
9df8b37c
PZ
11130 if (bgp->vrf_id == VRF_UNKNOWN)
11131 vty_out(vty, "%s", VRFID_NONE_STR);
11132 else
11133 vty_out(vty, "%u", bgp->vrf_id);
11134 vty_out(vty, "\n");
01eced22
AD
11135 vty_out(vty, "Default local pref %u, ",
11136 bgp->default_local_pref);
11137 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11138 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11139 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11140 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11141 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11142 if (type == bgp_show_type_dampend_paths
11143 || type == bgp_show_type_damp_neighbor)
98ce9a06 11144 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11145 else if (type == bgp_show_type_flap_statistics
11146 || type == bgp_show_type_flap_neighbor)
98ce9a06 11147 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11148 else
ae248832
MK
11149 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11150 : BGP_SHOW_HEADER));
2aad8c42
MS
11151 header = false;
11152
11153 } else if (json_detail && json_paths != NULL) {
11154 const struct prefix_rd *prd;
11155 json_object *jtemp;
11156
11157 /* Use common detail header, for most types;
11158 * need a json 'object'.
11159 */
11160
11161 jtemp = json_object_new_object();
11162 prd = bgp_rd_from_dest(dest, safi);
11163
11164 route_vty_out_detail_header(
11165 vty, bgp, dest, prd, table->afi,
11166 safi, jtemp);
11167
11168 json_object_array_add(json_paths, jtemp);
11169
11170 json_detail = false;
d62a17ae 11171 }
2aad8c42 11172
98ce9a06
DS
11173 if (rd != NULL && !display && !output_count) {
11174 if (!use_json)
11175 vty_out(vty,
11176 "Route Distinguisher: %s\n",
11177 rd);
d62a17ae 11178 }
98ce9a06
DS
11179 if (type == bgp_show_type_dampend_paths
11180 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11181 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11182 AFI_IP, safi, use_json,
11183 json_paths);
98ce9a06
DS
11184 else if (type == bgp_show_type_flap_statistics
11185 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11186 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11187 AFI_IP, safi, use_json,
11188 json_paths);
f280c93b
DA
11189 else {
11190 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11191 route_vty_out_detail(
11192 vty, bgp, dest, pi,
11193 family2afi(dest_p->family),
11194 safi, RPKI_NOT_BEING_USED,
11195 json_paths);
11196 else
11197 route_vty_out(vty, dest_p, pi, display,
11198 safi, json_paths, wide);
11199 }
98ce9a06 11200 display++;
d62a17ae 11201 }
11202
98ce9a06
DS
11203 if (display) {
11204 output_count++;
11205 if (!use_json)
11206 continue;
11207
625d2931 11208 /* encode prefix */
9bcb3eef 11209 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11210 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11211
1840384b 11212
b54892e0
DS
11213 bgp_fs_nlri_get_string(
11214 (unsigned char *)
9bcb3eef
DS
11215 dest_p->u.prefix_flowspec.ptr,
11216 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11217 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11218 family2afi(dest_p->u
11219 .prefix_flowspec.family));
625d2931 11220 if (first)
b54892e0 11221 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11222 dest_p->u.prefix_flowspec
b54892e0 11223 .prefixlen);
625d2931 11224 else
b54892e0 11225 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11226 dest_p->u.prefix_flowspec
b54892e0 11227 .prefixlen);
625d2931 11228 } else {
625d2931 11229 if (first)
1b78780b 11230 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11231 else
1b78780b 11232 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11233 }
3757f964 11234 vty_json(vty, json_paths);
449feb8e 11235 json_paths = NULL;
98ce9a06 11236 first = 0;
1f83ed02
DS
11237 } else
11238 json_object_free(json_paths);
98ce9a06
DS
11239 }
11240
1ae44dfc
LB
11241 if (output_cum) {
11242 output_count += *output_cum;
11243 *output_cum = output_count;
11244 }
11245 if (total_cum) {
11246 total_count += *total_cum;
11247 *total_cum = total_count;
11248 }
d62a17ae 11249 if (use_json) {
9386b588 11250 if (rd) {
a4d82a8a 11251 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11252 }
11253 if (is_last) {
a4d82a8a
PZ
11254 unsigned long i;
11255 for (i = 0; i < *json_header_depth; ++i)
11256 vty_out(vty, " } ");
96f3485c
MK
11257 if (!all)
11258 vty_out(vty, "\n");
9386b588 11259 }
d62a17ae 11260 } else {
1ae44dfc
LB
11261 if (is_last) {
11262 /* No route is displayed */
11263 if (output_count == 0) {
11264 if (type == bgp_show_type_normal)
11265 vty_out(vty,
11266 "No BGP prefixes displayed, %ld exist\n",
11267 total_count);
11268 } else
d62a17ae 11269 vty_out(vty,
1ae44dfc
LB
11270 "\nDisplayed %ld routes and %ld total paths\n",
11271 output_count, total_count);
11272 }
d62a17ae 11273 }
718e3744 11274
d62a17ae 11275 return CMD_SUCCESS;
718e3744 11276}
11277
1ae44dfc
LB
11278int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11279 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11280 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11281{
9bcb3eef 11282 struct bgp_dest *dest, *next;
1ae44dfc
LB
11283 unsigned long output_cum = 0;
11284 unsigned long total_cum = 0;
9386b588 11285 unsigned long json_header_depth = 0;
67009e22 11286 struct bgp_table *itable;
0136788c 11287 bool show_msg;
96c81f66 11288 uint16_t show_flags = 0;
0136788c
LB
11289
11290 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11291
96f3485c
MK
11292 if (use_json)
11293 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11294
9bcb3eef
DS
11295 for (dest = bgp_table_top(table); dest; dest = next) {
11296 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11297
9bcb3eef
DS
11298 next = bgp_route_next(dest);
11299 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11300 continue;
67009e22 11301
9bcb3eef 11302 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11303 if (itable != NULL) {
1ae44dfc 11304 struct prefix_rd prd;
06b9f471 11305 char rd[RD_ADDRSTRLEN];
1ae44dfc 11306
9bcb3eef 11307 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11308 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11309 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11310 rd, next == NULL, &output_cum,
11311 &total_cum, &json_header_depth,
1e2ce4f1 11312 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11313 if (next == NULL)
11314 show_msg = false;
1ae44dfc
LB
11315 }
11316 }
0136788c
LB
11317 if (show_msg) {
11318 if (output_cum == 0)
11319 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11320 total_cum);
11321 else
11322 vty_out(vty,
11323 "\nDisplayed %ld routes and %ld total paths\n",
11324 output_cum, total_cum);
11325 }
1ae44dfc
LB
11326 return CMD_SUCCESS;
11327}
2aad8c42 11328
d62a17ae 11329static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11330 enum bgp_show_type type, void *output_arg,
96c81f66 11331 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11332{
d62a17ae 11333 struct bgp_table *table;
9386b588 11334 unsigned long json_header_depth = 0;
96f3485c 11335 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11336
d62a17ae 11337 if (bgp == NULL) {
11338 bgp = bgp_get_default();
11339 }
fee0f4c6 11340
d62a17ae 11341 if (bgp == NULL) {
11342 if (!use_json)
11343 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11344 else
11345 vty_out(vty, "{}\n");
d62a17ae 11346 return CMD_WARNING;
11347 }
4dd6177e 11348
cd8c2a27
MS
11349 /* Labeled-unicast routes live in the unicast table. */
11350 if (safi == SAFI_LABELED_UNICAST)
11351 safi = SAFI_UNICAST;
11352
1ae44dfc 11353 table = bgp->rib[afi][safi];
d62a17ae 11354 /* use MPLS and ENCAP specific shows until they are merged */
11355 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11356 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11357 output_arg, use_json);
d62a17ae 11358 }
dba3c1d3
PG
11359
11360 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11361 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11362 output_arg, use_json,
11363 1, NULL, NULL);
11364 }
fee0f4c6 11365
96f3485c 11366 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11367 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11368 rpki_target_state);
fee0f4c6 11369}
11370
d62a17ae 11371static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11372 safi_t safi, uint16_t show_flags)
f186de26 11373{
d62a17ae 11374 struct listnode *node, *nnode;
11375 struct bgp *bgp;
11376 int is_first = 1;
9f049418 11377 bool route_output = false;
96f3485c 11378 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11379
d62a17ae 11380 if (use_json)
11381 vty_out(vty, "{\n");
9f689658 11382
d62a17ae 11383 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11384 route_output = true;
d62a17ae 11385 if (use_json) {
11386 if (!is_first)
11387 vty_out(vty, ",\n");
11388 else
11389 is_first = 0;
11390
11391 vty_out(vty, "\"%s\":",
11392 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11393 ? VRF_DEFAULT_NAME
d62a17ae 11394 : bgp->name);
11395 } else {
11396 vty_out(vty, "\nInstance %s:\n",
11397 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11398 ? VRF_DEFAULT_NAME
d62a17ae 11399 : bgp->name);
11400 }
11401 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11402 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11403 }
9f689658 11404
d62a17ae 11405 if (use_json)
11406 vty_out(vty, "}\n");
9f049418
DS
11407 else if (!route_output)
11408 vty_out(vty, "%% BGP instance not found\n");
f186de26 11409}
11410
718e3744 11411/* Header of detailed BGP route information */
d62a17ae 11412void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11413 struct bgp_dest *dest,
11414 const struct prefix_rd *prd,
d62a17ae 11415 afi_t afi, safi_t safi, json_object *json)
11416{
40381db7 11417 struct bgp_path_info *pi;
b54892e0 11418 const struct prefix *p;
d62a17ae 11419 struct peer *peer;
11420 struct listnode *node, *nnode;
06b9f471 11421 char buf1[RD_ADDRSTRLEN];
d62a17ae 11422 int count = 0;
11423 int best = 0;
11424 int suppress = 0;
c5f1e1b2
C
11425 int accept_own = 0;
11426 int route_filter_translated_v4 = 0;
11427 int route_filter_v4 = 0;
11428 int route_filter_translated_v6 = 0;
11429 int route_filter_v6 = 0;
11430 int llgr_stale = 0;
11431 int no_llgr = 0;
11432 int accept_own_nexthop = 0;
11433 int blackhole = 0;
d62a17ae 11434 int no_export = 0;
11435 int no_advertise = 0;
11436 int local_as = 0;
c5f1e1b2 11437 int no_peer = 0;
d62a17ae 11438 int first = 1;
11439 int has_valid_label = 0;
11440 mpls_label_t label = 0;
11441 json_object *json_adv_to = NULL;
67f67ba4
DA
11442 uint32_t ttl = 0;
11443 uint32_t bos = 0;
11444 uint32_t exp = 0;
9bedbb1e 11445
67f67ba4 11446 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11447
67f67ba4
DA
11448 p = bgp_dest_get_prefix(dest);
11449 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11450
44c69747 11451 if (safi == SAFI_EVPN) {
d62a17ae 11452
44c69747 11453 if (!json) {
2dbe669b 11454 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11455 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11456 : "",
2dbe669b 11457 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11458 } else {
11459 json_object_string_add(json, "rd",
11460 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11461 "");
11462 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11463 }
11464 } else {
11465 if (!json) {
9119ef3a
DA
11466 vty_out(vty,
11467 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11468 "\n",
d62a17ae 11469 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11470 ? prefix_rd2str(prd, buf1,
11471 sizeof(buf1))
11472 : ""),
9119ef3a
DA
11473 safi == SAFI_MPLS_VPN ? ":" : "", p,
11474 dest->version);
cd1964ff 11475
9119ef3a 11476 } else {
67d7e256 11477 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11478 json_object_int_add(json, "version", dest->version);
11479
11480 }
44c69747
LK
11481 }
11482
11483 if (has_valid_label) {
11484 if (json)
11485 json_object_int_add(json, "localLabel", label);
11486 else
d62a17ae 11487 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11488 }
11489
11490 if (!json)
d62a17ae 11491 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11492 vty_out(vty, "not allocated\n");
718e3744 11493
9bcb3eef 11494 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11495 struct community *picomm = NULL;
11496
11497 picomm = bgp_attr_get_community(pi->attr);
11498
d62a17ae 11499 count++;
40381db7 11500 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11501 best = count;
4056a5f6 11502 if (bgp_path_suppressed(pi))
d62a17ae 11503 suppress = 1;
cee9c031 11504
9a706b42 11505 if (!picomm)
cee9c031
QY
11506 continue;
11507
11508 no_advertise += community_include(
9a706b42
DA
11509 picomm, COMMUNITY_NO_ADVERTISE);
11510 no_export +=
11511 community_include(picomm, COMMUNITY_NO_EXPORT);
11512 local_as +=
11513 community_include(picomm, COMMUNITY_LOCAL_AS);
11514 accept_own +=
11515 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11516 route_filter_translated_v4 += community_include(
9a706b42 11517 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11518 route_filter_translated_v6 += community_include(
9a706b42 11519 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11520 route_filter_v4 += community_include(
9a706b42 11521 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11522 route_filter_v6 += community_include(
9a706b42
DA
11523 picomm, COMMUNITY_ROUTE_FILTER_v6);
11524 llgr_stale +=
11525 community_include(picomm, COMMUNITY_LLGR_STALE);
11526 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11527 accept_own_nexthop += community_include(
11528 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11529 blackhole +=
11530 community_include(picomm, COMMUNITY_BLACKHOLE);
11531 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11532 }
718e3744 11533 }
718e3744 11534
d62a17ae 11535 if (!json) {
11536 vty_out(vty, "Paths: (%d available", count);
11537 if (best) {
11538 vty_out(vty, ", best #%d", best);
b84060bb
PG
11539 if (safi == SAFI_UNICAST) {
11540 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11541 vty_out(vty, ", table %s",
11542 VRF_DEFAULT_NAME);
11543 else
11544 vty_out(vty, ", vrf %s",
11545 bgp->name);
11546 }
d62a17ae 11547 } else
11548 vty_out(vty, ", no best path");
11549
c5f1e1b2
C
11550 if (accept_own)
11551 vty_out(vty,
11552 ", accept own local route exported and imported in different VRF");
11553 else if (route_filter_translated_v4)
11554 vty_out(vty,
11555 ", mark translated RTs for VPNv4 route filtering");
11556 else if (route_filter_v4)
11557 vty_out(vty,
11558 ", attach RT as-is for VPNv4 route filtering");
11559 else if (route_filter_translated_v6)
11560 vty_out(vty,
11561 ", mark translated RTs for VPNv6 route filtering");
11562 else if (route_filter_v6)
11563 vty_out(vty,
11564 ", attach RT as-is for VPNv6 route filtering");
11565 else if (llgr_stale)
11566 vty_out(vty,
1479ed2f 11567 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11568 else if (no_llgr)
11569 vty_out(vty,
11570 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11571 else if (accept_own_nexthop)
11572 vty_out(vty,
11573 ", accept local nexthop");
11574 else if (blackhole)
11575 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11576 else if (no_export)
11577 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11578 else if (no_advertise)
11579 vty_out(vty, ", not advertised to any peer");
d62a17ae 11580 else if (local_as)
11581 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11582 else if (no_peer)
11583 vty_out(vty,
11584 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11585
11586 if (suppress)
11587 vty_out(vty,
11588 ", Advertisements suppressed by an aggregate.");
11589 vty_out(vty, ")\n");
11590 }
718e3744 11591
d62a17ae 11592 /* If we are not using addpath then we can display Advertised to and
11593 * that will
11594 * show what peers we advertised the bestpath to. If we are using
11595 * addpath
11596 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11597 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11598 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11599 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11600 if (json && !json_adv_to)
11601 json_adv_to = json_object_new_object();
11602
11603 route_vty_out_advertised_to(
11604 vty, peer, &first,
11605 " Advertised to non peer-group peers:\n ",
11606 json_adv_to);
11607 }
11608 }
11609
11610 if (json) {
11611 if (json_adv_to) {
11612 json_object_object_add(json, "advertisedTo",
11613 json_adv_to);
11614 }
11615 } else {
11616 if (first)
11617 vty_out(vty, " Not advertised to any peer");
11618 vty_out(vty, "\n");
11619 }
11620 }
718e3744 11621}
11622
edfee30d 11623static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11624 struct bgp_dest *bgp_node, struct vty *vty,
11625 struct bgp *bgp, afi_t afi, safi_t safi,
11626 json_object *json, enum bgp_path_type pathtype,
4027d19b 11627 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11628{
11629 struct bgp_path_info *pi;
11630 int header = 1;
11631 char rdbuf[RD_ADDRSTRLEN];
11632 json_object *json_header = NULL;
11633 json_object *json_paths = NULL;
4933eaaf 11634 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11635
9bcb3eef 11636 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11637 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11638
11639 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11640 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11641 pi->peer, pi->attr, p);
4933eaaf 11642
4027d19b
DS
11643 if (rpki_target_state != RPKI_NOT_BEING_USED
11644 && rpki_curr_state != rpki_target_state)
4933eaaf 11645 continue;
44c69747
LK
11646
11647 if (json && !json_paths) {
11648 /* Instantiate json_paths only if path is valid */
11649 json_paths = json_object_new_array();
11650 if (pfx_rd) {
11651 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11652 json_header = json_object_new_object();
11653 } else
11654 json_header = json;
11655 }
11656
11657 if (header) {
11658 route_vty_out_detail_header(
11659 vty, bgp, bgp_node, pfx_rd,
11660 AFI_IP, safi, json_header);
11661 header = 0;
11662 }
11663 (*display)++;
11664
11665 if (pathtype == BGP_PATH_SHOW_ALL
11666 || (pathtype == BGP_PATH_SHOW_BESTPATH
11667 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11668 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11669 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11670 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11671 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11672 safi, rpki_curr_state, json_paths);
44c69747
LK
11673 }
11674
11675 if (json && json_paths) {
11676 json_object_object_add(json_header, "paths", json_paths);
11677
11678 if (pfx_rd)
11679 json_object_object_add(json, rdbuf, json_header);
11680 }
11681}
11682
2aad8c42
MS
11683/*
11684 * Return rd based on safi
11685 */
11686static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11687 safi_t safi)
11688{
11689 switch (safi) {
11690 case SAFI_MPLS_VPN:
11691 case SAFI_ENCAP:
11692 case SAFI_EVPN:
11693 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11694 default:
11695 return NULL;
11696
11697 }
11698}
11699
718e3744 11700/* Display specified route of BGP table. */
d62a17ae 11701static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11702 struct bgp_table *rib, const char *ip_str,
11703 afi_t afi, safi_t safi,
4027d19b 11704 enum rpki_states rpki_target_state,
d62a17ae 11705 struct prefix_rd *prd, int prefix_check,
9f049418 11706 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11707{
11708 int ret;
d62a17ae 11709 int display = 0;
11710 struct prefix match;
9bcb3eef
DS
11711 struct bgp_dest *dest;
11712 struct bgp_dest *rm;
d62a17ae 11713 struct bgp_table *table;
11714 json_object *json = NULL;
11715 json_object *json_paths = NULL;
11716
11717 /* Check IP address argument. */
11718 ret = str2prefix(ip_str, &match);
11719 if (!ret) {
11720 vty_out(vty, "address is malformed\n");
11721 return CMD_WARNING;
11722 }
718e3744 11723
d62a17ae 11724 match.family = afi2family(afi);
b05a1c8b 11725
44c69747 11726 if (use_json)
d62a17ae 11727 json = json_object_new_object();
718e3744 11728
44c69747 11729 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11730 for (dest = bgp_table_top(rib); dest;
11731 dest = bgp_route_next(dest)) {
11732 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11733
9bcb3eef 11734 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11735 continue;
9bcb3eef 11736 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11737 if (!table)
ea47320b 11738 continue;
d62a17ae 11739
4953391b
DA
11740 rm = bgp_node_match(table, &match);
11741 if (rm == NULL)
ea47320b 11742 continue;
d62a17ae 11743
9bcb3eef 11744 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11745 if (prefix_check
b54892e0 11746 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11747 bgp_dest_unlock_node(rm);
ea47320b
DL
11748 continue;
11749 }
d62a17ae 11750
9bcb3eef 11751 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11752 bgp, afi, safi, json, pathtype,
4027d19b 11753 &display, rpki_target_state);
44c69747 11754
9bcb3eef 11755 bgp_dest_unlock_node(rm);
44c69747
LK
11756 }
11757 } else if (safi == SAFI_EVPN) {
9bcb3eef 11758 struct bgp_dest *longest_pfx;
cded3b72 11759 bool is_exact_pfxlen_match = false;
44c69747 11760
9bcb3eef
DS
11761 for (dest = bgp_table_top(rib); dest;
11762 dest = bgp_route_next(dest)) {
11763 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11764
9bcb3eef 11765 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11766 continue;
9bcb3eef 11767 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11768 if (!table)
11769 continue;
11770
11771 longest_pfx = NULL;
cded3b72 11772 is_exact_pfxlen_match = false;
44c69747
LK
11773 /*
11774 * Search through all the prefixes for a match. The
11775 * pfx's are enumerated in ascending order of pfxlens.
11776 * So, the last pfx match is the longest match. Set
11777 * is_exact_pfxlen_match when we get exact pfxlen match
11778 */
11779 for (rm = bgp_table_top(table); rm;
11780 rm = bgp_route_next(rm)) {
b54892e0 11781 const struct prefix *rm_p =
9bcb3eef 11782 bgp_dest_get_prefix(rm);
44c69747
LK
11783 /*
11784 * Get prefixlen of the ip-prefix within type5
11785 * evpn route
11786 */
b54892e0
DS
11787 if (evpn_type5_prefix_match(rm_p, &match)
11788 && rm->info) {
44c69747
LK
11789 longest_pfx = rm;
11790 int type5_pfxlen =
b54892e0
DS
11791 bgp_evpn_get_type5_prefixlen(
11792 rm_p);
44c69747 11793 if (type5_pfxlen == match.prefixlen) {
cded3b72 11794 is_exact_pfxlen_match = true;
9bcb3eef 11795 bgp_dest_unlock_node(rm);
44c69747
LK
11796 break;
11797 }
d62a17ae 11798 }
11799 }
ea47320b 11800
44c69747
LK
11801 if (!longest_pfx)
11802 continue;
11803
11804 if (prefix_check && !is_exact_pfxlen_match)
11805 continue;
11806
11807 rm = longest_pfx;
9bcb3eef 11808 bgp_dest_lock_node(rm);
44c69747 11809
9bcb3eef 11810 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11811 bgp, afi, safi, json, pathtype,
4027d19b 11812 &display, rpki_target_state);
44c69747 11813
9bcb3eef 11814 bgp_dest_unlock_node(rm);
d62a17ae 11815 }
98a9dbc7 11816 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11817 if (use_json)
11818 json_paths = json_object_new_array();
11819
63a0b7a9
PG
11820 display = bgp_flowspec_display_match_per_ip(afi, rib,
11821 &match, prefix_check,
11822 vty,
11823 use_json,
11824 json_paths);
d5f20468
SP
11825 if (use_json) {
11826 if (display)
11827 json_object_object_add(json, "paths",
11828 json_paths);
11829 else
11830 json_object_free(json_paths);
11831 }
d62a17ae 11832 } else {
4953391b
DA
11833 dest = bgp_node_match(rib, &match);
11834 if (dest != NULL) {
9bcb3eef 11835 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11836 if (!prefix_check
9bcb3eef
DS
11837 || dest_p->prefixlen == match.prefixlen) {
11838 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11839 safi, json, pathtype,
4027d19b 11840 &display, rpki_target_state);
d62a17ae 11841 }
11842
9bcb3eef 11843 bgp_dest_unlock_node(dest);
d62a17ae 11844 }
11845 }
e5eee9af 11846
d62a17ae 11847 if (use_json) {
75eeda93 11848 vty_json(vty, json);
d62a17ae 11849 } else {
11850 if (!display) {
11851 vty_out(vty, "%% Network not in table\n");
11852 return CMD_WARNING;
11853 }
11854 }
b05a1c8b 11855
d62a17ae 11856 return CMD_SUCCESS;
718e3744 11857}
11858
fee0f4c6 11859/* Display specified route of Main RIB */
d62a17ae 11860static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11861 afi_t afi, safi_t safi, struct prefix_rd *prd,
11862 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11863 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11864{
9b86009a 11865 if (!bgp) {
d62a17ae 11866 bgp = bgp_get_default();
9b86009a
RW
11867 if (!bgp) {
11868 if (!use_json)
11869 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11870 else
11871 vty_out(vty, "{}\n");
9b86009a
RW
11872 return CMD_WARNING;
11873 }
11874 }
d62a17ae 11875
11876 /* labeled-unicast routes live in the unicast table */
11877 if (safi == SAFI_LABELED_UNICAST)
11878 safi = SAFI_UNICAST;
11879
11880 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11881 afi, safi, rpki_target_state, prd,
8aa22bbb 11882 prefix_check, pathtype, use_json);
d62a17ae 11883}
11884
11885static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11886 struct cmd_token **argv, bool exact, afi_t afi,
11887 safi_t safi, bool uj)
d62a17ae 11888{
11889 struct lcommunity *lcom;
11890 struct buffer *b;
11891 int i;
11892 char *str;
11893 int first = 0;
96c81f66 11894 uint16_t show_flags = 0;
4f28b2b5 11895 int ret;
96f3485c
MK
11896
11897 if (uj)
11898 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11899
11900 b = buffer_new(1024);
11901 for (i = 0; i < argc; i++) {
11902 if (first)
11903 buffer_putc(b, ' ');
11904 else {
11905 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11906 first = 1;
11907 buffer_putstr(b, argv[i]->arg);
11908 }
11909 }
11910 }
11911 buffer_putc(b, '\0');
57d187bc 11912
d62a17ae 11913 str = buffer_getstr(b);
11914 buffer_free(b);
57d187bc 11915
d62a17ae 11916 lcom = lcommunity_str2com(str);
11917 XFREE(MTYPE_TMP, str);
11918 if (!lcom) {
11919 vty_out(vty, "%% Large-community malformed\n");
11920 return CMD_WARNING;
11921 }
57d187bc 11922
4f28b2b5 11923 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11924 (exact ? bgp_show_type_lcommunity_exact
11925 : bgp_show_type_lcommunity),
11926 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11927
11928 lcommunity_free(&lcom);
11929 return ret;
57d187bc
JS
11930}
11931
d62a17ae 11932static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11933 const char *lcom, bool exact, afi_t afi,
11934 safi_t safi, bool uj)
57d187bc 11935{
d62a17ae 11936 struct community_list *list;
96c81f66 11937 uint16_t show_flags = 0;
96f3485c
MK
11938
11939 if (uj)
11940 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11941
57d187bc 11942
e237b0d2 11943 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11944 LARGE_COMMUNITY_LIST_MASTER);
11945 if (list == NULL) {
11946 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11947 lcom);
11948 return CMD_WARNING;
11949 }
57d187bc 11950
36a206db 11951 return bgp_show(vty, bgp, afi, safi,
11952 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11953 : bgp_show_type_lcommunity_list),
1e2ce4f1 11954 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11955}
11956
52951b63
DS
11957DEFUN (show_ip_bgp_large_community_list,
11958 show_ip_bgp_large_community_list_cmd,
77a3a95e 11959 "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
11960 SHOW_STR
11961 IP_STR
11962 BGP_STR
11963 BGP_INSTANCE_HELP_STR
9bedbb1e 11964 BGP_AFI_HELP_STR
4dd6177e 11965 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11966 "Display routes matching the large-community-list\n"
11967 "large-community-list number\n"
11968 "large-community-list name\n"
36a206db 11969 "Exact match of the large-communities\n"
52951b63
DS
11970 JSON_STR)
11971{
d62a17ae 11972 afi_t afi = AFI_IP6;
11973 safi_t safi = SAFI_UNICAST;
11974 int idx = 0;
36a206db 11975 bool exact_match = 0;
4d678463 11976 struct bgp *bgp = NULL;
9f049418 11977 bool uj = use_json(argc, argv);
d62a17ae 11978
ef3364f0
DA
11979 if (uj)
11980 argc--;
4d678463 11981
ef3364f0
DA
11982 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11983 &bgp, uj);
11984 if (!idx)
11985 return CMD_WARNING;
d62a17ae 11986
11987 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11988
11989 const char *clist_number_or_name = argv[++idx]->arg;
11990
11991 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11992 exact_match = 1;
11993
11994 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11995 exact_match, afi, safi, uj);
52951b63
DS
11996}
11997DEFUN (show_ip_bgp_large_community,
11998 show_ip_bgp_large_community_cmd,
36a206db 11999 "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
12000 SHOW_STR
12001 IP_STR
12002 BGP_STR
12003 BGP_INSTANCE_HELP_STR
9bedbb1e 12004 BGP_AFI_HELP_STR
4dd6177e 12005 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12006 "Display routes matching the large-communities\n"
12007 "List of large-community numbers\n"
36a206db 12008 "Exact match of the large-communities\n"
52951b63
DS
12009 JSON_STR)
12010{
d62a17ae 12011 afi_t afi = AFI_IP6;
12012 safi_t safi = SAFI_UNICAST;
12013 int idx = 0;
36a206db 12014 bool exact_match = 0;
4d678463 12015 struct bgp *bgp = NULL;
9f049418 12016 bool uj = use_json(argc, argv);
96c81f66 12017 uint16_t show_flags = 0;
d62a17ae 12018
96f3485c
MK
12019 if (uj) {
12020 argc--;
12021 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12022 }
4d678463 12023
96f3485c
MK
12024 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12025 &bgp, uj);
12026 if (!idx)
12027 return CMD_WARNING;
d62a17ae 12028
36a206db 12029 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12030 if (argv_find(argv, argc, "exact-match", &idx))
12031 exact_match = 1;
12032 return bgp_show_lcommunity(vty, bgp, argc, argv,
12033 exact_match, afi, safi, uj);
12034 } else
d62a17ae 12035 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12036 bgp_show_type_lcommunity_all, NULL, show_flags,
12037 RPKI_NOT_BEING_USED);
52951b63
DS
12038}
12039
71f1613a
DA
12040static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12041 safi_t safi, struct json_object *json_array);
d62a17ae 12042static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12043 safi_t safi, struct json_object *json);
e01ca200 12044
7b2ff250 12045
9ab0cf58
PG
12046DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12047 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12048 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12049 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12050{
12051 bool uj = use_json(argc, argv);
12052 struct bgp *bgp = NULL;
ec76a1d1
DA
12053 safi_t safi = SAFI_UNICAST;
12054 afi_t afi = AFI_IP6;
4265b261 12055 int idx = 0;
6c9d22e2
PG
12056 struct json_object *json_all = NULL;
12057 struct json_object *json_afi_safi = NULL;
4265b261
PG
12058
12059 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12060 &bgp, false);
71f1613a 12061 if (!idx)
4265b261 12062 return CMD_WARNING;
6c9d22e2 12063
4265b261 12064 if (uj)
6c9d22e2 12065 json_all = json_object_new_object();
4265b261 12066
9ab0cf58
PG
12067 FOREACH_AFI_SAFI (afi, safi) {
12068 /*
12069 * So limit output to those afi/safi pairs that
12070 * actually have something interesting in them
12071 */
12072 if (strmatch(get_afi_safi_str(afi, safi, true),
12073 "Unknown")) {
12074 continue;
12075 }
12076 if (uj) {
12077 json_afi_safi = json_object_new_array();
12078 json_object_object_add(
12079 json_all,
12080 get_afi_safi_str(afi, safi, true),
12081 json_afi_safi);
12082 } else {
12083 json_afi_safi = NULL;
6c9d22e2 12084 }
9ab0cf58
PG
12085
12086 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12087 }
6c9d22e2 12088
3757f964
DA
12089 if (uj)
12090 vty_json(vty, json_all);
6c9d22e2 12091
4265b261
PG
12092 return CMD_SUCCESS;
12093}
12094
7b2ff250 12095/* BGP route print out function without JSON */
14718643
PG
12096DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12097 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12098 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12099 SHOW_STR
12100 IP_STR
12101 BGP_STR
12102 BGP_INSTANCE_HELP_STR
12103 L2VPN_HELP_STR
12104 EVPN_HELP_STR
12105 "BGP RIB advertisement statistics\n"
12106 JSON_STR)
12107{
ec76a1d1
DA
12108 afi_t afi = AFI_IP6;
12109 safi_t safi = SAFI_UNICAST;
14718643
PG
12110 struct bgp *bgp = NULL;
12111 int idx = 0, ret;
12112 bool uj = use_json(argc, argv);
12113 struct json_object *json_afi_safi = NULL, *json = NULL;
12114
12115 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12116 &bgp, false);
12117 if (!idx)
12118 return CMD_WARNING;
12119
12120 if (uj)
12121 json_afi_safi = json_object_new_array();
12122 else
12123 json_afi_safi = NULL;
12124
12125 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12126
12127 if (uj) {
12128 json = json_object_new_object();
12129 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12130 json_afi_safi);
3757f964 12131 vty_json(vty, json);
14718643
PG
12132 }
12133 return ret;
12134}
12135
893cccd0 12136/* BGP route print out function without JSON */
9ab0cf58
PG
12137DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12138 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12139 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12140 "]]\
893cccd0 12141 statistics [json]",
9ab0cf58
PG
12142 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12143 BGP_SAFI_WITH_LABEL_HELP_STR
12144 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12145{
ec76a1d1
DA
12146 afi_t afi = AFI_IP6;
12147 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12148 struct bgp *bgp = NULL;
12149 int idx = 0, ret;
12150 bool uj = use_json(argc, argv);
6c9d22e2 12151 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12152
12153 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12154 &bgp, false);
12155 if (!idx)
12156 return CMD_WARNING;
6c9d22e2 12157
893cccd0 12158 if (uj)
6c9d22e2
PG
12159 json_afi_safi = json_object_new_array();
12160 else
12161 json_afi_safi = NULL;
12162
12163 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12164
12165 if (uj) {
12166 json = json_object_new_object();
12167 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12168 json_afi_safi);
3757f964 12169 vty_json(vty, json);
893cccd0
PG
12170 }
12171 return ret;
893cccd0 12172}
7b2ff250 12173
fe0f234d 12174DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12175 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12176 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12177 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12178 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12179 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12180 "Display the entries for all address families\n"
9ab0cf58
PG
12181 "Display detailed information about dampening\n"
12182 "Display detail of configured dampening parameters\n"
fe0f234d 12183 JSON_STR)
718e3744 12184{
d62a17ae 12185 afi_t afi = AFI_IP6;
12186 safi_t safi = SAFI_UNICAST;
d62a17ae 12187 struct bgp *bgp = NULL;
12188 int idx = 0;
96c81f66 12189 uint16_t show_flags = 0;
fe0f234d
RW
12190 bool uj = use_json(argc, argv);
12191
12192 if (uj) {
12193 argc--;
12194 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12195 }
96f3485c
MK
12196
12197 /* [<ipv4|ipv6> [all]] */
12198 if (all) {
12199 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12200 if (argv_find(argv, argc, "ipv4", &idx))
12201 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12202
12203 if (argv_find(argv, argc, "ipv6", &idx))
12204 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12205 }
d62a17ae 12206
12207 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12208 &bgp, false);
d62a17ae 12209 if (!idx)
12210 return CMD_WARNING;
12211
fe0f234d 12212 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12213}
12214
fe0f234d
RW
12215/* BGP route print out function */
12216DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12217 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12218 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12219 "]]\
96f3485c 12220 [all$all]\
cf4898bc
QY
12221 [cidr-only\
12222 |dampening <flap-statistics|dampened-paths>\
12223 |community [AA:NN|local-AS|no-advertise|no-export\
12224 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12225 |accept-own|accept-own-nexthop|route-filter-v6\
12226 |route-filter-v4|route-filter-translated-v6\
12227 |route-filter-translated-v4] [exact-match]\
70799983 12228 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12229 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12230 |prefix-list WORD\
70dd370f 12231 |route-map RMAP_NAME\
1e2ce4f1 12232 |rpki <invalid|valid|notfound>\
7d3cae70 12233 |version (1-4294967295)\
b4ad2fae 12234 |alias ALIAS_NAME\
39c3c736
RW
12235 |A.B.C.D/M longer-prefixes\
12236 |X:X::X:X/M longer-prefixes\
f280c93b 12237 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12238 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12239 BGP_SAFI_WITH_LABEL_HELP_STR
12240 "Display the entries for all address families\n"
12241 "Display only routes with non-natural netmasks\n"
12242 "Display detailed information about dampening\n"
12243 "Display flap statistics of routes\n"
12244 "Display paths suppressed due to dampening\n"
12245 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12246 "Do not send outside local AS (well-known community)\n"
12247 "Do not advertise to any peer (well-known community)\n"
12248 "Do not export to next AS (well-known community)\n"
12249 "Graceful shutdown (well-known community)\n"
12250 "Do not export to any peer (well-known community)\n"
12251 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12252 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12253 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12254 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12255 "Should accept VPN route with local nexthop (well-known community)\n"
12256 "RT VPNv6 route filtering (well-known community)\n"
12257 "RT VPNv4 route filtering (well-known community)\n"
12258 "RT translated VPNv6 route filtering (well-known community)\n"
12259 "RT translated VPNv4 route filtering (well-known community)\n"
12260 "Exact match of the communities\n"
70799983
RW
12261 "Community-list number\n"
12262 "Community-list name\n"
12263 "Display routes matching the community-list\n"
12264 "Exact match of the communities\n"
a7129347
RW
12265 "Display routes conforming to the filter-list\n"
12266 "Regular expression access list name\n"
6deaf579
RW
12267 "Display routes conforming to the prefix-list\n"
12268 "Prefix-list name\n"
bf1a944a
RW
12269 "Display routes matching the route-map\n"
12270 "A route-map to match on\n"
a70a28a5
DA
12271 "RPKI route types\n"
12272 "A valid path as determined by rpki\n"
12273 "A invalid path as determined by rpki\n"
12274 "A path that has no rpki data\n"
12275 "Display prefixes with matching version numbers\n"
12276 "Version number and above\n"
12277 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12278 "BGP community alias\n"
12279 "IPv4 prefix\n"
12280 "Display route and more specific routes\n"
12281 "IPv6 prefix\n"
12282 "Display route and more specific routes\n"
12283 JSON_STR
a70a28a5
DA
12284 "Display detailed version of JSON output\n"
12285 "Increase table width for longer prefixes\n")
7b2ff250
DW
12286{
12287 afi_t afi = AFI_IP6;
12288 safi_t safi = SAFI_UNICAST;
12289 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12290 void *output_arg = NULL;
7b2ff250
DW
12291 struct bgp *bgp = NULL;
12292 int idx = 0;
d0086e8e 12293 int exact_match = 0;
96f3485c
MK
12294 char *community = NULL;
12295 bool first = true;
96c81f66 12296 uint16_t show_flags = 0;
4027d19b 12297 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12298 struct prefix p;
96f3485c
MK
12299
12300 if (uj) {
9f049418 12301 argc--;
96f3485c
MK
12302 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12303 }
12304
f280c93b
DA
12305 if (detail)
12306 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12307
96f3485c
MK
12308 /* [<ipv4|ipv6> [all]] */
12309 if (all) {
12310 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12311
12312 if (argv_find(argv, argc, "ipv4", &idx))
12313 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12314
12315 if (argv_find(argv, argc, "ipv6", &idx))
12316 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12317 }
12318
12319 if (wide)
12320 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12321
12322 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12323 &bgp, uj);
7b2ff250
DW
12324 if (!idx)
12325 return CMD_WARNING;
12326
7b2ff250 12327 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12328 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12329
12330 if (argv_find(argv, argc, "dampening", &idx)) {
12331 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12332 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12333 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12334 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12335 }
12336
12337 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12338 char *maybecomm = NULL;
d0086e8e 12339
79bc257a
RW
12340 if (idx + 1 < argc) {
12341 if (argv[idx + 1]->type == VARIABLE_TKN)
12342 maybecomm = argv[idx + 1]->arg;
12343 else
12344 maybecomm = argv[idx + 1]->text;
12345 }
12346
cf4898bc
QY
12347 if (maybecomm && !strmatch(maybecomm, "json")
12348 && !strmatch(maybecomm, "exact-match"))
12349 community = maybecomm;
d0086e8e 12350
cf4898bc
QY
12351 if (argv_find(argv, argc, "exact-match", &idx))
12352 exact_match = 1;
d0086e8e 12353
96f3485c
MK
12354 if (!community)
12355 sh_type = bgp_show_type_community_all;
12356 }
12357
70799983
RW
12358 if (argv_find(argv, argc, "community-list", &idx)) {
12359 const char *clist_number_or_name = argv[++idx]->arg;
12360 struct community_list *list;
12361
12362 if (argv_find(argv, argc, "exact-match", &idx))
12363 exact_match = 1;
12364
12365 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12366 COMMUNITY_LIST_MASTER);
12367 if (list == NULL) {
12368 vty_out(vty,
12369 "%% %s is not a valid community-list name\n",
12370 clist_number_or_name);
12371 return CMD_WARNING;
12372 }
12373
12374 if (exact_match)
12375 sh_type = bgp_show_type_community_list_exact;
12376 else
12377 sh_type = bgp_show_type_community_list;
12378 output_arg = list;
12379 }
12380
a7129347
RW
12381 if (argv_find(argv, argc, "filter-list", &idx)) {
12382 const char *filter = argv[++idx]->arg;
12383 struct as_list *as_list;
12384
12385 as_list = as_list_lookup(filter);
12386 if (as_list == NULL) {
12387 vty_out(vty,
12388 "%% %s is not a valid AS-path access-list name\n",
12389 filter);
12390 return CMD_WARNING;
12391 }
12392
12393 sh_type = bgp_show_type_filter_list;
12394 output_arg = as_list;
12395 }
12396
6deaf579
RW
12397 if (argv_find(argv, argc, "prefix-list", &idx)) {
12398 const char *prefix_list_str = argv[++idx]->arg;
12399 struct prefix_list *plist;
12400
12401 plist = prefix_list_lookup(afi, prefix_list_str);
12402 if (plist == NULL) {
12403 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12404 prefix_list_str);
12405 return CMD_WARNING;
12406 }
12407
12408 sh_type = bgp_show_type_prefix_list;
12409 output_arg = plist;
12410 }
12411
bf1a944a
RW
12412 if (argv_find(argv, argc, "route-map", &idx)) {
12413 const char *rmap_str = argv[++idx]->arg;
12414 struct route_map *rmap;
12415
12416 rmap = route_map_lookup_by_name(rmap_str);
12417 if (!rmap) {
12418 vty_out(vty, "%% %s is not a valid route-map name\n",
12419 rmap_str);
12420 return CMD_WARNING;
12421 }
12422
12423 sh_type = bgp_show_type_route_map;
12424 output_arg = rmap;
12425 }
12426
1e2ce4f1
DS
12427 if (argv_find(argv, argc, "rpki", &idx)) {
12428 sh_type = bgp_show_type_rpki;
12429 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12430 rpki_target_state = RPKI_VALID;
1e2ce4f1 12431 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12432 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12433 }
12434
7d3cae70
DA
12435 /* Display prefixes with matching version numbers */
12436 if (argv_find(argv, argc, "version", &idx)) {
12437 sh_type = bgp_show_type_prefix_version;
2391833e 12438 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12439 }
12440
a70a28a5
DA
12441 /* Display prefixes with matching BGP community alias */
12442 if (argv_find(argv, argc, "alias", &idx)) {
12443 sh_type = bgp_show_type_community_alias;
2391833e 12444 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12445 }
12446
39c3c736
RW
12447 /* prefix-longer */
12448 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12449 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12450 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12451
12452 if (!str2prefix(prefix_str, &p)) {
12453 vty_out(vty, "%% Malformed Prefix\n");
12454 return CMD_WARNING;
12455 }
12456
12457 sh_type = bgp_show_type_prefix_longer;
12458 output_arg = &p;
a70a28a5
DA
12459 }
12460
96f3485c
MK
12461 if (!all) {
12462 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12463 if (community)
12464 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12465 exact_match, afi, safi,
12466 show_flags);
2391833e 12467 else
a70a28a5 12468 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12469 output_arg, show_flags,
a70a28a5 12470 rpki_target_state);
96f3485c 12471 } else {
fa5ac378
DA
12472 struct listnode *node;
12473 struct bgp *abgp;
96f3485c
MK
12474 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12475 * AFI_IP6 */
12476
12477 if (uj)
12478 vty_out(vty, "{\n");
12479
12480 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12481 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12482 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12483 ? AFI_IP
12484 : AFI_IP6;
fa5ac378
DA
12485 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12486 FOREACH_SAFI (safi) {
12487 if (!bgp_afi_safi_peer_exists(abgp, afi,
12488 safi))
12489 continue;
96f3485c 12490
fa5ac378
DA
12491 if (uj) {
12492 if (first)
12493 first = false;
12494 else
12495 vty_out(vty, ",\n");
12496 vty_out(vty, "\"%s\":{\n",
12497 get_afi_safi_str(afi,
12498 safi,
12499 true));
12500 } else
12501 vty_out(vty,
12502 "\nFor address family: %s\n",
12503 get_afi_safi_str(
12504 afi, safi,
12505 false));
12506
12507 if (community)
12508 bgp_show_community(
12509 vty, abgp, community,
12510 exact_match, afi, safi,
12511 show_flags);
96f3485c 12512 else
fa5ac378
DA
12513 bgp_show(vty, abgp, afi, safi,
12514 sh_type, output_arg,
12515 show_flags,
12516 rpki_target_state);
12517 if (uj)
12518 vty_out(vty, "}\n");
12519 }
96f3485c
MK
12520 }
12521 } else {
12522 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12523 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12524 FOREACH_AFI_SAFI (afi, safi) {
12525 if (!bgp_afi_safi_peer_exists(abgp, afi,
12526 safi))
12527 continue;
96f3485c 12528
fa5ac378
DA
12529 if (uj) {
12530 if (first)
12531 first = false;
12532 else
12533 vty_out(vty, ",\n");
12534
12535 vty_out(vty, "\"%s\":{\n",
12536 get_afi_safi_str(afi,
12537 safi,
12538 true));
12539 } else
12540 vty_out(vty,
12541 "\nFor address family: %s\n",
12542 get_afi_safi_str(
12543 afi, safi,
12544 false));
12545
12546 if (community)
12547 bgp_show_community(
12548 vty, abgp, community,
12549 exact_match, afi, safi,
12550 show_flags);
96f3485c 12551 else
fa5ac378
DA
12552 bgp_show(vty, abgp, afi, safi,
12553 sh_type, output_arg,
12554 show_flags,
12555 rpki_target_state);
12556 if (uj)
12557 vty_out(vty, "}\n");
12558 }
96f3485c
MK
12559 }
12560 }
12561 if (uj)
12562 vty_out(vty, "}\n");
12563 }
12564 return CMD_SUCCESS;
a636c635 12565}
47fc97cc 12566
718e3744 12567DEFUN (show_ip_bgp_route,
12568 show_ip_bgp_route_cmd,
8aa22bbb 12569 "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 12570 SHOW_STR
12571 IP_STR
12572 BGP_STR
a636c635 12573 BGP_INSTANCE_HELP_STR
4f280b15 12574 BGP_AFI_HELP_STR
4dd6177e 12575 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12576 "Network in the BGP routing table to display\n"
0c7b1b01 12577 "IPv4 prefix\n"
8c3deaae 12578 "Network in the BGP routing table to display\n"
0c7b1b01 12579 "IPv6 prefix\n"
4092b06c 12580 "Display only the bestpath\n"
b05a1c8b 12581 "Display only multipaths\n"
8aa22bbb
DS
12582 "Display only paths that match the specified rpki state\n"
12583 "A valid path as determined by rpki\n"
12584 "A invalid path as determined by rpki\n"
12585 "A path that has no rpki data\n"
9973d184 12586 JSON_STR)
4092b06c 12587{
d62a17ae 12588 int prefix_check = 0;
ae19d7dd 12589
d62a17ae 12590 afi_t afi = AFI_IP6;
12591 safi_t safi = SAFI_UNICAST;
12592 char *prefix = NULL;
12593 struct bgp *bgp = NULL;
12594 enum bgp_path_type path_type;
9f049418 12595 bool uj = use_json(argc, argv);
b05a1c8b 12596
d62a17ae 12597 int idx = 0;
ae19d7dd 12598
d62a17ae 12599 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12600 &bgp, uj);
d62a17ae 12601 if (!idx)
12602 return CMD_WARNING;
c41247f5 12603
d62a17ae 12604 if (!bgp) {
12605 vty_out(vty,
12606 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12607 return CMD_WARNING;
12608 }
a636c635 12609
d62a17ae 12610 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12611 if (argv_find(argv, argc, "A.B.C.D", &idx)
12612 || argv_find(argv, argc, "X:X::X:X", &idx))
12613 prefix_check = 0;
12614 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12615 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12616 prefix_check = 1;
12617
12618 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12619 && afi != AFI_IP6) {
12620 vty_out(vty,
12621 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12622 return CMD_WARNING;
12623 }
12624 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12625 && afi != AFI_IP) {
12626 vty_out(vty,
12627 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12628 return CMD_WARNING;
12629 }
12630
12631 prefix = argv[idx]->arg;
12632
12633 /* [<bestpath|multipath>] */
12634 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12635 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12636 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12637 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12638 else
360660c6 12639 path_type = BGP_PATH_SHOW_ALL;
a636c635 12640
d62a17ae 12641 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12642 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12643}
12644
8c3deaae
QY
12645DEFUN (show_ip_bgp_regexp,
12646 show_ip_bgp_regexp_cmd,
3e5b31b3 12647 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12648 SHOW_STR
12649 IP_STR
12650 BGP_STR
b00b230a 12651 BGP_INSTANCE_HELP_STR
4f280b15 12652 BGP_AFI_HELP_STR
4dd6177e 12653 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12654 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12655 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12656 JSON_STR)
8c3deaae 12657{
d62a17ae 12658 afi_t afi = AFI_IP6;
12659 safi_t safi = SAFI_UNICAST;
12660 struct bgp *bgp = NULL;
3e5b31b3
DA
12661 bool uj = use_json(argc, argv);
12662 char *regstr = NULL;
8c3deaae 12663
d62a17ae 12664 int idx = 0;
12665 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12666 &bgp, false);
d62a17ae 12667 if (!idx)
12668 return CMD_WARNING;
8c3deaae 12669
d62a17ae 12670 // get index of regex
3e5b31b3
DA
12671 if (argv_find(argv, argc, "REGEX", &idx))
12672 regstr = argv[idx]->arg;
8c3deaae 12673
5f71d11c 12674 assert(regstr);
3e5b31b3
DA
12675 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12676 bgp_show_type_regexp, uj);
8c3deaae
QY
12677}
12678
ae248832 12679DEFPY (show_ip_bgp_instance_all,
a636c635 12680 show_ip_bgp_instance_all_cmd,
ae248832 12681 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12682 SHOW_STR
a636c635 12683 IP_STR
4092b06c 12684 BGP_STR
a636c635 12685 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12686 BGP_AFI_HELP_STR
4dd6177e 12687 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12688 JSON_STR
12689 "Increase table width for longer prefixes\n")
4092b06c 12690{
54d05dea 12691 afi_t afi = AFI_IP6;
d62a17ae 12692 safi_t safi = SAFI_UNICAST;
12693 struct bgp *bgp = NULL;
d62a17ae 12694 int idx = 0;
96c81f66 12695 uint16_t show_flags = 0;
ae19d7dd 12696
96f3485c 12697 if (uj) {
d62a17ae 12698 argc--;
96f3485c
MK
12699 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12700 }
12701
12702 if (wide)
12703 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12704
9f049418
DS
12705 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12706 &bgp, uj);
12707 if (!idx)
12708 return CMD_WARNING;
12709
96f3485c 12710 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12711 return CMD_SUCCESS;
e3e29b32
LB
12712}
12713
a4d82a8a 12714static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12715 afi_t afi, safi_t safi, enum bgp_show_type type,
12716 bool use_json)
718e3744 12717{
d62a17ae 12718 regex_t *regex;
12719 int rc;
96c81f66 12720 uint16_t show_flags = 0;
96f3485c
MK
12721
12722 if (use_json)
12723 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12724
c3900853 12725 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12726 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12727 regstr);
12728 return CMD_WARNING_CONFIG_FAILED;
12729 }
12730
d62a17ae 12731 regex = bgp_regcomp(regstr);
12732 if (!regex) {
12733 vty_out(vty, "Can't compile regexp %s\n", regstr);
12734 return CMD_WARNING;
12735 }
a636c635 12736
1e2ce4f1
DS
12737 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12738 RPKI_NOT_BEING_USED);
d62a17ae 12739 bgp_regex_free(regex);
12740 return rc;
e3e29b32
LB
12741}
12742
7f323236
DW
12743static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12744 const char *comstr, int exact, afi_t afi,
96c81f66 12745 safi_t safi, uint16_t show_flags)
d62a17ae 12746{
12747 struct community *com;
d62a17ae 12748 int ret = 0;
12749
7f323236 12750 com = community_str2com(comstr);
d62a17ae 12751 if (!com) {
7f323236 12752 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12753 return CMD_WARNING;
12754 }
12755
12756 ret = bgp_show(vty, bgp, afi, safi,
12757 (exact ? bgp_show_type_community_exact
12758 : bgp_show_type_community),
1e2ce4f1 12759 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12760 community_free(&com);
46c3ce83 12761
d62a17ae 12762 return ret;
718e3744 12763}
12764
d62a17ae 12765enum bgp_stats {
12766 BGP_STATS_MAXBITLEN = 0,
12767 BGP_STATS_RIB,
12768 BGP_STATS_PREFIXES,
12769 BGP_STATS_TOTPLEN,
12770 BGP_STATS_UNAGGREGATEABLE,
12771 BGP_STATS_MAX_AGGREGATEABLE,
12772 BGP_STATS_AGGREGATES,
12773 BGP_STATS_SPACE,
12774 BGP_STATS_ASPATH_COUNT,
12775 BGP_STATS_ASPATH_MAXHOPS,
12776 BGP_STATS_ASPATH_TOTHOPS,
12777 BGP_STATS_ASPATH_MAXSIZE,
12778 BGP_STATS_ASPATH_TOTSIZE,
12779 BGP_STATS_ASN_HIGHEST,
12780 BGP_STATS_MAX,
a636c635 12781};
2815e61f 12782
9ab0cf58 12783#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12784#define TABLE_STATS_IDX_JSON 1
12785
12786static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12787 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12788 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12789 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12790 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12791 "unaggregateablePrefixes"},
12792 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12793 "maximumAggregateablePrefixes"},
12794 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12795 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12796 [BGP_STATS_SPACE] = {"Address space advertised",
12797 "addressSpaceAdvertised"},
9ab0cf58
PG
12798 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12799 "advertisementsWithPaths"},
12800 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12801 "longestAsPath"},
12802 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12803 "largestAsPath"},
12804 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12805 "averageAsPathLengthHops"},
12806 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12807 "averageAsPathSizeBytes"},
12808 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12809 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12810};
2815e61f 12811
d62a17ae 12812struct bgp_table_stats {
12813 struct bgp_table *table;
12814 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12815 double total_space;
ff7924f6
PJ
12816};
12817
9bcb3eef 12818static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12819 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12820{
9bcb3eef 12821 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12822 struct bgp_path_info *pi;
b54892e0 12823 const struct prefix *rn_p;
d62a17ae 12824
9bcb3eef 12825 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12826 return;
d62a17ae 12827
9bcb3eef 12828 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12829 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12830 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12831
9c14ec72 12832 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12833 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12834 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12835
9bcb3eef 12836 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12837 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12838 /* announced address space */
12839 if (space)
b54892e0 12840 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12841 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12842 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12843
9c14ec72 12844
9bcb3eef 12845 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12846 ts->counts[BGP_STATS_RIB]++;
12847
05864da7
DS
12848 if (CHECK_FLAG(pi->attr->flag,
12849 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12850 ts->counts[BGP_STATS_AGGREGATES]++;
12851
12852 /* as-path stats */
05864da7 12853 if (pi->attr->aspath) {
9c14ec72
RW
12854 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12855 unsigned int size = aspath_size(pi->attr->aspath);
12856 as_t highest = aspath_highest(pi->attr->aspath);
12857
12858 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12859
12860 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12861 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12862
12863 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12864 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12865
12866 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12867 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12868 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12869 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12870 }
12871 }
12872}
12873
cc9f21da 12874static void bgp_table_stats_walker(struct thread *t)
9c14ec72 12875{
9bcb3eef
DS
12876 struct bgp_dest *dest, *ndest;
12877 struct bgp_dest *top;
9c14ec72
RW
12878 struct bgp_table_stats *ts = THREAD_ARG(t);
12879 unsigned int space = 0;
12880
12881 if (!(top = bgp_table_top(ts->table)))
cc9f21da 12882 return;
9c14ec72
RW
12883
12884 switch (ts->table->afi) {
12885 case AFI_IP:
12886 space = IPV4_MAX_BITLEN;
12887 break;
12888 case AFI_IP6:
12889 space = IPV6_MAX_BITLEN;
12890 break;
3ba7b4af
TA
12891 case AFI_L2VPN:
12892 space = EVPN_ROUTE_PREFIXLEN;
12893 break;
9c14ec72 12894 default:
cc9f21da 12895 return;
9c14ec72
RW
12896 }
12897
12898 ts->counts[BGP_STATS_MAXBITLEN] = space;
12899
9bcb3eef 12900 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12901 if (ts->table->safi == SAFI_MPLS_VPN
12902 || ts->table->safi == SAFI_ENCAP
12903 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12904 struct bgp_table *table;
12905
9bcb3eef 12906 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12907 if (!table)
12908 continue;
12909
12910 top = bgp_table_top(table);
9bcb3eef
DS
12911 for (ndest = bgp_table_top(table); ndest;
12912 ndest = bgp_route_next(ndest))
12913 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12914 } else {
9bcb3eef 12915 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12916 }
12917 }
2815e61f 12918}
ff7924f6 12919
71f1613a
DA
12920static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12921 struct json_object *json_array)
12922{
12923 struct listnode *node, *nnode;
12924 struct bgp *bgp;
12925
12926 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12927 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12928}
12929
12930static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12931 safi_t safi, struct json_object *json_array)
2815e61f 12932{
d62a17ae 12933 struct bgp_table_stats ts;
12934 unsigned int i;
893cccd0
PG
12935 int ret = CMD_SUCCESS;
12936 char temp_buf[20];
6c9d22e2
PG
12937 struct json_object *json = NULL;
12938
12939 if (json_array)
12940 json = json_object_new_object();
019386c2 12941
d62a17ae 12942 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12943 char warning_msg[50];
12944
12945 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12946 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12947 safi);
6c9d22e2
PG
12948
12949 if (!json)
893cccd0
PG
12950 vty_out(vty, "%s\n", warning_msg);
12951 else
9ab0cf58 12952 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12953
893cccd0
PG
12954 ret = CMD_WARNING;
12955 goto end_table_stats;
d62a17ae 12956 }
019386c2 12957
893cccd0 12958 if (!json)
5290ceab
DA
12959 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12960 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12961 else
12962 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12963
d62a17ae 12964 /* labeled-unicast routes live in the unicast table */
12965 if (safi == SAFI_LABELED_UNICAST)
12966 safi = SAFI_UNICAST;
019386c2 12967
d62a17ae 12968 memset(&ts, 0, sizeof(ts));
12969 ts.table = bgp->rib[afi][safi];
12970 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12971
d62a17ae 12972 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12973 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12974 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12975 continue;
12976
12977 switch (i) {
d62a17ae 12978 case BGP_STATS_ASPATH_TOTHOPS:
12979 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12980 if (!json) {
9ab0cf58
PG
12981 snprintf(
12982 temp_buf, sizeof(temp_buf), "%12.2f",
12983 ts.counts[i]
12984 ? (float)ts.counts[i]
12985 / (float)ts.counts
12986 [BGP_STATS_ASPATH_COUNT]
12987 : 0);
893cccd0 12988 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12989 table_stats_strs[i]
12990 [TABLE_STATS_IDX_VTY],
893cccd0 12991 temp_buf);
9ab0cf58
PG
12992 } else {
12993 json_object_double_add(
12994 json,
12995 table_stats_strs[i]
12996 [TABLE_STATS_IDX_JSON],
12997 ts.counts[i]
12998 ? (double)ts.counts[i]
12999 / (double)ts.counts
d62a17ae 13000 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13001 : 0);
13002 }
d62a17ae 13003 break;
13004 case BGP_STATS_TOTPLEN:
6c9d22e2 13005 if (!json) {
9ab0cf58
PG
13006 snprintf(
13007 temp_buf, sizeof(temp_buf), "%12.2f",
13008 ts.counts[i]
13009 ? (float)ts.counts[i]
13010 / (float)ts.counts
13011 [BGP_STATS_PREFIXES]
13012 : 0);
893cccd0 13013 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13014 table_stats_strs[i]
13015 [TABLE_STATS_IDX_VTY],
893cccd0 13016 temp_buf);
9ab0cf58
PG
13017 } else {
13018 json_object_double_add(
13019 json,
13020 table_stats_strs[i]
13021 [TABLE_STATS_IDX_JSON],
13022 ts.counts[i]
13023 ? (double)ts.counts[i]
13024 / (double)ts.counts
d62a17ae 13025 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13026 : 0);
13027 }
d62a17ae 13028 break;
13029 case BGP_STATS_SPACE:
6c9d22e2
PG
13030 if (!json) {
13031 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13032 ts.total_space);
893cccd0 13033 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13034 table_stats_strs[i]
13035 [TABLE_STATS_IDX_VTY],
893cccd0 13036 temp_buf);
9ab0cf58
PG
13037 } else {
13038 json_object_double_add(
13039 json,
13040 table_stats_strs[i]
13041 [TABLE_STATS_IDX_JSON],
13042 (double)ts.total_space);
13043 }
8d0ab76d 13044 if (afi == AFI_IP6) {
6c9d22e2
PG
13045 if (!json) {
13046 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13047 "%12g",
13048 ts.total_space
13049 * pow(2.0, -128 + 32));
6c9d22e2
PG
13050 vty_out(vty, "%30s: %s\n",
13051 "/32 equivalent %s\n",
13052 temp_buf);
9ab0cf58
PG
13053 } else {
13054 json_object_double_add(
13055 json, "/32equivalent",
13056 (double)(ts.total_space
13057 * pow(2.0,
13058 -128 + 32)));
13059 }
6c9d22e2
PG
13060 if (!json) {
13061 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13062 "%12g",
13063 ts.total_space
13064 * pow(2.0, -128 + 48));
6c9d22e2
PG
13065 vty_out(vty, "%30s: %s\n",
13066 "/48 equivalent %s\n",
13067 temp_buf);
9ab0cf58
PG
13068 } else {
13069 json_object_double_add(
13070 json, "/48equivalent",
13071 (double)(ts.total_space
13072 * pow(2.0,
13073 -128 + 48)));
13074 }
8d0ab76d 13075 } else {
6c9d22e2
PG
13076 if (!json) {
13077 snprintf(temp_buf, sizeof(temp_buf),
13078 "%12.2f",
9ab0cf58
PG
13079 ts.total_space * 100.
13080 * pow(2.0, -32));
6c9d22e2 13081 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13082 "% announced ", temp_buf);
13083 } else {
13084 json_object_double_add(
13085 json, "%announced",
13086 (double)(ts.total_space * 100.
13087 * pow(2.0, -32)));
13088 }
6c9d22e2
PG
13089 if (!json) {
13090 snprintf(temp_buf, sizeof(temp_buf),
13091 "%12.2f",
9ab0cf58
PG
13092 ts.total_space
13093 * pow(2.0, -32 + 8));
6c9d22e2
PG
13094 vty_out(vty, "%30s: %s\n",
13095 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13096 } else {
13097 json_object_double_add(
13098 json, "/8equivalent",
13099 (double)(ts.total_space
13100 * pow(2.0, -32 + 8)));
13101 }
6c9d22e2
PG
13102 if (!json) {
13103 snprintf(temp_buf, sizeof(temp_buf),
13104 "%12.2f",
9ab0cf58
PG
13105 ts.total_space
13106 * pow(2.0, -32 + 24));
6c9d22e2 13107 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13108 "/24 equivalent ", temp_buf);
13109 } else {
13110 json_object_double_add(
13111 json, "/24equivalent",
13112 (double)(ts.total_space
13113 * pow(2.0, -32 + 24)));
13114 }
8d0ab76d 13115 }
d62a17ae 13116 break;
13117 default:
6c9d22e2
PG
13118 if (!json) {
13119 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13120 ts.counts[i]);
893cccd0 13121 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13122 table_stats_strs[i]
13123 [TABLE_STATS_IDX_VTY],
13124 temp_buf);
13125 } else {
13126 json_object_int_add(
13127 json,
13128 table_stats_strs[i]
13129 [TABLE_STATS_IDX_JSON],
13130 ts.counts[i]);
13131 }
d62a17ae 13132 }
893cccd0
PG
13133 if (!json)
13134 vty_out(vty, "\n");
d62a17ae 13135 }
9ab0cf58 13136end_table_stats:
6c9d22e2
PG
13137 if (json)
13138 json_object_array_add(json_array, json);
893cccd0 13139 return ret;
d62a17ae 13140}
13141
71f1613a
DA
13142static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13143 safi_t safi, struct json_object *json_array)
13144{
13145 if (!bgp) {
13146 bgp_table_stats_all(vty, afi, safi, json_array);
13147 return CMD_SUCCESS;
13148 }
13149
13150 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13151}
13152
d62a17ae 13153enum bgp_pcounts {
13154 PCOUNT_ADJ_IN = 0,
13155 PCOUNT_DAMPED,
13156 PCOUNT_REMOVED,
13157 PCOUNT_HISTORY,
13158 PCOUNT_STALE,
13159 PCOUNT_VALID,
13160 PCOUNT_ALL,
13161 PCOUNT_COUNTED,
7e3d9632 13162 PCOUNT_BPATH_SELECTED,
d62a17ae 13163 PCOUNT_PFCNT, /* the figure we display to users */
13164 PCOUNT_MAX,
a636c635 13165};
718e3744 13166
2b64873d 13167static const char *const pcount_strs[] = {
9d303b37
DL
13168 [PCOUNT_ADJ_IN] = "Adj-in",
13169 [PCOUNT_DAMPED] = "Damped",
13170 [PCOUNT_REMOVED] = "Removed",
13171 [PCOUNT_HISTORY] = "History",
13172 [PCOUNT_STALE] = "Stale",
13173 [PCOUNT_VALID] = "Valid",
13174 [PCOUNT_ALL] = "All RIB",
13175 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13176 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13177 [PCOUNT_PFCNT] = "Useable",
13178 [PCOUNT_MAX] = NULL,
a636c635 13179};
718e3744 13180
d62a17ae 13181struct peer_pcounts {
13182 unsigned int count[PCOUNT_MAX];
13183 const struct peer *peer;
13184 const struct bgp_table *table;
54317cba 13185 safi_t safi;
a636c635 13186};
47fc97cc 13187
9bcb3eef 13188static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13189{
54317cba
JW
13190 const struct bgp_adj_in *ain;
13191 const struct bgp_path_info *pi;
d62a17ae 13192 const struct peer *peer = pc->peer;
13193
54317cba
JW
13194 for (ain = rn->adj_in; ain; ain = ain->next)
13195 if (ain->peer == peer)
13196 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13197
9bcb3eef 13198 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13199
54317cba
JW
13200 if (pi->peer != peer)
13201 continue;
d62a17ae 13202
54317cba 13203 pc->count[PCOUNT_ALL]++;
d62a17ae 13204
54317cba
JW
13205 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13206 pc->count[PCOUNT_DAMPED]++;
13207 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13208 pc->count[PCOUNT_HISTORY]++;
13209 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13210 pc->count[PCOUNT_REMOVED]++;
13211 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13212 pc->count[PCOUNT_STALE]++;
13213 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13214 pc->count[PCOUNT_VALID]++;
13215 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13216 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13217 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13218 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13219
13220 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13221 pc->count[PCOUNT_COUNTED]++;
13222 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13223 flog_err(
13224 EC_LIB_DEVELOPMENT,
13225 "Attempting to count but flags say it is unusable");
13226 } else {
40381db7 13227 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13228 flog_err(
13229 EC_LIB_DEVELOPMENT,
13230 "Not counted but flags say we should");
d62a17ae 13231 }
13232 }
54317cba
JW
13233}
13234
cc9f21da 13235static void bgp_peer_count_walker(struct thread *t)
54317cba 13236{
9bcb3eef 13237 struct bgp_dest *rn, *rm;
54317cba
JW
13238 const struct bgp_table *table;
13239 struct peer_pcounts *pc = THREAD_ARG(t);
13240
13241 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13242 || pc->safi == SAFI_EVPN) {
13243 /* Special handling for 2-level routing tables. */
13244 for (rn = bgp_table_top(pc->table); rn;
13245 rn = bgp_route_next(rn)) {
9bcb3eef 13246 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13247 if (table != NULL)
13248 for (rm = bgp_table_top(table); rm;
13249 rm = bgp_route_next(rm))
13250 bgp_peer_count_proc(rm, pc);
13251 }
13252 } else
13253 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13254 bgp_peer_count_proc(rn, pc);
718e3744 13255}
13256
d62a17ae 13257static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13258 safi_t safi, bool use_json)
856ca177 13259{
d62a17ae 13260 struct peer_pcounts pcounts = {.peer = peer};
13261 unsigned int i;
13262 json_object *json = NULL;
13263 json_object *json_loop = NULL;
856ca177 13264
d62a17ae 13265 if (use_json) {
13266 json = json_object_new_object();
13267 json_loop = json_object_new_object();
13268 }
718e3744 13269
d62a17ae 13270 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13271 || !peer->bgp->rib[afi][safi]) {
13272 if (use_json) {
13273 json_object_string_add(
13274 json, "warning",
13275 "No such neighbor or address family");
13276 vty_out(vty, "%s\n", json_object_to_json_string(json));
13277 json_object_free(json);
d5f20468 13278 json_object_free(json_loop);
d62a17ae 13279 } else
13280 vty_out(vty, "%% No such neighbor or address family\n");
13281
13282 return CMD_WARNING;
13283 }
2a71e9ce 13284
d62a17ae 13285 memset(&pcounts, 0, sizeof(pcounts));
13286 pcounts.peer = peer;
13287 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13288 pcounts.safi = safi;
d62a17ae 13289
13290 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13291 * stats for the thread-walk (i.e. ensure this can't be blamed on
13292 * on just vty_read()).
13293 */
d62a17ae 13294 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13295
13296 if (use_json) {
13297 json_object_string_add(json, "prefixCountsFor", peer->host);
13298 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13299 get_afi_safi_str(afi, safi, true));
d62a17ae 13300 json_object_int_add(json, "pfxCounter",
13301 peer->pcount[afi][safi]);
13302
13303 for (i = 0; i < PCOUNT_MAX; i++)
13304 json_object_int_add(json_loop, pcount_strs[i],
13305 pcounts.count[i]);
13306
13307 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13308
13309 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13310 json_object_string_add(json, "pfxctDriftFor",
13311 peer->host);
13312 json_object_string_add(
13313 json, "recommended",
13314 "Please report this bug, with the above command output");
13315 }
75eeda93 13316 vty_json(vty, json);
d62a17ae 13317 } else {
13318
13319 if (peer->hostname
892fedb6 13320 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13321 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13322 peer->hostname, peer->host,
5cb5f4d0 13323 get_afi_safi_str(afi, safi, false));
d62a17ae 13324 } else {
13325 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13326 get_afi_safi_str(afi, safi, false));
d62a17ae 13327 }
13328
6cde4b45 13329 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13330 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13331
13332 for (i = 0; i < PCOUNT_MAX; i++)
13333 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13334 pcounts.count[i]);
13335
13336 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13337 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13338 vty_out(vty,
13339 "Please report this bug, with the above command output\n");
13340 }
13341 }
13342
13343 return CMD_SUCCESS;
718e3744 13344}
13345
a636c635
DW
13346DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13347 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13348 "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 13349 SHOW_STR
13350 IP_STR
13351 BGP_STR
8386ac43 13352 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13353 BGP_AFI_HELP_STR
13354 BGP_SAFI_HELP_STR
0b16f239
DS
13355 "Detailed information on TCP and BGP neighbor connections\n"
13356 "Neighbor to display information about\n"
13357 "Neighbor to display information about\n"
91d37724 13358 "Neighbor on BGP configured interface\n"
a636c635 13359 "Display detailed prefix count information\n"
9973d184 13360 JSON_STR)
0b16f239 13361{
d62a17ae 13362 afi_t afi = AFI_IP6;
13363 safi_t safi = SAFI_UNICAST;
13364 struct peer *peer;
13365 int idx = 0;
13366 struct bgp *bgp = NULL;
9f049418
DS
13367 bool uj = use_json(argc, argv);
13368
13369 if (uj)
13370 argc--;
856ca177 13371
d62a17ae 13372 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13373 &bgp, uj);
d62a17ae 13374 if (!idx)
13375 return CMD_WARNING;
0b16f239 13376
d62a17ae 13377 argv_find(argv, argc, "neighbors", &idx);
13378 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13379 if (!peer)
13380 return CMD_WARNING;
bb46e94f 13381
29c8d9da 13382 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13383}
0b16f239 13384
d6902373
PG
13385#ifdef KEEP_OLD_VPN_COMMANDS
13386DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13387 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13388 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13389 SHOW_STR
13390 IP_STR
13391 BGP_STR
d6902373 13392 BGP_VPNVX_HELP_STR
91d37724 13393 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13394 "Detailed information on TCP and BGP neighbor connections\n"
13395 "Neighbor to display information about\n"
13396 "Neighbor to display information about\n"
91d37724 13397 "Neighbor on BGP configured interface\n"
a636c635 13398 "Display detailed prefix count information\n"
9973d184 13399 JSON_STR)
a636c635 13400{
d62a17ae 13401 int idx_peer = 6;
13402 struct peer *peer;
9f049418 13403 bool uj = use_json(argc, argv);
a636c635 13404
d62a17ae 13405 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13406 if (!peer)
13407 return CMD_WARNING;
13408
13409 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13410}
13411
d6902373
PG
13412DEFUN (show_ip_bgp_vpn_all_route_prefix,
13413 show_ip_bgp_vpn_all_route_prefix_cmd,
13414 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13415 SHOW_STR
13416 IP_STR
13417 BGP_STR
d6902373 13418 BGP_VPNVX_HELP_STR
91d37724
QY
13419 "Display information about all VPNv4 NLRIs\n"
13420 "Network in the BGP routing table to display\n"
3a2d747c 13421 "Network in the BGP routing table to display\n"
9973d184 13422 JSON_STR)
91d37724 13423{
d62a17ae 13424 int idx = 0;
13425 char *network = NULL;
13426 struct bgp *bgp = bgp_get_default();
13427 if (!bgp) {
13428 vty_out(vty, "Can't find default instance\n");
13429 return CMD_WARNING;
13430 }
87e34b58 13431
d62a17ae 13432 if (argv_find(argv, argc, "A.B.C.D", &idx))
13433 network = argv[idx]->arg;
13434 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13435 network = argv[idx]->arg;
13436 else {
13437 vty_out(vty, "Unable to figure out Network\n");
13438 return CMD_WARNING;
13439 }
87e34b58 13440
d62a17ae 13441 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13442 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13443 use_json(argc, argv));
91d37724 13444}
d6902373 13445#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13446
44c69747
LK
13447DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13448 show_bgp_l2vpn_evpn_route_prefix_cmd,
13449 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13450 SHOW_STR
4c63a661
PG
13451 BGP_STR
13452 L2VPN_HELP_STR
13453 EVPN_HELP_STR
44c69747
LK
13454 "Network in the BGP routing table to display\n"
13455 "Network in the BGP routing table to display\n"
4c63a661
PG
13456 "Network in the BGP routing table to display\n"
13457 "Network in the BGP routing table to display\n"
13458 JSON_STR)
13459{
d62a17ae 13460 int idx = 0;
13461 char *network = NULL;
44c69747 13462 int prefix_check = 0;
a636c635 13463
44c69747
LK
13464 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13465 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13466 network = argv[idx]->arg;
44c69747 13467 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13468 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13469 network = argv[idx]->arg;
44c69747
LK
13470 prefix_check = 1;
13471 } else {
d62a17ae 13472 vty_out(vty, "Unable to figure out Network\n");
13473 return CMD_WARNING;
13474 }
44c69747
LK
13475 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13476 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13477 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13478}
13479
114fc229 13480static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13481 struct bgp_table *table, int *header1,
13482 int *header2, json_object *json,
13483 json_object *json_scode,
13484 json_object *json_ocode, bool wide)
13485{
13486 uint64_t version = table ? table->version : 0;
13487
13488 if (*header1) {
13489 if (json) {
13490 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13491 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13492 "%pI4", &peer->bgp->router_id);
2f9bc755 13493 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13494 peer->bgp->default_local_pref);
13495 json_object_int_add(json, "localAS",
13496 peer->change_local_as
13497 ? peer->change_local_as
13498 : peer->local_as);
2f9bc755
DS
13499 json_object_object_add(json, "bgpStatusCodes",
13500 json_scode);
13501 json_object_object_add(json, "bgpOriginCodes",
13502 json_ocode);
13503 } else {
13504 vty_out(vty,
23d0a753
DA
13505 "BGP table version is %" PRIu64
13506 ", local router ID is %pI4, vrf id ",
114fc229
DA
13507 version, &peer->bgp->router_id);
13508 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13509 vty_out(vty, "%s", VRFID_NONE_STR);
13510 else
114fc229 13511 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13512 vty_out(vty, "\n");
13513 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13514 peer->bgp->default_local_pref);
13515 vty_out(vty, "local AS %u\n",
13516 peer->change_local_as ? peer->change_local_as
13517 : peer->local_as);
2f9bc755
DS
13518 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13519 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13520 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13521 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13522 }
13523 *header1 = 0;
13524 }
13525 if (*header2) {
13526 if (!json)
13527 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13528 : BGP_SHOW_HEADER));
13529 *header2 = 0;
13530 }
13531}
13532
d9478df0
TA
13533static void
13534show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13535 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13536 const char *rmap_name, json_object *json, json_object *json_ar,
13537 json_object *json_scode, json_object *json_ocode,
96c81f66 13538 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13539 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13540{
d62a17ae 13541 struct bgp_adj_in *ain;
13542 struct bgp_adj_out *adj;
9bcb3eef 13543 struct bgp_dest *dest;
d62a17ae 13544 struct bgp *bgp;
d62a17ae 13545 struct attr attr;
13546 int ret;
13547 struct update_subgroup *subgrp;
d62a17ae 13548 struct peer_af *paf;
f99def61 13549 bool route_filtered;
96f3485c
MK
13550 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13551 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13552 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13553 || (safi == SAFI_EVPN))
13554 ? true
13555 : false;
a636c635 13556
d62a17ae 13557 bgp = peer->bgp;
a636c635 13558
d62a17ae 13559 subgrp = peer_subgroup(peer, afi, safi);
13560
6392aaa6 13561 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13562 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13563 if (use_json) {
13564 json_object_int_add(json, "bgpTableVersion",
13565 table->version);
c949c771
DA
13566 json_object_string_addf(json, "bgpLocalRouterId",
13567 "%pI4", &bgp->router_id);
01eced22
AD
13568 json_object_int_add(json, "defaultLocPrf",
13569 bgp->default_local_pref);
114fc229
DA
13570 json_object_int_add(json, "localAS",
13571 peer->change_local_as
13572 ? peer->change_local_as
13573 : peer->local_as);
d62a17ae 13574 json_object_object_add(json, "bgpStatusCodes",
13575 json_scode);
13576 json_object_object_add(json, "bgpOriginCodes",
13577 json_ocode);
07d0c4ed
DA
13578 json_object_string_add(
13579 json, "bgpOriginatingDefaultNetwork",
13580 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13581 } else {
23d0a753
DA
13582 vty_out(vty,
13583 "BGP table version is %" PRIu64
13584 ", local router ID is %pI4, vrf id ",
13585 table->version, &bgp->router_id);
9df8b37c
PZ
13586 if (bgp->vrf_id == VRF_UNKNOWN)
13587 vty_out(vty, "%s", VRFID_NONE_STR);
13588 else
13589 vty_out(vty, "%u", bgp->vrf_id);
13590 vty_out(vty, "\n");
01eced22
AD
13591 vty_out(vty, "Default local pref %u, ",
13592 bgp->default_local_pref);
114fc229
DA
13593 vty_out(vty, "local AS %u\n",
13594 peer->change_local_as ? peer->change_local_as
13595 : peer->local_as);
d62a17ae 13596 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13597 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13598 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13599 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13600
07d0c4ed
DA
13601 vty_out(vty, "Originating default network %s\n\n",
13602 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13603 }
d9478df0 13604 *header1 = 0;
d62a17ae 13605 }
a636c635 13606
9bcb3eef 13607 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13608 if (type == bgp_show_adj_route_received
13609 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13610 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13611 if (ain->peer != peer)
ea47320b 13612 continue;
6392aaa6 13613
114fc229 13614 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13615 header2, json, json_scode,
13616 json_ocode, wide);
13617
13618 if ((safi == SAFI_MPLS_VPN)
13619 || (safi == SAFI_ENCAP)
13620 || (safi == SAFI_EVPN)) {
13621 if (use_json)
13622 json_object_string_add(
13623 json_ar, "rd", rd_str);
13624 else if (show_rd && rd_str) {
13625 vty_out(vty,
13626 "Route Distinguisher: %s\n",
13627 rd_str);
13628 show_rd = false;
13629 }
13630 }
6392aaa6 13631
6f4f49b2 13632 attr = *ain->attr;
f99def61
AD
13633 route_filtered = false;
13634
13635 /* Filter prefix using distribute list,
13636 * filter list or prefix list
13637 */
b54892e0 13638 const struct prefix *rn_p =
9bcb3eef 13639 bgp_dest_get_prefix(dest);
b54892e0
DS
13640 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13641 safi))
13642 == FILTER_DENY)
f99def61
AD
13643 route_filtered = true;
13644
13645 /* Filter prefix using route-map */
b54892e0
DS
13646 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13647 safi, rmap_name, NULL,
13648 0, NULL);
6392aaa6 13649
13c8e163
AD
13650 if (type == bgp_show_adj_route_filtered &&
13651 !route_filtered && ret != RMAP_DENY) {
d498917e 13652 bgp_attr_flush(&attr);
6392aaa6 13653 continue;
d62a17ae 13654 }
6392aaa6 13655
d9478df0
TA
13656 if (type == bgp_show_adj_route_received
13657 && (route_filtered || ret == RMAP_DENY))
13658 (*filtered_count)++;
6392aaa6 13659
7d3cae70 13660 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13661 use_json, json_ar, wide);
d498917e 13662 bgp_attr_flush(&attr);
d9478df0 13663 (*output_count)++;
d62a17ae 13664 }
6392aaa6 13665 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13666 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13667 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13668 if (paf->peer != peer || !adj->attr)
924c3f6a 13669 continue;
d62a17ae 13670
114fc229 13671 show_adj_route_header(vty, peer, table,
d9478df0
TA
13672 header1, header2,
13673 json, json_scode,
13674 json_ocode, wide);
d62a17ae 13675
b54892e0 13676 const struct prefix *rn_p =
9bcb3eef 13677 bgp_dest_get_prefix(dest);
b54892e0 13678
6f4f49b2 13679 attr = *adj->attr;
b755861b 13680 ret = bgp_output_modifier(
b54892e0 13681 peer, rn_p, &attr, afi, safi,
b755861b 13682 rmap_name);
f46d8e1e 13683
b755861b 13684 if (ret != RMAP_DENY) {
d9478df0
TA
13685 if ((safi == SAFI_MPLS_VPN)
13686 || (safi == SAFI_ENCAP)
13687 || (safi == SAFI_EVPN)) {
13688 if (use_json)
13689 json_object_string_add(
13690 json_ar,
13691 "rd",
13692 rd_str);
13693 else if (show_rd
13694 && rd_str) {
13695 vty_out(vty,
13696 "Route Distinguisher: %s\n",
13697 rd_str);
13698 show_rd = false;
13699 }
13700 }
b54892e0 13701 route_vty_out_tmp(
7d3cae70
DA
13702 vty, dest, rn_p, &attr,
13703 safi, use_json, json_ar,
ae248832 13704 wide);
d9478df0 13705 (*output_count)++;
b755861b 13706 } else {
d9478df0 13707 (*filtered_count)++;
a2addae8 13708 }
b755861b 13709
d498917e 13710 bgp_attr_flush(&attr);
924c3f6a 13711 }
f20ce998
DS
13712 } else if (type == bgp_show_adj_route_bestpath) {
13713 struct bgp_path_info *pi;
13714
114fc229
DA
13715 show_adj_route_header(vty, peer, table, header1,
13716 header2, json, json_scode,
13717 json_ocode, wide);
f20ce998
DS
13718
13719 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13720 pi = pi->next) {
13721 if (pi->peer != peer)
13722 continue;
13723
13724 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13725 continue;
13726
7d3cae70 13727 route_vty_out_tmp(vty, dest,
f20ce998
DS
13728 bgp_dest_get_prefix(dest),
13729 pi->attr, safi, use_json,
13730 json_ar, wide);
d9478df0 13731 (*output_count)++;
f20ce998 13732 }
d62a17ae 13733 }
13734 }
a636c635 13735}
2a71e9ce 13736
d62a17ae 13737static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13738 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13739 const char *rmap_name, uint16_t show_flags)
0b16f239 13740{
d9478df0
TA
13741 struct bgp *bgp;
13742 struct bgp_table *table;
d62a17ae 13743 json_object *json = NULL;
d9478df0
TA
13744 json_object *json_scode = NULL;
13745 json_object *json_ocode = NULL;
13746 json_object *json_ar = NULL;
96f3485c 13747 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13748
d9478df0
TA
13749 /* Init BGP headers here so they're only displayed once
13750 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13751 */
13752 int header1 = 1;
13753 int header2 = 1;
13754
13755 /*
13756 * Initialize variables for each RD
13757 * All prefixes under an RD is aggregated within "json_routes"
13758 */
13759 char rd_str[BUFSIZ] = {0};
13760 json_object *json_routes = NULL;
13761
13762
13763 /* For 2-tier tables, prefix counts need to be
13764 * maintained across multiple runs of show_adj_route()
13765 */
13766 unsigned long output_count_per_rd;
13767 unsigned long filtered_count_per_rd;
13768 unsigned long output_count = 0;
13769 unsigned long filtered_count = 0;
13770
13771 if (use_json) {
d62a17ae 13772 json = json_object_new_object();
d9478df0
TA
13773 json_ar = json_object_new_object();
13774 json_scode = json_object_new_object();
13775 json_ocode = json_object_new_object();
13776
13777 json_object_string_add(json_scode, "suppressed", "s");
13778 json_object_string_add(json_scode, "damped", "d");
13779 json_object_string_add(json_scode, "history", "h");
13780 json_object_string_add(json_scode, "valid", "*");
13781 json_object_string_add(json_scode, "best", ">");
13782 json_object_string_add(json_scode, "multipath", "=");
13783 json_object_string_add(json_scode, "internal", "i");
13784 json_object_string_add(json_scode, "ribFailure", "r");
13785 json_object_string_add(json_scode, "stale", "S");
13786 json_object_string_add(json_scode, "removed", "R");
13787
13788 json_object_string_add(json_ocode, "igp", "i");
13789 json_object_string_add(json_ocode, "egp", "e");
13790 json_object_string_add(json_ocode, "incomplete", "?");
13791 }
0b16f239 13792
d62a17ae 13793 if (!peer || !peer->afc[afi][safi]) {
13794 if (use_json) {
13795 json_object_string_add(
13796 json, "warning",
13797 "No such neighbor or address family");
13798 vty_out(vty, "%s\n", json_object_to_json_string(json));
13799 json_object_free(json);
690c3134
MW
13800 json_object_free(json_ar);
13801 json_object_free(json_scode);
13802 json_object_free(json_ocode);
d62a17ae 13803 } else
13804 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13805
d62a17ae 13806 return CMD_WARNING;
13807 }
13808
6392aaa6
PM
13809 if ((type == bgp_show_adj_route_received
13810 || type == bgp_show_adj_route_filtered)
d62a17ae 13811 && !CHECK_FLAG(peer->af_flags[afi][safi],
13812 PEER_FLAG_SOFT_RECONFIG)) {
13813 if (use_json) {
13814 json_object_string_add(
13815 json, "warning",
13816 "Inbound soft reconfiguration not enabled");
13817 vty_out(vty, "%s\n", json_object_to_json_string(json));
13818 json_object_free(json);
690c3134
MW
13819 json_object_free(json_ar);
13820 json_object_free(json_scode);
13821 json_object_free(json_ocode);
d62a17ae 13822 } else
13823 vty_out(vty,
13824 "%% Inbound soft reconfiguration not enabled\n");
13825
13826 return CMD_WARNING;
13827 }
0b16f239 13828
d9478df0
TA
13829 bgp = peer->bgp;
13830
13831 /* labeled-unicast routes live in the unicast table */
13832 if (safi == SAFI_LABELED_UNICAST)
13833 table = bgp->rib[afi][SAFI_UNICAST];
13834 else
13835 table = bgp->rib[afi][safi];
13836
13837 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13838 || (safi == SAFI_EVPN)) {
13839
13840 struct bgp_dest *dest;
13841
13842 for (dest = bgp_table_top(table); dest;
13843 dest = bgp_route_next(dest)) {
13844 table = bgp_dest_get_bgp_table_info(dest);
13845 if (!table)
13846 continue;
13847
13848 output_count_per_rd = 0;
13849 filtered_count_per_rd = 0;
13850
13851 if (use_json)
13852 json_routes = json_object_new_object();
13853
13854 const struct prefix_rd *prd;
13855 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13856 dest);
13857
13858 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13859
13860 show_adj_route(vty, peer, table, afi, safi, type,
13861 rmap_name, json, json_routes, json_scode,
13862 json_ocode, show_flags, &header1,
13863 &header2, rd_str, &output_count_per_rd,
13864 &filtered_count_per_rd);
13865
13866 /* Don't include an empty RD in the output! */
13867 if (json_routes && (output_count_per_rd > 0))
13868 json_object_object_add(json_ar, rd_str,
13869 json_routes);
13870
13871 output_count += output_count_per_rd;
13872 filtered_count += filtered_count_per_rd;
13873 }
13874 } else
13875 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13876 json, json_ar, json_scode, json_ocode,
13877 show_flags, &header1, &header2, rd_str,
13878 &output_count, &filtered_count);
13879
13880 if (use_json) {
c1984955
TA
13881 if (type == bgp_show_adj_route_advertised)
13882 json_object_object_add(json, "advertisedRoutes",
13883 json_ar);
13884 else
13885 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
13886 json_object_int_add(json, "totalPrefixCounter", output_count);
13887 json_object_int_add(json, "filteredPrefixCounter",
13888 filtered_count);
13889
690c3134
MW
13890 /*
13891 * These fields only give up ownership to `json` when `header1`
13892 * is used (set to zero). See code in `show_adj_route` and
13893 * `show_adj_route_header`.
13894 */
13895 if (header1 == 1) {
d9478df0
TA
13896 json_object_free(json_scode);
13897 json_object_free(json_ocode);
13898 }
13899
75eeda93 13900 vty_json(vty, json);
d9478df0
TA
13901 } else if (output_count > 0) {
13902 if (filtered_count > 0)
13903 vty_out(vty,
13904 "\nTotal number of prefixes %ld (%ld filtered)\n",
13905 output_count, filtered_count);
13906 else
13907 vty_out(vty, "\nTotal number of prefixes %ld\n",
13908 output_count);
13909 }
0b16f239 13910
d62a17ae 13911 return CMD_SUCCESS;
a636c635 13912}
50ef26d4 13913
f20ce998
DS
13914DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13915 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13916 "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]",
13917 SHOW_STR
13918 IP_STR
13919 BGP_STR
13920 BGP_INSTANCE_HELP_STR
13921 BGP_AFI_HELP_STR
13922 BGP_SAFI_WITH_LABEL_HELP_STR
13923 "Detailed information on TCP and BGP neighbor connections\n"
13924 "Neighbor to display information about\n"
13925 "Neighbor to display information about\n"
13926 "Neighbor on BGP configured interface\n"
13927 "Display the routes selected by best path\n"
13928 JSON_STR
13929 "Increase table width for longer prefixes\n")
13930{
13931 afi_t afi = AFI_IP6;
13932 safi_t safi = SAFI_UNICAST;
13933 char *rmap_name = NULL;
13934 char *peerstr = NULL;
13935 struct bgp *bgp = NULL;
13936 struct peer *peer;
13937 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13938 int idx = 0;
96c81f66 13939 uint16_t show_flags = 0;
96f3485c
MK
13940
13941 if (uj)
13942 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13943
13944 if (wide)
13945 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13946
13947 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13948 &bgp, uj);
13949
13950 if (!idx)
13951 return CMD_WARNING;
13952
13953 argv_find(argv, argc, "neighbors", &idx);
13954 peerstr = argv[++idx]->arg;
13955
13956 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13957 if (!peer)
13958 return CMD_WARNING;
13959
96f3485c
MK
13960 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13961 show_flags);
f20ce998
DS
13962}
13963
ae248832 13964DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13965 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 13966 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [json$uj | wide$wide]",
718e3744 13967 SHOW_STR
13968 IP_STR
13969 BGP_STR
a636c635 13970 BGP_INSTANCE_HELP_STR
7395a2c9 13971 BGP_AFI_HELP_STR
4dd6177e 13972 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13973 "Display the entries for all address families\n"
718e3744 13974 "Detailed information on TCP and BGP neighbor connections\n"
13975 "Neighbor to display information about\n"
13976 "Neighbor to display information about\n"
91d37724 13977 "Neighbor on BGP configured interface\n"
a636c635 13978 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13979 "Display the received routes from neighbor\n"
13980 "Display the filtered routes received from neighbor\n"
a636c635
DW
13981 "Route-map to modify the attributes\n"
13982 "Name of the route map\n"
ae248832
MK
13983 JSON_STR
13984 "Increase table width for longer prefixes\n")
718e3744 13985{
d62a17ae 13986 afi_t afi = AFI_IP6;
13987 safi_t safi = SAFI_UNICAST;
d62a17ae 13988 char *peerstr = NULL;
d62a17ae 13989 struct bgp *bgp = NULL;
13990 struct peer *peer;
6392aaa6 13991 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13992 int idx = 0;
96f3485c 13993 bool first = true;
96c81f66 13994 uint16_t show_flags = 0;
75ce3b14
DA
13995 struct listnode *node;
13996 struct bgp *abgp;
6392aaa6 13997
96f3485c 13998 if (uj) {
d62a17ae 13999 argc--;
96f3485c
MK
14000 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14001 }
14002
14003 if (all) {
14004 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14005 if (argv_find(argv, argc, "ipv4", &idx))
14006 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14007
14008 if (argv_find(argv, argc, "ipv6", &idx))
14009 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14010 }
14011
14012 if (wide)
14013 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14014
9f049418
DS
14015 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14016 &bgp, uj);
14017 if (!idx)
14018 return CMD_WARNING;
14019
d62a17ae 14020 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14021 argv_find(argv, argc, "neighbors", &idx);
14022 peerstr = argv[++idx]->arg;
8c3deaae 14023
d62a17ae 14024 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14025 if (!peer)
14026 return CMD_WARNING;
856ca177 14027
d62a17ae 14028 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14029 type = bgp_show_adj_route_advertised;
14030 else if (argv_find(argv, argc, "received-routes", &idx))
14031 type = bgp_show_adj_route_received;
14032 else if (argv_find(argv, argc, "filtered-routes", &idx))
14033 type = bgp_show_adj_route_filtered;
14034
96f3485c 14035 if (!all)
70dd370f 14036 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14037 show_flags);
14038 if (uj)
14039 vty_out(vty, "{\n");
14040
14041 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14042 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14043 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14044 : AFI_IP6;
75ce3b14
DA
14045 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14046 FOREACH_SAFI (safi) {
14047 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14048 continue;
96f3485c 14049
75ce3b14
DA
14050 if (uj) {
14051 if (first)
14052 first = false;
14053 else
14054 vty_out(vty, ",\n");
14055 vty_out(vty, "\"%s\":",
14056 get_afi_safi_str(afi, safi,
14057 true));
14058 } else
14059 vty_out(vty,
14060 "\nFor address family: %s\n",
14061 get_afi_safi_str(afi, safi,
14062 false));
96f3485c 14063
75ce3b14 14064 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14065 route_map, show_flags);
75ce3b14 14066 }
96f3485c
MK
14067 }
14068 } else {
75ce3b14
DA
14069 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14070 FOREACH_AFI_SAFI (afi, safi) {
14071 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14072 continue;
96f3485c 14073
75ce3b14
DA
14074 if (uj) {
14075 if (first)
14076 first = false;
14077 else
14078 vty_out(vty, ",\n");
14079 vty_out(vty, "\"%s\":",
14080 get_afi_safi_str(afi, safi,
14081 true));
14082 } else
14083 vty_out(vty,
14084 "\nFor address family: %s\n",
14085 get_afi_safi_str(afi, safi,
14086 false));
96f3485c 14087
75ce3b14 14088 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14089 route_map, show_flags);
75ce3b14 14090 }
96f3485c
MK
14091 }
14092 }
14093 if (uj)
14094 vty_out(vty, "}\n");
14095
14096 return CMD_SUCCESS;
95cbbd2a
ML
14097}
14098
718e3744 14099DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14100 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14101 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14102 SHOW_STR
14103 IP_STR
14104 BGP_STR
d3120452 14105 BGP_INSTANCE_HELP_STR
8c3deaae
QY
14106 "Address Family\n"
14107 "Address Family\n"
718e3744 14108 "Address Family modifier\n"
14109 "Detailed information on TCP and BGP neighbor connections\n"
14110 "Neighbor to display information about\n"
14111 "Neighbor to display information about\n"
91d37724 14112 "Neighbor on BGP configured interface\n"
718e3744 14113 "Display information received from a BGP neighbor\n"
856ca177 14114 "Display the prefixlist filter\n"
9973d184 14115 JSON_STR)
718e3744 14116{
d62a17ae 14117 afi_t afi = AFI_IP6;
14118 safi_t safi = SAFI_UNICAST;
14119 char *peerstr = NULL;
d62a17ae 14120 char name[BUFSIZ];
d62a17ae 14121 struct peer *peer;
d3120452 14122 int count;
d62a17ae 14123 int idx = 0;
d3120452
IR
14124 struct bgp *bgp = NULL;
14125 bool uj = use_json(argc, argv);
14126
14127 if (uj)
14128 argc--;
14129
14130 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14131 &bgp, uj);
14132 if (!idx)
14133 return CMD_WARNING;
d62a17ae 14134
d62a17ae 14135 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14136 argv_find(argv, argc, "neighbors", &idx);
14137 peerstr = argv[++idx]->arg;
14138
d3120452
IR
14139 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14140 if (!peer)
14141 return CMD_WARNING;
718e3744 14142
4ced1a2c 14143 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14144 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14145 if (count) {
14146 if (!uj)
14147 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14148 get_afi_safi_str(afi, safi, false));
d62a17ae 14149 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14150 } else {
14151 if (uj)
14152 vty_out(vty, "{}\n");
14153 else
14154 vty_out(vty, "No functional output\n");
14155 }
718e3744 14156
d62a17ae 14157 return CMD_SUCCESS;
14158}
14159
14160static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14161 afi_t afi, safi_t safi,
9f049418 14162 enum bgp_show_type type, bool use_json)
d62a17ae 14163{
96c81f66 14164 uint16_t show_flags = 0;
96f3485c
MK
14165
14166 if (use_json)
14167 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14168
d62a17ae 14169 if (!peer || !peer->afc[afi][safi]) {
14170 if (use_json) {
14171 json_object *json_no = NULL;
14172 json_no = json_object_new_object();
14173 json_object_string_add(
14174 json_no, "warning",
14175 "No such neighbor or address family");
14176 vty_out(vty, "%s\n",
14177 json_object_to_json_string(json_no));
14178 json_object_free(json_no);
14179 } else
14180 vty_out(vty, "%% No such neighbor or address family\n");
14181 return CMD_WARNING;
14182 }
47fc97cc 14183
7daf25a3
TA
14184 /* labeled-unicast routes live in the unicast table */
14185 if (safi == SAFI_LABELED_UNICAST)
14186 safi = SAFI_UNICAST;
14187
1e2ce4f1
DS
14188 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14189 RPKI_NOT_BEING_USED);
718e3744 14190}
14191
dba3c1d3
PG
14192DEFUN (show_ip_bgp_flowspec_routes_detailed,
14193 show_ip_bgp_flowspec_routes_detailed_cmd,
14194 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14195 SHOW_STR
14196 IP_STR
14197 BGP_STR
14198 BGP_INSTANCE_HELP_STR
14199 BGP_AFI_HELP_STR
14200 "SAFI Flowspec\n"
14201 "Detailed information on flowspec entries\n"
14202 JSON_STR)
14203{
458c1475 14204 afi_t afi = AFI_IP6;
dba3c1d3
PG
14205 safi_t safi = SAFI_UNICAST;
14206 struct bgp *bgp = NULL;
14207 int idx = 0;
9f049418 14208 bool uj = use_json(argc, argv);
5be6fa9b 14209 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14210
96f3485c 14211 if (uj) {
9f049418 14212 argc--;
96f3485c
MK
14213 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14214 }
dba3c1d3
PG
14215
14216 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14217 &bgp, uj);
dba3c1d3
PG
14218 if (!idx)
14219 return CMD_WARNING;
14220
96f3485c 14221 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14222 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14223}
14224
718e3744 14225DEFUN (show_ip_bgp_neighbor_routes,
14226 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14227 "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 14228 SHOW_STR
14229 IP_STR
14230 BGP_STR
8386ac43 14231 BGP_INSTANCE_HELP_STR
4f280b15 14232 BGP_AFI_HELP_STR
4dd6177e 14233 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14234 "Detailed information on TCP and BGP neighbor connections\n"
14235 "Neighbor to display information about\n"
14236 "Neighbor to display information about\n"
91d37724 14237 "Neighbor on BGP configured interface\n"
2525cf39 14238 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14239 "Display the dampened routes received from neighbor\n"
14240 "Display routes learned from neighbor\n"
9973d184 14241 JSON_STR)
718e3744 14242{
d62a17ae 14243 char *peerstr = NULL;
14244 struct bgp *bgp = NULL;
14245 afi_t afi = AFI_IP6;
14246 safi_t safi = SAFI_UNICAST;
14247 struct peer *peer;
14248 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14249 int idx = 0;
9f049418
DS
14250 bool uj = use_json(argc, argv);
14251
14252 if (uj)
14253 argc--;
bb46e94f 14254
d62a17ae 14255 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14256 &bgp, uj);
d62a17ae 14257 if (!idx)
14258 return CMD_WARNING;
c493f2d8 14259
d62a17ae 14260 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14261 argv_find(argv, argc, "neighbors", &idx);
14262 peerstr = argv[++idx]->arg;
8c3deaae 14263
d62a17ae 14264 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14265 if (!peer)
d62a17ae 14266 return CMD_WARNING;
bb46e94f 14267
d62a17ae 14268 if (argv_find(argv, argc, "flap-statistics", &idx))
14269 sh_type = bgp_show_type_flap_neighbor;
14270 else if (argv_find(argv, argc, "dampened-routes", &idx))
14271 sh_type = bgp_show_type_damp_neighbor;
14272 else if (argv_find(argv, argc, "routes", &idx))
14273 sh_type = bgp_show_type_neighbor;
2525cf39 14274
d62a17ae 14275 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14276}
6b0655a2 14277
734b349e 14278struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14279
d62a17ae 14280struct bgp_distance {
14281 /* Distance value for the IP source prefix. */
d7c0a89a 14282 uint8_t distance;
718e3744 14283
d62a17ae 14284 /* Name of the access-list to be matched. */
14285 char *access_list;
718e3744 14286};
14287
4f280b15
LB
14288DEFUN (show_bgp_afi_vpn_rd_route,
14289 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14290 "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
14291 SHOW_STR
14292 BGP_STR
14293 BGP_AFI_HELP_STR
14294 "Address Family modifier\n"
14295 "Display information for a route distinguisher\n"
14296 "Route Distinguisher\n"
a111dd97 14297 "All Route Distinguishers\n"
7395a2c9
DS
14298 "Network in the BGP routing table to display\n"
14299 "Network in the BGP routing table to display\n"
14300 JSON_STR)
4f280b15 14301{
d62a17ae 14302 int ret;
14303 struct prefix_rd prd;
14304 afi_t afi = AFI_MAX;
14305 int idx = 0;
4f280b15 14306
ff6566f3
DS
14307 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14308 vty_out(vty, "%% Malformed Address Family\n");
14309 return CMD_WARNING;
14310 }
14311
a111dd97
TA
14312 if (!strcmp(argv[5]->arg, "all"))
14313 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14314 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14315 RPKI_NOT_BEING_USED,
14316 use_json(argc, argv));
14317
d62a17ae 14318 ret = str2prefix_rd(argv[5]->arg, &prd);
14319 if (!ret) {
14320 vty_out(vty, "%% Malformed Route Distinguisher\n");
14321 return CMD_WARNING;
14322 }
ff6566f3 14323
d62a17ae 14324 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14325 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14326 use_json(argc, argv));
4f280b15
LB
14327}
14328
d62a17ae 14329static struct bgp_distance *bgp_distance_new(void)
718e3744 14330{
d62a17ae 14331 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14332}
14333
d62a17ae 14334static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14335{
d62a17ae 14336 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14337}
14338
585f1adc
IR
14339static int bgp_distance_set(struct vty *vty, const char *distance_str,
14340 const char *ip_str, const char *access_list_str)
718e3744 14341{
d62a17ae 14342 int ret;
585f1adc
IR
14343 afi_t afi;
14344 safi_t safi;
d62a17ae 14345 struct prefix p;
585f1adc 14346 uint8_t distance;
9bcb3eef 14347 struct bgp_dest *dest;
d62a17ae 14348 struct bgp_distance *bdistance;
718e3744 14349
585f1adc
IR
14350 afi = bgp_node_afi(vty);
14351 safi = bgp_node_safi(vty);
14352
d62a17ae 14353 ret = str2prefix(ip_str, &p);
14354 if (ret == 0) {
585f1adc 14355 vty_out(vty, "Malformed prefix\n");
d62a17ae 14356 return CMD_WARNING_CONFIG_FAILED;
14357 }
718e3744 14358
585f1adc
IR
14359 distance = atoi(distance_str);
14360
d62a17ae 14361 /* Get BGP distance node. */
9bcb3eef
DS
14362 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14363 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14364 if (bdistance)
9bcb3eef 14365 bgp_dest_unlock_node(dest);
ca2e160d 14366 else {
d62a17ae 14367 bdistance = bgp_distance_new();
9bcb3eef 14368 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14369 }
718e3744 14370
d62a17ae 14371 /* Set distance value. */
14372 bdistance->distance = distance;
718e3744 14373
d62a17ae 14374 /* Reset access-list configuration. */
e1b36e13 14375 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14376 if (access_list_str)
14377 bdistance->access_list =
14378 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14379
d62a17ae 14380 return CMD_SUCCESS;
718e3744 14381}
14382
585f1adc
IR
14383static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14384 const char *ip_str, const char *access_list_str)
718e3744 14385{
d62a17ae 14386 int ret;
585f1adc
IR
14387 afi_t afi;
14388 safi_t safi;
d62a17ae 14389 struct prefix p;
585f1adc 14390 int distance;
9bcb3eef 14391 struct bgp_dest *dest;
d62a17ae 14392 struct bgp_distance *bdistance;
718e3744 14393
585f1adc
IR
14394 afi = bgp_node_afi(vty);
14395 safi = bgp_node_safi(vty);
14396
d62a17ae 14397 ret = str2prefix(ip_str, &p);
14398 if (ret == 0) {
585f1adc 14399 vty_out(vty, "Malformed prefix\n");
d62a17ae 14400 return CMD_WARNING_CONFIG_FAILED;
14401 }
718e3744 14402
9bcb3eef
DS
14403 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14404 if (!dest) {
585f1adc 14405 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14406 return CMD_WARNING_CONFIG_FAILED;
14407 }
718e3744 14408
9bcb3eef 14409 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14410 distance = atoi(distance_str);
1f9a9fff 14411
d62a17ae 14412 if (bdistance->distance != distance) {
585f1adc 14413 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14414 bgp_dest_unlock_node(dest);
d62a17ae 14415 return CMD_WARNING_CONFIG_FAILED;
14416 }
718e3744 14417
0a22ddfb 14418 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14419 bgp_distance_free(bdistance);
718e3744 14420
9bcb3eef
DS
14421 bgp_dest_set_bgp_path_info(dest, NULL);
14422 bgp_dest_unlock_node(dest);
14423 bgp_dest_unlock_node(dest);
718e3744 14424
d62a17ae 14425 return CMD_SUCCESS;
718e3744 14426}
14427
718e3744 14428/* Apply BGP information to distance method. */
b8685f9b 14429uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14430 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14431{
9bcb3eef 14432 struct bgp_dest *dest;
801bb996 14433 struct prefix q = {0};
d62a17ae 14434 struct peer *peer;
14435 struct bgp_distance *bdistance;
14436 struct access_list *alist;
14437 struct bgp_static *bgp_static;
14438
14439 if (!bgp)
14440 return 0;
14441
40381db7 14442 peer = pinfo->peer;
d62a17ae 14443
7b7d48e5
DS
14444 if (pinfo->attr->distance)
14445 return pinfo->attr->distance;
14446
801bb996
CS
14447 /* Check source address.
14448 * Note: for aggregate route, peer can have unspec af type.
14449 */
14450 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14451 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14452 return 0;
14453
9bcb3eef
DS
14454 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14455 if (dest) {
14456 bdistance = bgp_dest_get_bgp_distance_info(dest);
14457 bgp_dest_unlock_node(dest);
d62a17ae 14458
14459 if (bdistance->access_list) {
14460 alist = access_list_lookup(afi, bdistance->access_list);
14461 if (alist
14462 && access_list_apply(alist, p) == FILTER_PERMIT)
14463 return bdistance->distance;
14464 } else
14465 return bdistance->distance;
718e3744 14466 }
718e3744 14467
d62a17ae 14468 /* Backdoor check. */
9bcb3eef
DS
14469 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14470 if (dest) {
14471 bgp_static = bgp_dest_get_bgp_static_info(dest);
14472 bgp_dest_unlock_node(dest);
718e3744 14473
d62a17ae 14474 if (bgp_static->backdoor) {
14475 if (bgp->distance_local[afi][safi])
14476 return bgp->distance_local[afi][safi];
14477 else
14478 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14479 }
718e3744 14480 }
718e3744 14481
d62a17ae 14482 if (peer->sort == BGP_PEER_EBGP) {
14483 if (bgp->distance_ebgp[afi][safi])
14484 return bgp->distance_ebgp[afi][safi];
14485 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14486 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14487 if (bgp->distance_ibgp[afi][safi])
14488 return bgp->distance_ibgp[afi][safi];
14489 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14490 } else {
14491 if (bgp->distance_local[afi][safi])
14492 return bgp->distance_local[afi][safi];
14493 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14494 }
718e3744 14495}
14496
a612fb77
DA
14497/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14498 * we should tell ZEBRA update the routes for a specific
14499 * AFI/SAFI to reflect changes in RIB.
14500 */
585f1adc
IR
14501static void bgp_announce_routes_distance_update(struct bgp *bgp,
14502 afi_t update_afi,
14503 safi_t update_safi)
a612fb77
DA
14504{
14505 afi_t afi;
14506 safi_t safi;
14507
14508 FOREACH_AFI_SAFI (afi, safi) {
14509 if (!bgp_fibupd_safi(safi))
14510 continue;
14511
8b54bc30
DA
14512 if (afi != update_afi && safi != update_safi)
14513 continue;
14514
14515 if (BGP_DEBUG(zebra, ZEBRA))
14516 zlog_debug(
14517 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14518 __func__, afi, safi);
14519 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14520 }
14521}
14522
585f1adc
IR
14523DEFUN (bgp_distance,
14524 bgp_distance_cmd,
14525 "distance bgp (1-255) (1-255) (1-255)",
14526 "Define an administrative distance\n"
14527 "BGP distance\n"
14528 "Distance for routes external to the AS\n"
14529 "Distance for routes internal to the AS\n"
14530 "Distance for local routes\n")
718e3744 14531{
585f1adc 14532 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14533 int idx_number = 2;
14534 int idx_number_2 = 3;
14535 int idx_number_3 = 4;
585f1adc
IR
14536 int distance_ebgp = atoi(argv[idx_number]->arg);
14537 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14538 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14539 afi_t afi;
14540 safi_t safi;
718e3744 14541
d62a17ae 14542 afi = bgp_node_afi(vty);
14543 safi = bgp_node_safi(vty);
718e3744 14544
585f1adc
IR
14545 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14546 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14547 || bgp->distance_local[afi][safi] != distance_local) {
14548 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14549 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14550 bgp->distance_local[afi][safi] = distance_local;
14551 bgp_announce_routes_distance_update(bgp, afi, safi);
14552 }
14553 return CMD_SUCCESS;
14554}
37a87b8f 14555
585f1adc
IR
14556DEFUN (no_bgp_distance,
14557 no_bgp_distance_cmd,
14558 "no distance bgp [(1-255) (1-255) (1-255)]",
14559 NO_STR
14560 "Define an administrative distance\n"
14561 "BGP distance\n"
14562 "Distance for routes external to the AS\n"
14563 "Distance for routes internal to the AS\n"
14564 "Distance for local routes\n")
718e3744 14565{
585f1adc 14566 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14567 afi_t afi;
14568 safi_t safi;
37a87b8f
CS
14569
14570 afi = bgp_node_afi(vty);
14571 safi = bgp_node_safi(vty);
14572
585f1adc
IR
14573 if (bgp->distance_ebgp[afi][safi] != 0
14574 || bgp->distance_ibgp[afi][safi] != 0
14575 || bgp->distance_local[afi][safi] != 0) {
14576 bgp->distance_ebgp[afi][safi] = 0;
14577 bgp->distance_ibgp[afi][safi] = 0;
14578 bgp->distance_local[afi][safi] = 0;
14579 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14580 }
585f1adc
IR
14581 return CMD_SUCCESS;
14582}
37a87b8f 14583
37a87b8f 14584
585f1adc
IR
14585DEFUN (bgp_distance_source,
14586 bgp_distance_source_cmd,
14587 "distance (1-255) A.B.C.D/M",
14588 "Define an administrative distance\n"
14589 "Administrative distance\n"
14590 "IP source prefix\n")
14591{
14592 int idx_number = 1;
14593 int idx_ipv4_prefixlen = 2;
14594 bgp_distance_set(vty, argv[idx_number]->arg,
14595 argv[idx_ipv4_prefixlen]->arg, NULL);
14596 return CMD_SUCCESS;
734b349e
MZ
14597}
14598
585f1adc
IR
14599DEFUN (no_bgp_distance_source,
14600 no_bgp_distance_source_cmd,
14601 "no distance (1-255) A.B.C.D/M",
14602 NO_STR
14603 "Define an administrative distance\n"
14604 "Administrative distance\n"
14605 "IP source prefix\n")
37a87b8f 14606{
585f1adc
IR
14607 int idx_number = 2;
14608 int idx_ipv4_prefixlen = 3;
14609 bgp_distance_unset(vty, argv[idx_number]->arg,
14610 argv[idx_ipv4_prefixlen]->arg, NULL);
14611 return CMD_SUCCESS;
37a87b8f
CS
14612}
14613
585f1adc
IR
14614DEFUN (bgp_distance_source_access_list,
14615 bgp_distance_source_access_list_cmd,
14616 "distance (1-255) A.B.C.D/M WORD",
14617 "Define an administrative distance\n"
14618 "Administrative distance\n"
14619 "IP source prefix\n"
14620 "Access list name\n")
37a87b8f 14621{
585f1adc
IR
14622 int idx_number = 1;
14623 int idx_ipv4_prefixlen = 2;
14624 int idx_word = 3;
14625 bgp_distance_set(vty, argv[idx_number]->arg,
14626 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14627 return CMD_SUCCESS;
14628}
718e3744 14629
585f1adc
IR
14630DEFUN (no_bgp_distance_source_access_list,
14631 no_bgp_distance_source_access_list_cmd,
14632 "no distance (1-255) A.B.C.D/M WORD",
14633 NO_STR
14634 "Define an administrative distance\n"
14635 "Administrative distance\n"
14636 "IP source prefix\n"
14637 "Access list name\n")
14638{
14639 int idx_number = 2;
14640 int idx_ipv4_prefixlen = 3;
14641 int idx_word = 4;
14642 bgp_distance_unset(vty, argv[idx_number]->arg,
14643 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14644 return CMD_SUCCESS;
14645}
37a87b8f 14646
585f1adc
IR
14647DEFUN (ipv6_bgp_distance_source,
14648 ipv6_bgp_distance_source_cmd,
14649 "distance (1-255) X:X::X:X/M",
14650 "Define an administrative distance\n"
14651 "Administrative distance\n"
14652 "IP source prefix\n")
14653{
14654 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14655 return CMD_SUCCESS;
14656}
7ebe9748 14657
585f1adc
IR
14658DEFUN (no_ipv6_bgp_distance_source,
14659 no_ipv6_bgp_distance_source_cmd,
14660 "no distance (1-255) X:X::X:X/M",
14661 NO_STR
14662 "Define an administrative distance\n"
14663 "Administrative distance\n"
14664 "IP source prefix\n")
14665{
14666 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14667 return CMD_SUCCESS;
14668}
37a87b8f 14669
585f1adc
IR
14670DEFUN (ipv6_bgp_distance_source_access_list,
14671 ipv6_bgp_distance_source_access_list_cmd,
14672 "distance (1-255) X:X::X:X/M WORD",
14673 "Define an administrative distance\n"
14674 "Administrative distance\n"
14675 "IP source prefix\n"
14676 "Access list name\n")
14677{
14678 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14679 return CMD_SUCCESS;
718e3744 14680}
14681
585f1adc
IR
14682DEFUN (no_ipv6_bgp_distance_source_access_list,
14683 no_ipv6_bgp_distance_source_access_list_cmd,
14684 "no distance (1-255) X:X::X:X/M WORD",
14685 NO_STR
14686 "Define an administrative distance\n"
14687 "Administrative distance\n"
14688 "IP source prefix\n"
14689 "Access list name\n")
718e3744 14690{
585f1adc
IR
14691 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14692 return CMD_SUCCESS;
14693}
37a87b8f 14694
585f1adc
IR
14695DEFUN (bgp_damp_set,
14696 bgp_damp_set_cmd,
a30fec23 14697 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14698 "BGP Specific commands\n"
14699 "Enable route-flap dampening\n"
14700 "Half-life time for the penalty\n"
14701 "Value to start reusing a route\n"
14702 "Value to start suppressing a route\n"
14703 "Maximum duration to suppress a stable route\n")
14704{
14705 VTY_DECLVAR_CONTEXT(bgp, bgp);
14706 int idx_half_life = 2;
14707 int idx_reuse = 3;
14708 int idx_suppress = 4;
14709 int idx_max_suppress = 5;
37a87b8f
CS
14710 int half = DEFAULT_HALF_LIFE * 60;
14711 int reuse = DEFAULT_REUSE;
14712 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14713 int max = 4 * half;
14714
14715 if (argc == 6) {
14716 half = atoi(argv[idx_half_life]->arg) * 60;
14717 reuse = atoi(argv[idx_reuse]->arg);
14718 suppress = atoi(argv[idx_suppress]->arg);
14719 max = atoi(argv[idx_max_suppress]->arg) * 60;
14720 } else if (argc == 3) {
14721 half = atoi(argv[idx_half_life]->arg) * 60;
14722 max = 4 * half;
14723 }
14724
14725 /*
14726 * These can't be 0 but our SA doesn't understand the
14727 * way our cli is constructed
14728 */
14729 assert(reuse);
14730 assert(half);
14731 if (suppress < reuse) {
14732 vty_out(vty,
14733 "Suppress value cannot be less than reuse value \n");
14734 return 0;
14735 }
14736
14737 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14738 reuse, suppress, max);
14739}
14740
14741DEFUN (bgp_damp_unset,
14742 bgp_damp_unset_cmd,
a30fec23 14743 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14744 NO_STR
14745 "BGP Specific commands\n"
14746 "Enable route-flap dampening\n"
14747 "Half-life time for the penalty\n"
14748 "Value to start reusing a route\n"
14749 "Value to start suppressing a route\n"
14750 "Maximum duration to suppress a stable route\n")
14751{
14752 VTY_DECLVAR_CONTEXT(bgp, bgp);
14753 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14754}
14755
718e3744 14756/* Display specified route of BGP table. */
d62a17ae 14757static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14758 const char *ip_str, afi_t afi, safi_t safi,
14759 struct prefix_rd *prd, int prefix_check)
14760{
14761 int ret;
14762 struct prefix match;
9bcb3eef
DS
14763 struct bgp_dest *dest;
14764 struct bgp_dest *rm;
40381db7
DS
14765 struct bgp_path_info *pi;
14766 struct bgp_path_info *pi_temp;
d62a17ae 14767 struct bgp *bgp;
14768 struct bgp_table *table;
14769
14770 /* BGP structure lookup. */
14771 if (view_name) {
14772 bgp = bgp_lookup_by_name(view_name);
14773 if (bgp == NULL) {
14774 vty_out(vty, "%% Can't find BGP instance %s\n",
14775 view_name);
14776 return CMD_WARNING;
14777 }
14778 } else {
14779 bgp = bgp_get_default();
14780 if (bgp == NULL) {
14781 vty_out(vty, "%% No BGP process is configured\n");
14782 return CMD_WARNING;
14783 }
718e3744 14784 }
718e3744 14785
d62a17ae 14786 /* Check IP address argument. */
14787 ret = str2prefix(ip_str, &match);
14788 if (!ret) {
14789 vty_out(vty, "%% address is malformed\n");
14790 return CMD_WARNING;
14791 }
718e3744 14792
d62a17ae 14793 match.family = afi2family(afi);
14794
14795 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14796 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14797 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14798 dest = bgp_route_next(dest)) {
14799 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14800
9bcb3eef 14801 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14802 continue;
9bcb3eef 14803 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14804 if (!table)
ea47320b 14805 continue;
4953391b
DA
14806 rm = bgp_node_match(table, &match);
14807 if (rm == NULL)
ea47320b 14808 continue;
d62a17ae 14809
9bcb3eef 14810 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14811
ea47320b 14812 if (!prefix_check
b54892e0 14813 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14814 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14815 while (pi) {
14816 if (pi->extra && pi->extra->damp_info) {
14817 pi_temp = pi->next;
ea47320b 14818 bgp_damp_info_free(
19971c9a 14819 pi->extra->damp_info,
5c8846f6 14820 1, afi, safi);
40381db7 14821 pi = pi_temp;
ea47320b 14822 } else
40381db7 14823 pi = pi->next;
d62a17ae 14824 }
ea47320b
DL
14825 }
14826
9bcb3eef 14827 bgp_dest_unlock_node(rm);
d62a17ae 14828 }
14829 } else {
4953391b
DA
14830 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14831 if (dest != NULL) {
9bcb3eef 14832 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14833
d62a17ae 14834 if (!prefix_check
9bcb3eef
DS
14835 || dest_p->prefixlen == match.prefixlen) {
14836 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14837 while (pi) {
14838 if (pi->extra && pi->extra->damp_info) {
14839 pi_temp = pi->next;
d62a17ae 14840 bgp_damp_info_free(
19971c9a 14841 pi->extra->damp_info,
5c8846f6 14842 1, afi, safi);
40381db7 14843 pi = pi_temp;
d62a17ae 14844 } else
40381db7 14845 pi = pi->next;
d62a17ae 14846 }
14847 }
14848
9bcb3eef 14849 bgp_dest_unlock_node(dest);
d62a17ae 14850 }
14851 }
718e3744 14852
d62a17ae 14853 return CMD_SUCCESS;
718e3744 14854}
14855
14856DEFUN (clear_ip_bgp_dampening,
14857 clear_ip_bgp_dampening_cmd,
14858 "clear ip bgp dampening",
14859 CLEAR_STR
14860 IP_STR
14861 BGP_STR
14862 "Clear route flap dampening information\n")
14863{
b4f7f45b 14864 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14865 return CMD_SUCCESS;
718e3744 14866}
14867
14868DEFUN (clear_ip_bgp_dampening_prefix,
14869 clear_ip_bgp_dampening_prefix_cmd,
14870 "clear ip bgp dampening A.B.C.D/M",
14871 CLEAR_STR
14872 IP_STR
14873 BGP_STR
14874 "Clear route flap dampening information\n"
0c7b1b01 14875 "IPv4 prefix\n")
718e3744 14876{
d62a17ae 14877 int idx_ipv4_prefixlen = 4;
14878 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14879 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14880}
14881
14882DEFUN (clear_ip_bgp_dampening_address,
14883 clear_ip_bgp_dampening_address_cmd,
14884 "clear ip bgp dampening A.B.C.D",
14885 CLEAR_STR
14886 IP_STR
14887 BGP_STR
14888 "Clear route flap dampening information\n"
14889 "Network to clear damping information\n")
14890{
d62a17ae 14891 int idx_ipv4 = 4;
14892 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14893 SAFI_UNICAST, NULL, 0);
718e3744 14894}
14895
14896DEFUN (clear_ip_bgp_dampening_address_mask,
14897 clear_ip_bgp_dampening_address_mask_cmd,
14898 "clear ip bgp dampening A.B.C.D A.B.C.D",
14899 CLEAR_STR
14900 IP_STR
14901 BGP_STR
14902 "Clear route flap dampening information\n"
14903 "Network to clear damping information\n"
14904 "Network mask\n")
14905{
d62a17ae 14906 int idx_ipv4 = 4;
14907 int idx_ipv4_2 = 5;
14908 int ret;
14909 char prefix_str[BUFSIZ];
718e3744 14910
d62a17ae 14911 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14912 prefix_str, sizeof(prefix_str));
d62a17ae 14913 if (!ret) {
14914 vty_out(vty, "%% Inconsistent address and mask\n");
14915 return CMD_WARNING;
14916 }
718e3744 14917
d62a17ae 14918 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14919 NULL, 0);
718e3744 14920}
6b0655a2 14921
e3b78da8 14922static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14923{
14924 struct vty *vty = arg;
e3b78da8 14925 struct peer *peer = bucket->data;
825d9834
DS
14926 char buf[SU_ADDRSTRLEN];
14927
14928 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14929 sockunion2str(&peer->su, buf, sizeof(buf)));
14930}
14931
2a0e69ae
DS
14932DEFUN (show_bgp_listeners,
14933 show_bgp_listeners_cmd,
14934 "show bgp listeners",
14935 SHOW_STR
14936 BGP_STR
14937 "Display Listen Sockets and who created them\n")
14938{
14939 bgp_dump_listener_info(vty);
14940
14941 return CMD_SUCCESS;
14942}
14943
825d9834
DS
14944DEFUN (show_bgp_peerhash,
14945 show_bgp_peerhash_cmd,
14946 "show bgp peerhash",
14947 SHOW_STR
14948 BGP_STR
14949 "Display information about the BGP peerhash\n")
14950{
14951 struct list *instances = bm->bgp;
14952 struct listnode *node;
14953 struct bgp *bgp;
14954
14955 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14956 vty_out(vty, "BGP: %s\n", bgp->name);
14957 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14958 vty);
14959 }
14960
14961 return CMD_SUCCESS;
14962}
14963
587ff0fd 14964/* also used for encap safi */
2b791107
DL
14965static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14966 afi_t afi, safi_t safi)
d62a17ae 14967{
9bcb3eef
DS
14968 struct bgp_dest *pdest;
14969 struct bgp_dest *dest;
d62a17ae 14970 struct bgp_table *table;
b54892e0
DS
14971 const struct prefix *p;
14972 const struct prefix_rd *prd;
d62a17ae 14973 struct bgp_static *bgp_static;
14974 mpls_label_t label;
d62a17ae 14975 char rdbuf[RD_ADDRSTRLEN];
14976
14977 /* Network configuration. */
9bcb3eef
DS
14978 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14979 pdest = bgp_route_next(pdest)) {
14980 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14981 if (!table)
ea47320b 14982 continue;
d62a17ae 14983
9bcb3eef
DS
14984 for (dest = bgp_table_top(table); dest;
14985 dest = bgp_route_next(dest)) {
14986 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14987 if (bgp_static == NULL)
ea47320b 14988 continue;
d62a17ae 14989
9bcb3eef
DS
14990 p = bgp_dest_get_prefix(dest);
14991 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14992 pdest);
d62a17ae 14993
ea47320b 14994 /* "network" configuration display. */
06b9f471 14995 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14996 label = decode_label(&bgp_static->label);
14997
8228a9a7 14998 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14999 if (safi == SAFI_MPLS_VPN)
15000 vty_out(vty, " label %u", label);
15001
15002 if (bgp_static->rmap.name)
15003 vty_out(vty, " route-map %s",
15004 bgp_static->rmap.name);
e2a86ad9
DS
15005
15006 if (bgp_static->backdoor)
15007 vty_out(vty, " backdoor");
15008
ea47320b
DL
15009 vty_out(vty, "\n");
15010 }
15011 }
d62a17ae 15012}
15013
2b791107
DL
15014static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15015 afi_t afi, safi_t safi)
d62a17ae 15016{
9bcb3eef
DS
15017 struct bgp_dest *pdest;
15018 struct bgp_dest *dest;
d62a17ae 15019 struct bgp_table *table;
b54892e0
DS
15020 const struct prefix *p;
15021 const struct prefix_rd *prd;
d62a17ae 15022 struct bgp_static *bgp_static;
ff44f570 15023 char buf[PREFIX_STRLEN * 2];
d62a17ae 15024 char buf2[SU_ADDRSTRLEN];
15025 char rdbuf[RD_ADDRSTRLEN];
5f933e1e 15026 char esi_buf[ESI_STR_LEN];
d62a17ae 15027
15028 /* Network configuration. */
9bcb3eef
DS
15029 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15030 pdest = bgp_route_next(pdest)) {
15031 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15032 if (!table)
ea47320b 15033 continue;
d62a17ae 15034
9bcb3eef
DS
15035 for (dest = bgp_table_top(table); dest;
15036 dest = bgp_route_next(dest)) {
15037 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15038 if (bgp_static == NULL)
ea47320b 15039 continue;
d62a17ae 15040
ea47320b 15041 char *macrouter = NULL;
d62a17ae 15042
ea47320b
DL
15043 if (bgp_static->router_mac)
15044 macrouter = prefix_mac2str(
15045 bgp_static->router_mac, NULL, 0);
15046 if (bgp_static->eth_s_id)
0a50c248
AK
15047 esi_to_str(bgp_static->eth_s_id,
15048 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15049 p = bgp_dest_get_prefix(dest);
15050 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15051
ea47320b 15052 /* "network" configuration display. */
06b9f471 15053 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15054 if (p->u.prefix_evpn.route_type == 5) {
15055 char local_buf[PREFIX_STRLEN];
3714a385 15056 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15057 struct prefix_evpn *)p)
15058 ? AF_INET
15059 : AF_INET6;
3714a385 15060 inet_ntop(family,
15061 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15062 local_buf, PREFIX_STRLEN);
772270f3
QY
15063 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15064 p->u.prefix_evpn.prefix_addr
15065 .ip_prefix_length);
197cb530
PG
15066 } else {
15067 prefix2str(p, buf, sizeof(buf));
15068 }
ea47320b 15069
a4d82a8a
PZ
15070 if (bgp_static->gatewayIp.family == AF_INET
15071 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15072 inet_ntop(bgp_static->gatewayIp.family,
15073 &bgp_static->gatewayIp.u.prefix, buf2,
15074 sizeof(buf2));
ea47320b 15075 vty_out(vty,
7bcc8dac 15076 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15077 buf, rdbuf,
15078 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15079 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15080 macrouter);
15081
0a22ddfb 15082 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15083 }
15084 }
3da6fcd5
PG
15085}
15086
718e3744 15087/* Configuration of static route announcement and aggregate
15088 information. */
2b791107
DL
15089void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15090 safi_t safi)
d62a17ae 15091{
9bcb3eef 15092 struct bgp_dest *dest;
b54892e0 15093 const struct prefix *p;
d62a17ae 15094 struct bgp_static *bgp_static;
15095 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15096
2b791107
DL
15097 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15098 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15099 return;
15100 }
d62a17ae 15101
2b791107
DL
15102 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15103 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15104 return;
15105 }
d62a17ae 15106
15107 /* Network configuration. */
9bcb3eef
DS
15108 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15109 dest = bgp_route_next(dest)) {
15110 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15111 if (bgp_static == NULL)
ea47320b 15112 continue;
d62a17ae 15113
9bcb3eef 15114 p = bgp_dest_get_prefix(dest);
d62a17ae 15115
8228a9a7 15116 vty_out(vty, " network %pFX", p);
d62a17ae 15117
ea47320b
DL
15118 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15119 vty_out(vty, " label-index %u",
15120 bgp_static->label_index);
d62a17ae 15121
ea47320b
DL
15122 if (bgp_static->rmap.name)
15123 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15124
15125 if (bgp_static->backdoor)
15126 vty_out(vty, " backdoor");
718e3744 15127
ea47320b
DL
15128 vty_out(vty, "\n");
15129 }
15130
d62a17ae 15131 /* Aggregate-address configuration. */
9bcb3eef
DS
15132 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15133 dest = bgp_route_next(dest)) {
15134 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15135 if (bgp_aggregate == NULL)
ea47320b 15136 continue;
d62a17ae 15137
9bcb3eef 15138 p = bgp_dest_get_prefix(dest);
d62a17ae 15139
8228a9a7 15140 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15141
ea47320b
DL
15142 if (bgp_aggregate->as_set)
15143 vty_out(vty, " as-set");
d62a17ae 15144
ea47320b
DL
15145 if (bgp_aggregate->summary_only)
15146 vty_out(vty, " summary-only");
718e3744 15147
20894f50
DA
15148 if (bgp_aggregate->rmap.name)
15149 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15150
229757f1
DA
15151 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15152 vty_out(vty, " origin %s",
15153 bgp_origin2str(bgp_aggregate->origin));
15154
6aabb15d
RZ
15155 if (bgp_aggregate->match_med)
15156 vty_out(vty, " matching-MED-only");
15157
365ab2e7
RZ
15158 if (bgp_aggregate->suppress_map_name)
15159 vty_out(vty, " suppress-map %s",
15160 bgp_aggregate->suppress_map_name);
15161
ea47320b
DL
15162 vty_out(vty, "\n");
15163 }
d62a17ae 15164}
734b349e 15165
2b791107 15166void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15167 safi_t safi)
d62a17ae 15168{
9bcb3eef 15169 struct bgp_dest *dest;
d62a17ae 15170 struct bgp_distance *bdistance;
15171
15172 /* Distance configuration. */
15173 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15174 && bgp->distance_local[afi][safi]
15175 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15176 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15177 || bgp->distance_local[afi][safi]
15178 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15179 vty_out(vty, " distance bgp %d %d %d\n",
15180 bgp->distance_ebgp[afi][safi],
15181 bgp->distance_ibgp[afi][safi],
15182 bgp->distance_local[afi][safi]);
15183 }
734b349e 15184
9bcb3eef
DS
15185 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15186 dest = bgp_route_next(dest)) {
15187 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15188 if (bdistance != NULL)
56ca3b5b 15189 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15190 bdistance->distance, dest,
d62a17ae 15191 bdistance->access_list ? bdistance->access_list
15192 : "");
ca2e160d 15193 }
718e3744 15194}
15195
15196/* Allocate routing table structure and install commands. */
d62a17ae 15197void bgp_route_init(void)
15198{
15199 afi_t afi;
15200 safi_t safi;
15201
15202 /* Init BGP distance table. */
05c7a1cc 15203 FOREACH_AFI_SAFI (afi, safi)
960035b2 15204 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15205
15206 /* IPv4 BGP commands. */
15207 install_element(BGP_NODE, &bgp_table_map_cmd);
15208 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15209 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15210
554b3b10 15211 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15212
15213 /* IPv4 unicast configuration. */
15214 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15215 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15216 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15217
554b3b10 15218 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15219
15220 /* IPv4 multicast configuration. */
15221 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15222 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15223 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15224 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15225
15226 /* IPv4 labeled-unicast configuration. */
fb985e0c 15227 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15228 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15229
d62a17ae 15230 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15231 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15232 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15233 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15234 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15235 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15236 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15237 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15238
15239 install_element(VIEW_NODE,
15240 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15241 install_element(VIEW_NODE,
15242 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15243 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15244 install_element(VIEW_NODE,
15245 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15246#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15247 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15248#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15249 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15250 install_element(VIEW_NODE,
44c69747 15251 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15252
d62a17ae 15253 /* BGP dampening clear commands */
15254 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15255 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15256
d62a17ae 15257 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15258 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15259
15260 /* prefix count */
15261 install_element(ENABLE_NODE,
15262 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15263#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15264 install_element(ENABLE_NODE,
15265 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15266#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15267
d62a17ae 15268 /* New config IPv6 BGP commands. */
15269 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15270 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15271 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15272
554b3b10 15273 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15274
15275 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15276
fb985e0c
DA
15277 /* IPv6 labeled unicast address family. */
15278 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15279 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15280
d62a17ae 15281 install_element(BGP_NODE, &bgp_distance_cmd);
15282 install_element(BGP_NODE, &no_bgp_distance_cmd);
15283 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15284 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15285 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15286 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15287 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15288 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15289 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15290 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15291 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15292 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15293 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15294 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15295 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15296 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15297 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15298 install_element(BGP_IPV4M_NODE,
15299 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15300 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15301 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15302 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15303 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15304 install_element(BGP_IPV6_NODE,
15305 &ipv6_bgp_distance_source_access_list_cmd);
15306 install_element(BGP_IPV6_NODE,
15307 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15308 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15309 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15310 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15311 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15312 install_element(BGP_IPV6M_NODE,
15313 &ipv6_bgp_distance_source_access_list_cmd);
15314 install_element(BGP_IPV6M_NODE,
15315 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15316
ef5f4b23 15317 /* BGP dampening */
585f1adc
IR
15318 install_element(BGP_NODE, &bgp_damp_set_cmd);
15319 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15320 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15321 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15322 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15323 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15324 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15325 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15326 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15327 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15328 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15329 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15330 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15331 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15332
15333 /* Large Communities */
15334 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15335 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15336
15337 /* show bgp ipv4 flowspec detailed */
15338 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15339
2a0e69ae 15340 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15341 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15342}
15343
15344void bgp_route_finish(void)
15345{
15346 afi_t afi;
15347 safi_t safi;
15348
05c7a1cc
QY
15349 FOREACH_AFI_SAFI (afi, safi) {
15350 bgp_table_unlock(bgp_distance_table[afi][safi]);
15351 bgp_distance_table[afi][safi] = NULL;
15352 }
228da428 15353}