]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #10254 from ton31337/fix/typo
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
7fd28dd2
PR
96DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 98 (rn, pi, added));
7fd28dd2 99
b5b99af8
DS
100DEFINE_HOOK(bgp_rpki_prefix_status,
101 (struct peer *peer, struct attr *attr,
102 const struct prefix *prefix),
8451921b 103 (peer, attr, prefix));
b5b99af8 104
2aad8c42
MS
105/* Render dest to prefix_rd based on safi */
106static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
107 safi_t safi);
108
718e3744 109/* Extern from bgp_dump.c */
dde72586
SH
110extern const char *bgp_origin_str[];
111extern const char *bgp_origin_long_str[];
3742de8d 112
b7d08f5a 113/* PMSI strings. */
114#define PMSI_TNLTYPE_STR_NO_INFO "No info"
115#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116static const struct message bgp_pmsi_tnltype_str[] = {
117 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 125 {0}
126};
b7d08f5a 127
9df8b37c 128#define VRFID_NONE_STR "-"
46aeabed 129#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 130
4a11bf2c 131DEFINE_HOOK(bgp_process,
9bcb3eef
DS
132 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
133 struct peer *peer, bool withdraw),
8451921b 134 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 135
4056a5f6
RZ
136/** Test if path is suppressed. */
137static bool bgp_path_suppressed(struct bgp_path_info *pi)
138{
139 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
140 return false;
141
142 return listcount(pi->extra->aggr_suppressors) > 0;
143}
4a11bf2c 144
9bcb3eef 145struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 146 safi_t safi, const struct prefix *p,
d62a17ae 147 struct prefix_rd *prd)
148{
9bcb3eef
DS
149 struct bgp_dest *dest;
150 struct bgp_dest *pdest = NULL;
d62a17ae 151
152 assert(table);
d62a17ae 153
154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN)) {
9bcb3eef 156 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 157
9bcb3eef
DS
158 if (!bgp_dest_has_bgp_path_info_data(pdest))
159 bgp_dest_set_bgp_table_info(
160 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 161 else
9bcb3eef
DS
162 bgp_dest_unlock_node(pdest);
163 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 164 }
718e3744 165
9bcb3eef 166 dest = bgp_node_get(table, p);
718e3744 167
d62a17ae 168 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
169 || (safi == SAFI_EVPN))
9bcb3eef 170 dest->pdest = pdest;
718e3744 171
9bcb3eef 172 return dest;
718e3744 173}
6b0655a2 174
9bcb3eef 175struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 176 safi_t safi, const struct prefix *p,
d62a17ae 177 struct prefix_rd *prd)
128ea8ab 178{
9bcb3eef
DS
179 struct bgp_dest *dest;
180 struct bgp_dest *pdest = NULL;
128ea8ab 181
d62a17ae 182 if (!table)
183 return NULL;
128ea8ab 184
d62a17ae 185 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
186 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
187 pdest = bgp_node_lookup(table, (struct prefix *)prd);
188 if (!pdest)
d62a17ae 189 return NULL;
128ea8ab 190
9bcb3eef
DS
191 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
192 bgp_dest_unlock_node(pdest);
d62a17ae 193 return NULL;
194 }
128ea8ab 195
9bcb3eef 196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 197 }
128ea8ab 198
9bcb3eef 199 dest = bgp_node_lookup(table, p);
128ea8ab 200
9bcb3eef 201 return dest;
128ea8ab 202}
203
18ee8310
DS
204/* Allocate bgp_path_info_extra */
205static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 206{
4b7e6066
DS
207 struct bgp_path_info_extra *new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
209 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
210 new->label[0] = MPLS_INVALID_LABEL;
211 new->num_labels = 0;
3e3708cb
PG
212 new->bgp_fs_pbr = NULL;
213 new->bgp_fs_iprule = NULL;
d62a17ae 214 return new;
fb982c25
PJ
215}
216
a2e219fe 217void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 218{
4b7e6066 219 struct bgp_path_info_extra *e;
d62a17ae 220
c93a3b77
DS
221 if (!extra || !*extra)
222 return;
d62a17ae 223
c93a3b77 224 e = *extra;
4538f895 225 if (e->damp_info)
b4f7f45b
IR
226 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
227 e->damp_info->safi);
4538f895 228
c93a3b77
DS
229 e->damp_info = NULL;
230 if (e->parent) {
40381db7 231 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 232
40381db7 233 if (bpi->net) {
0e70e6c8
DL
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
237 *
40381db7
DS
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
0e70e6c8
DL
241 */
242 unsigned refcount;
243
40381db7 244 bpi = bgp_path_info_lock(bpi);
c10e14e9 245 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 246 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 247 if (!refcount)
40381db7
DS
248 bpi->net = NULL;
249 bgp_path_info_unlock(bpi);
0e70e6c8 250 }
18ee8310 251 bgp_path_info_unlock(e->parent);
c93a3b77 252 e->parent = NULL;
d62a17ae 253 }
c93a3b77
DS
254
255 if (e->bgp_orig)
256 bgp_unlock(e->bgp_orig);
c26edcda 257
ff3bf9a4
DS
258 if (e->aggr_suppressors)
259 list_delete(&e->aggr_suppressors);
260
60605cbc
AK
261 if (e->mh_info)
262 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 263
ce3c0614
PG
264 if ((*extra)->bgp_fs_iprule)
265 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 266 if ((*extra)->bgp_fs_pbr)
6a154c88 267 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 268 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
269}
270
18ee8310
DS
271/* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
fb982c25 273 */
40381db7 274struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 275{
40381db7
DS
276 if (!pi->extra)
277 pi->extra = bgp_path_info_extra_new();
278 return pi->extra;
fb982c25
PJ
279}
280
718e3744 281/* Free bgp route information. */
9b6d8fcf 282static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 283{
05864da7 284 bgp_attr_unintern(&path->attr);
fb018d25 285
9b6d8fcf
DS
286 bgp_unlink_nexthop(path);
287 bgp_path_info_extra_free(&path->extra);
288 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
289 if (path->net)
290 bgp_addpath_free_info_data(&path->tx_addpath,
291 &path->net->tx_addpath);
718e3744 292
9b6d8fcf 293 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 294
9b6d8fcf 295 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 296}
297
9b6d8fcf 298struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 299{
9b6d8fcf
DS
300 path->lock++;
301 return path;
200df115 302}
303
9b6d8fcf 304struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 305{
9b6d8fcf
DS
306 assert(path && path->lock > 0);
307 path->lock--;
d62a17ae 308
9b6d8fcf 309 if (path->lock == 0) {
9b6d8fcf 310 bgp_path_info_free(path);
d62a17ae 311 return NULL;
312 }
200df115 313
9b6d8fcf 314 return path;
200df115 315}
316
f009ff26 317/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 318static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 319{
320 struct peer *peer;
321 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 322 bool set_flag = false;
f009ff26 323 struct bgp *bgp = NULL;
324 struct bgp_table *table = NULL;
325 afi_t afi = 0;
326 safi_t safi = 0;
f009ff26 327
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
330 */
9bcb3eef 331 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 332 return 0;
333
9bcb3eef 334 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 335 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 336 zlog_debug(
56ca3b5b
DL
337 "Route %pBD is in workqueue and being processed, not deferred.",
338 dest);
b54892e0 339
5f9c1aa2 340 return 0;
341 }
342
9bcb3eef 343 table = bgp_dest_table(dest);
f009ff26 344 if (table) {
345 bgp = table->bgp;
346 afi = table->afi;
347 safi = table->safi;
348 }
349
9bcb3eef 350 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 351 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
352 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
353 continue;
354
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
357 */
36235319
QY
358 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
359 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 360 set_flag = true;
f009ff26 361 } else {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
364 */
365 peer = old_pi->peer;
36235319
QY
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
367 && BGP_PEER_RESTARTING_MODE(peer)
368 && (old_pi
369 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 370 set_flag = true;
f009ff26 371 }
372 }
373 if (set_flag)
374 break;
375 }
376
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
378 * is active
379 */
2ba1fe69 380 if (set_flag && table) {
f009ff26 381 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
382 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
383 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 384 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 385 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
386 zlog_debug("DEFER route %pBD, dest %p", dest,
387 dest);
f009ff26 388 return 0;
389 }
390 }
391 return -1;
392}
393
9bcb3eef 394void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 395{
4b7e6066 396 struct bgp_path_info *top;
718e3744 397
9bcb3eef 398 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 399
6f94b685 400 pi->next = top;
40381db7 401 pi->prev = NULL;
d62a17ae 402 if (top)
40381db7 403 top->prev = pi;
9bcb3eef 404 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 405
40381db7 406 bgp_path_info_lock(pi);
9bcb3eef 407 bgp_dest_lock_node(dest);
40381db7 408 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 409 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 410 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 411}
412
d62a17ae 413/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 414 completion callback *only* */
9bcb3eef 415void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 416{
40381db7
DS
417 if (pi->next)
418 pi->next->prev = pi->prev;
419 if (pi->prev)
420 pi->prev->next = pi->next;
d62a17ae 421 else
9bcb3eef 422 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 423
40381db7
DS
424 bgp_path_info_mpath_dequeue(pi);
425 bgp_path_info_unlock(pi);
7fd28dd2 426 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 427 bgp_dest_unlock_node(dest);
718e3744 428}
429
9bcb3eef 430void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 431{
9bcb3eef 432 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 433 /* set of previous already took care of pcount */
40381db7 434 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 435}
436
18ee8310 437/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
438 called when a route is deleted and then quickly re-added before the
439 deletion has been processed */
9bcb3eef 440void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 441{
9bcb3eef 442 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 443 /* unset of previous already took care of pcount */
40381db7 444 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
445}
446
d62a17ae 447/* Adjust pcount as required */
9bcb3eef 448static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 449{
d62a17ae 450 struct bgp_table *table;
67174041 451
9bcb3eef 452 assert(dest && bgp_dest_table(dest));
40381db7 453 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 454
9bcb3eef 455 table = bgp_dest_table(dest);
67174041 456
40381db7 457 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 458 return;
459
40381db7
DS
460 if (!BGP_PATH_COUNTABLE(pi)
461 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 462
40381db7 463 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 464
465 /* slight hack, but more robust against errors. */
40381db7
DS
466 if (pi->peer->pcount[table->afi][table->safi])
467 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 468 else
450971aa 469 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 470 "Asked to decrement 0 prefix count for peer");
40381db7
DS
471 } else if (BGP_PATH_COUNTABLE(pi)
472 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
473 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
474 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 475 }
1a392d46
PJ
476}
477
40381db7
DS
478static int bgp_label_index_differs(struct bgp_path_info *pi1,
479 struct bgp_path_info *pi2)
28d58fd7 480{
40381db7 481 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 482}
1a392d46 483
18ee8310 484/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
485 * This is here primarily to keep prefix-count in check.
486 */
9bcb3eef 487void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 488 uint32_t flag)
1a392d46 489{
40381db7 490 SET_FLAG(pi->flags, flag);
d62a17ae 491
492 /* early bath if we know it's not a flag that changes countability state
493 */
494 if (!CHECK_FLAG(flag,
1defdda8 495 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 496 return;
497
9bcb3eef 498 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
499}
500
9bcb3eef 501void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 502 uint32_t flag)
1a392d46 503{
40381db7 504 UNSET_FLAG(pi->flags, flag);
d62a17ae 505
506 /* early bath if we know it's not a flag that changes countability state
507 */
508 if (!CHECK_FLAG(flag,
1defdda8 509 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 510 return;
511
9bcb3eef 512 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
513}
514
718e3744 515/* Get MED value. If MED value is missing and "bgp bestpath
516 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 517static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 518{
519 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
520 return attr->med;
521 else {
892fedb6 522 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 523 return BGP_MED_MAX;
524 else
525 return 0;
526 }
718e3744 527}
528
7533cad7
QY
529void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
530 size_t buf_len)
2ec1e66f 531{
40381db7 532 if (pi->addpath_rx_id)
7533cad7
QY
533 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
534 pi->peer->host, pi->addpath_rx_id);
d62a17ae 535 else
7533cad7 536 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 537}
9fbdd100 538
da0c0ef7
KM
539
540/*
541 * Get the ultimate path info.
542 */
543struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
544{
545 struct bgp_path_info *bpi_ultimate;
546
547 if (info->sub_type != BGP_ROUTE_IMPORTED)
548 return info;
549
550 for (bpi_ultimate = info;
551 bpi_ultimate->extra && bpi_ultimate->extra->parent;
552 bpi_ultimate = bpi_ultimate->extra->parent)
553 ;
554
555 return bpi_ultimate;
556}
557
d62a17ae 558/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 */
18ee8310
DS
560static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
561 struct bgp_path_info *exist, int *paths_eq,
562 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
563 char *pfx_buf, afi_t afi, safi_t safi,
564 enum bgp_path_selection_reason *reason)
d62a17ae 565{
5df26422 566 const struct prefix *new_p;
d62a17ae 567 struct attr *newattr, *existattr;
568 bgp_peer_sort_t new_sort;
569 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
570 uint32_t new_pref;
571 uint32_t exist_pref;
572 uint32_t new_med;
573 uint32_t exist_med;
574 uint32_t new_weight;
575 uint32_t exist_weight;
d62a17ae 576 uint32_t newm, existm;
577 struct in_addr new_id;
578 struct in_addr exist_id;
579 int new_cluster;
580 int exist_cluster;
581 int internal_as_route;
582 int confed_as_route;
04d14c8b 583 int ret = 0;
ee88563a
JM
584 int igp_metric_ret = 0;
585 int peer_sort_ret = -1;
d62a17ae 586 char new_buf[PATH_ADDPATH_STR_BUFFER];
587 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
588 uint32_t new_mm_seq;
589 uint32_t exist_mm_seq;
6d8c603a 590 int nh_cmp;
d071f237
AK
591 esi_t *exist_esi;
592 esi_t *new_esi;
593 bool same_esi;
594 bool old_proxy;
595 bool new_proxy;
33c6e933 596 bool new_origin, exist_origin;
da0c0ef7 597 struct bgp_path_info *bpi_ultimate;
d62a17ae 598
599 *paths_eq = 0;
600
601 /* 0. Null check. */
602 if (new == NULL) {
fdf81fa0 603 *reason = bgp_path_selection_none;
d62a17ae 604 if (debug)
605 zlog_debug("%s: new is NULL", pfx_buf);
606 return 0;
607 }
2ec1e66f 608
da0c0ef7
KM
609 if (debug) {
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 612 sizeof(new_buf));
da0c0ef7 613 }
718e3744 614
d62a17ae 615 if (exist == NULL) {
fdf81fa0 616 *reason = bgp_path_selection_first;
d62a17ae 617 if (debug)
4378495a
DS
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 620 return 1;
621 }
2ec1e66f 622
d62a17ae 623 if (debug) {
da0c0ef7
KM
624 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 626 sizeof(exist_buf));
4378495a
DS
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf, bgp->name_pretty, new_buf, new->flags,
629 exist_buf, exist->flags);
d62a17ae 630 }
8ff56318 631
d62a17ae 632 newattr = new->attr;
633 existattr = exist->attr;
634
5df26422
NS
635 new_p = bgp_dest_get_prefix(new->net);
636
d62a17ae 637 /* For EVPN routes, we cannot just go by local vs remote, we have to
638 * look at the MAC mobility sequence number, if present.
639 */
5df26422
NS
640 if ((safi == SAFI_EVPN)
641 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 642 /* This is an error condition described in RFC 7432 Section
643 * 15.2. The RFC
644 * states that in this scenario "the PE MUST alert the operator"
645 * but it
646 * does not state what other action to take. In order to provide
647 * some
648 * consistency in this scenario we are going to prefer the path
649 * with the
650 * sticky flag.
651 */
652 if (newattr->sticky != existattr->sticky) {
653 if (!debug) {
5df26422
NS
654 prefix2str(new_p, pfx_buf,
655 sizeof(*pfx_buf)
656 * PREFIX2STR_BUFFER);
18ee8310 657 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
658 new, new_buf, sizeof(new_buf));
659 bgp_path_info_path_with_addpath_rx_str(
660 exist, exist_buf, sizeof(exist_buf));
d62a17ae 661 }
662
663 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 664 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
665 if (debug)
666 zlog_debug(
667 "%s: %s wins over %s due to sticky MAC flag",
668 pfx_buf, new_buf, exist_buf);
d62a17ae 669 return 1;
670 }
671
672 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 673 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
674 if (debug)
675 zlog_debug(
676 "%s: %s loses to %s due to sticky MAC flag",
677 pfx_buf, new_buf, exist_buf);
d62a17ae 678 return 0;
679 }
680 }
128ea8ab 681
d071f237
AK
682 new_esi = bgp_evpn_attr_get_esi(newattr);
683 exist_esi = bgp_evpn_attr_get_esi(existattr);
684 if (bgp_evpn_is_esi_valid(new_esi) &&
685 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
686 same_esi = true;
687 } else {
688 same_esi = false;
689 }
690
691 /* If both paths have the same non-zero ES and
692 * one path is local it wins.
693 * PS: Note the local path wins even if the remote
694 * has the higher MM seq. The local path's
695 * MM seq will be fixed up to match the highest
696 * rem seq, subsequently.
697 */
698 if (same_esi) {
699 char esi_buf[ESI_STR_LEN];
700
701 if (bgp_evpn_is_path_local(bgp, new)) {
702 *reason = bgp_path_selection_evpn_local_path;
703 if (debug)
704 zlog_debug(
705 "%s: %s wins over %s as ES %s is same and local",
706 pfx_buf, new_buf, exist_buf,
707 esi_to_str(new_esi, esi_buf,
708 sizeof(esi_buf)));
709 return 1;
710 }
711 if (bgp_evpn_is_path_local(bgp, exist)) {
712 *reason = bgp_path_selection_evpn_local_path;
713 if (debug)
714 zlog_debug(
715 "%s: %s loses to %s as ES %s is same and local",
716 pfx_buf, new_buf, exist_buf,
717 esi_to_str(new_esi, esi_buf,
718 sizeof(esi_buf)));
719 return 0;
720 }
721 }
722
d62a17ae 723 new_mm_seq = mac_mobility_seqnum(newattr);
724 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 725
d62a17ae 726 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 727 *reason = bgp_path_selection_evpn_seq;
d62a17ae 728 if (debug)
729 zlog_debug(
730 "%s: %s wins over %s due to MM seq %u > %u",
731 pfx_buf, new_buf, exist_buf, new_mm_seq,
732 exist_mm_seq);
733 return 1;
734 }
8ff56318 735
d62a17ae 736 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 737 *reason = bgp_path_selection_evpn_seq;
d62a17ae 738 if (debug)
739 zlog_debug(
740 "%s: %s loses to %s due to MM seq %u < %u",
741 pfx_buf, new_buf, exist_buf, new_mm_seq,
742 exist_mm_seq);
743 return 0;
744 }
6d8c603a 745
d071f237
AK
746 /* if the sequence numbers and ESI are the same and one path
747 * is non-proxy it wins (over proxy)
748 */
749 new_proxy = bgp_evpn_attr_is_proxy(newattr);
750 old_proxy = bgp_evpn_attr_is_proxy(existattr);
751 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
752 old_proxy != new_proxy) {
753 if (!new_proxy) {
754 *reason = bgp_path_selection_evpn_non_proxy;
755 if (debug)
756 zlog_debug(
757 "%s: %s wins over %s, same seq/es and non-proxy",
758 pfx_buf, new_buf, exist_buf);
759 return 1;
760 }
761
762 *reason = bgp_path_selection_evpn_non_proxy;
763 if (debug)
764 zlog_debug(
765 "%s: %s loses to %s, same seq/es and non-proxy",
766 pfx_buf, new_buf, exist_buf);
767 return 0;
768 }
769
6d8c603a
AK
770 /*
771 * if sequence numbers are the same path with the lowest IP
772 * wins
773 */
774 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
775 if (nh_cmp < 0) {
fdf81fa0 776 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
777 if (debug)
778 zlog_debug(
23d0a753 779 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 780 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 781 &new->attr->nexthop);
6d8c603a
AK
782 return 1;
783 }
784 if (nh_cmp > 0) {
fdf81fa0 785 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
786 if (debug)
787 zlog_debug(
23d0a753 788 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 789 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 790 &new->attr->nexthop);
6d8c603a
AK
791 return 0;
792 }
d62a17ae 793 }
9fbdd100 794
d62a17ae 795 /* 1. Weight check. */
d62a17ae 796 new_weight = newattr->weight;
797 exist_weight = existattr->weight;
8ff56318 798
d62a17ae 799 if (new_weight > exist_weight) {
fdf81fa0 800 *reason = bgp_path_selection_weight;
d62a17ae 801 if (debug)
802 zlog_debug("%s: %s wins over %s due to weight %d > %d",
803 pfx_buf, new_buf, exist_buf, new_weight,
804 exist_weight);
805 return 1;
806 }
718e3744 807
d62a17ae 808 if (new_weight < exist_weight) {
fdf81fa0 809 *reason = bgp_path_selection_weight;
d62a17ae 810 if (debug)
811 zlog_debug("%s: %s loses to %s due to weight %d < %d",
812 pfx_buf, new_buf, exist_buf, new_weight,
813 exist_weight);
814 return 0;
815 }
9fbdd100 816
d62a17ae 817 /* 2. Local preference check. */
818 new_pref = exist_pref = bgp->default_local_pref;
819
820 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
821 new_pref = newattr->local_pref;
822 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
823 exist_pref = existattr->local_pref;
824
825 if (new_pref > exist_pref) {
fdf81fa0 826 *reason = bgp_path_selection_local_pref;
d62a17ae 827 if (debug)
828 zlog_debug(
829 "%s: %s wins over %s due to localpref %d > %d",
830 pfx_buf, new_buf, exist_buf, new_pref,
831 exist_pref);
832 return 1;
833 }
718e3744 834
d62a17ae 835 if (new_pref < exist_pref) {
fdf81fa0 836 *reason = bgp_path_selection_local_pref;
d62a17ae 837 if (debug)
838 zlog_debug(
839 "%s: %s loses to %s due to localpref %d < %d",
840 pfx_buf, new_buf, exist_buf, new_pref,
841 exist_pref);
842 return 0;
843 }
9fbdd100 844
d62a17ae 845 /* 3. Local route check. We prefer:
846 * - BGP_ROUTE_STATIC
847 * - BGP_ROUTE_AGGREGATE
848 * - BGP_ROUTE_REDISTRIBUTE
849 */
33c6e933
DS
850 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
851 new->sub_type == BGP_ROUTE_IMPORTED);
852 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
853 exist->sub_type == BGP_ROUTE_IMPORTED);
854
855 if (new_origin && !exist_origin) {
fdf81fa0 856 *reason = bgp_path_selection_local_route;
d62a17ae 857 if (debug)
858 zlog_debug(
859 "%s: %s wins over %s due to preferred BGP_ROUTE type",
860 pfx_buf, new_buf, exist_buf);
861 return 1;
862 }
718e3744 863
33c6e933 864 if (!new_origin && exist_origin) {
fdf81fa0 865 *reason = bgp_path_selection_local_route;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s loses to %s due to preferred BGP_ROUTE type",
869 pfx_buf, new_buf, exist_buf);
870 return 0;
6811845b 871 }
718e3744 872
da0c0ef7
KM
873 /* Here if these are imported routes then get ultimate pi for
874 * path compare.
875 */
876 new = bgp_get_imported_bpi_ultimate(new);
877 exist = bgp_get_imported_bpi_ultimate(exist);
878 newattr = new->attr;
879 existattr = exist->attr;
880
d62a17ae 881 /* 4. AS path length check. */
892fedb6 882 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 883 int exist_hops = aspath_count_hops(existattr->aspath);
884 int exist_confeds = aspath_count_confeds(existattr->aspath);
885
892fedb6 886 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 887 int aspath_hops;
888
889 aspath_hops = aspath_count_hops(newattr->aspath);
890 aspath_hops += aspath_count_confeds(newattr->aspath);
891
892 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 893 *reason = bgp_path_selection_confed_as_path;
d62a17ae 894 if (debug)
895 zlog_debug(
896 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
897 pfx_buf, new_buf, exist_buf,
898 aspath_hops,
899 (exist_hops + exist_confeds));
900 return 1;
901 }
902
903 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 904 *reason = bgp_path_selection_confed_as_path;
d62a17ae 905 if (debug)
906 zlog_debug(
907 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
908 pfx_buf, new_buf, exist_buf,
909 aspath_hops,
910 (exist_hops + exist_confeds));
911 return 0;
912 }
913 } else {
914 int newhops = aspath_count_hops(newattr->aspath);
915
916 if (newhops < exist_hops) {
fdf81fa0 917 *reason = bgp_path_selection_as_path;
d62a17ae 918 if (debug)
919 zlog_debug(
920 "%s: %s wins over %s due to aspath hopcount %d < %d",
921 pfx_buf, new_buf, exist_buf,
922 newhops, exist_hops);
923 return 1;
924 }
925
926 if (newhops > exist_hops) {
fdf81fa0 927 *reason = bgp_path_selection_as_path;
d62a17ae 928 if (debug)
929 zlog_debug(
930 "%s: %s loses to %s due to aspath hopcount %d > %d",
931 pfx_buf, new_buf, exist_buf,
932 newhops, exist_hops);
933 return 0;
934 }
935 }
936 }
9fbdd100 937
d62a17ae 938 /* 5. Origin check. */
939 if (newattr->origin < existattr->origin) {
fdf81fa0 940 *reason = bgp_path_selection_origin;
d62a17ae 941 if (debug)
942 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
943 pfx_buf, new_buf, exist_buf,
944 bgp_origin_long_str[newattr->origin],
945 bgp_origin_long_str[existattr->origin]);
946 return 1;
947 }
718e3744 948
d62a17ae 949 if (newattr->origin > existattr->origin) {
fdf81fa0 950 *reason = bgp_path_selection_origin;
d62a17ae 951 if (debug)
952 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
953 pfx_buf, new_buf, exist_buf,
954 bgp_origin_long_str[newattr->origin],
955 bgp_origin_long_str[existattr->origin]);
956 return 0;
957 }
718e3744 958
d62a17ae 959 /* 6. MED check. */
960 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
961 && aspath_count_hops(existattr->aspath) == 0);
962 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
963 && aspath_count_confeds(existattr->aspath) > 0
964 && aspath_count_hops(newattr->aspath) == 0
965 && aspath_count_hops(existattr->aspath) == 0);
966
892fedb6
DA
967 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
968 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 969 || aspath_cmp_left(newattr->aspath, existattr->aspath)
970 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
971 || internal_as_route) {
972 new_med = bgp_med_value(new->attr, bgp);
973 exist_med = bgp_med_value(exist->attr, bgp);
974
975 if (new_med < exist_med) {
fdf81fa0 976 *reason = bgp_path_selection_med;
d62a17ae 977 if (debug)
978 zlog_debug(
979 "%s: %s wins over %s due to MED %d < %d",
980 pfx_buf, new_buf, exist_buf, new_med,
981 exist_med);
982 return 1;
983 }
8ff56318 984
d62a17ae 985 if (new_med > exist_med) {
fdf81fa0 986 *reason = bgp_path_selection_med;
d62a17ae 987 if (debug)
988 zlog_debug(
989 "%s: %s loses to %s due to MED %d > %d",
990 pfx_buf, new_buf, exist_buf, new_med,
991 exist_med);
992 return 0;
993 }
994 }
9fbdd100 995
d62a17ae 996 /* 7. Peer type check. */
997 new_sort = new->peer->sort;
998 exist_sort = exist->peer->sort;
999
1000 if (new_sort == BGP_PEER_EBGP
1001 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1002 *reason = bgp_path_selection_peer;
d62a17ae 1003 if (debug)
1004 zlog_debug(
1005 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1006 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1007 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1008 return 1;
1009 peer_sort_ret = 1;
d62a17ae 1010 }
718e3744 1011
d62a17ae 1012 if (exist_sort == BGP_PEER_EBGP
1013 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1014 *reason = bgp_path_selection_peer;
d62a17ae 1015 if (debug)
1016 zlog_debug(
1017 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1018 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1019 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1020 return 0;
1021 peer_sort_ret = 0;
d62a17ae 1022 }
8ff56318 1023
d62a17ae 1024 /* 8. IGP metric check. */
1025 newm = existm = 0;
8ff56318 1026
d62a17ae 1027 if (new->extra)
1028 newm = new->extra->igpmetric;
1029 if (exist->extra)
1030 existm = exist->extra->igpmetric;
9fbdd100 1031
d62a17ae 1032 if (newm < existm) {
ee88563a 1033 if (debug && peer_sort_ret < 0)
d62a17ae 1034 zlog_debug(
d588b995 1035 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1036 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1037 igp_metric_ret = 1;
d62a17ae 1038 }
718e3744 1039
d62a17ae 1040 if (newm > existm) {
ee88563a 1041 if (debug && peer_sort_ret < 0)
d62a17ae 1042 zlog_debug(
d588b995 1043 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1044 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1045 igp_metric_ret = 0;
5e242b0d 1046 }
5e242b0d 1047
d62a17ae 1048 /* 9. Same IGP metric. Compare the cluster list length as
1049 representative of IGP hops metric. Rewrite the metric value
1050 pair (newm, existm) with the cluster list length. Prefer the
1051 path with smaller cluster list length. */
1052 if (newm == existm) {
bf0d28dc
DS
1053 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1054 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1055 && (mpath_cfg == NULL
1056 || CHECK_FLAG(
1057 mpath_cfg->ibgp_flags,
1058 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1059 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1060 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1061
1062 if (newm < existm) {
ee88563a 1063 if (debug && peer_sort_ret < 0)
d62a17ae 1064 zlog_debug(
d588b995 1065 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1066 pfx_buf, new_buf, exist_buf,
1067 newm, existm);
ee88563a 1068 igp_metric_ret = 1;
d62a17ae 1069 }
1070
1071 if (newm > existm) {
ee88563a 1072 if (debug && peer_sort_ret < 0)
d62a17ae 1073 zlog_debug(
d588b995 1074 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1075 pfx_buf, new_buf, exist_buf,
1076 newm, existm);
ee88563a 1077 igp_metric_ret = 0;
d62a17ae 1078 }
1079 }
1080 }
31a4638f 1081
d62a17ae 1082 /* 10. confed-external vs. confed-internal */
1083 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1084 if (new_sort == BGP_PEER_CONFED
1085 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1086 *reason = bgp_path_selection_confed;
d62a17ae 1087 if (debug)
1088 zlog_debug(
1089 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1090 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1091 if (!CHECK_FLAG(bgp->flags,
1092 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1093 return 1;
1094 peer_sort_ret = 1;
d62a17ae 1095 }
718e3744 1096
d62a17ae 1097 if (exist_sort == BGP_PEER_CONFED
1098 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1099 *reason = bgp_path_selection_confed;
d62a17ae 1100 if (debug)
1101 zlog_debug(
1102 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1103 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1104 if (!CHECK_FLAG(bgp->flags,
1105 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1106 return 0;
1107 peer_sort_ret = 0;
d62a17ae 1108 }
1109 }
718e3744 1110
d62a17ae 1111 /* 11. Maximum path check. */
1112 if (newm == existm) {
1113 /* If one path has a label but the other does not, do not treat
1114 * them as equals for multipath
1115 */
a4d82a8a 1116 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1117 != (exist->extra
b57ba6d2 1118 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1119 if (debug)
1120 zlog_debug(
1121 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1122 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1123 } else if (CHECK_FLAG(bgp->flags,
1124 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1125
1126 /*
1127 * For the two paths, all comparison steps till IGP
1128 * metric
1129 * have succeeded - including AS_PATH hop count. Since
1130 * 'bgp
1131 * bestpath as-path multipath-relax' knob is on, we
1132 * don't need
1133 * an exact match of AS_PATH. Thus, mark the paths are
1134 * equal.
1135 * That will trigger both these paths to get into the
1136 * multipath
1137 * array.
1138 */
1139 *paths_eq = 1;
1140
1141 if (debug)
1142 zlog_debug(
1143 "%s: %s and %s are equal via multipath-relax",
1144 pfx_buf, new_buf, exist_buf);
1145 } else if (new->peer->sort == BGP_PEER_IBGP) {
1146 if (aspath_cmp(new->attr->aspath,
1147 exist->attr->aspath)) {
1148 *paths_eq = 1;
1149
1150 if (debug)
1151 zlog_debug(
1152 "%s: %s and %s are equal via matching aspaths",
1153 pfx_buf, new_buf, exist_buf);
1154 }
1155 } else if (new->peer->as == exist->peer->as) {
1156 *paths_eq = 1;
1157
1158 if (debug)
1159 zlog_debug(
1160 "%s: %s and %s are equal via same remote-as",
1161 pfx_buf, new_buf, exist_buf);
1162 }
1163 } else {
1164 /*
1165 * TODO: If unequal cost ibgp multipath is enabled we can
1166 * mark the paths as equal here instead of returning
1167 */
ee88563a
JM
1168
1169 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1170 * if either step 7 or 10 (peer type checks) yielded a winner,
1171 * that result was returned immediately. Returning from step 10
1172 * ignored the return value computed in steps 8 and 9 (IGP
1173 * metric checks). In order to preserve that behavior, if
1174 * peer_sort_ret is set, return that rather than igp_metric_ret.
1175 */
1176 ret = peer_sort_ret;
1177 if (peer_sort_ret < 0) {
1178 ret = igp_metric_ret;
1179 if (debug) {
1180 if (ret == 1)
1181 zlog_debug(
1182 "%s: %s wins over %s after IGP metric comparison",
1183 pfx_buf, new_buf, exist_buf);
1184 else
1185 zlog_debug(
1186 "%s: %s loses to %s after IGP metric comparison",
1187 pfx_buf, new_buf, exist_buf);
1188 }
1189 *reason = bgp_path_selection_igp_metric;
d62a17ae 1190 }
1191 return ret;
1192 }
718e3744 1193
ee88563a
JM
1194 /*
1195 * At this point, the decision whether to set *paths_eq = 1 has been
1196 * completed. If we deferred returning because of bestpath peer-type
1197 * relax configuration, return now.
1198 */
1199 if (peer_sort_ret >= 0)
1200 return peer_sort_ret;
1201
d62a17ae 1202 /* 12. If both paths are external, prefer the path that was received
1203 first (the oldest one). This step minimizes route-flap, since a
1204 newer path won't displace an older one, even if it was the
1205 preferred route based on the additional decision criteria below. */
892fedb6 1206 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1207 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1208 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1209 *reason = bgp_path_selection_older;
d62a17ae 1210 if (debug)
1211 zlog_debug(
1212 "%s: %s wins over %s due to oldest external",
1213 pfx_buf, new_buf, exist_buf);
1214 return 1;
1215 }
9fbdd100 1216
1defdda8 1217 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1218 *reason = bgp_path_selection_older;
d62a17ae 1219 if (debug)
1220 zlog_debug(
1221 "%s: %s loses to %s due to oldest external",
1222 pfx_buf, new_buf, exist_buf);
1223 return 0;
1224 }
1225 }
718e3744 1226
d62a17ae 1227 /* 13. Router-ID comparision. */
1228 /* If one of the paths is "stale", the corresponding peer router-id will
1229 * be 0 and would always win over the other path. If originator id is
1230 * used for the comparision, it will decide which path is better.
1231 */
1232 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1233 new_id.s_addr = newattr->originator_id.s_addr;
1234 else
1235 new_id.s_addr = new->peer->remote_id.s_addr;
1236 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1237 exist_id.s_addr = existattr->originator_id.s_addr;
1238 else
1239 exist_id.s_addr = exist->peer->remote_id.s_addr;
1240
1241 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1242 *reason = bgp_path_selection_router_id;
d62a17ae 1243 if (debug)
1244 zlog_debug(
1245 "%s: %s wins over %s due to Router-ID comparison",
1246 pfx_buf, new_buf, exist_buf);
1247 return 1;
1248 }
718e3744 1249
d62a17ae 1250 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1251 *reason = bgp_path_selection_router_id;
d62a17ae 1252 if (debug)
1253 zlog_debug(
1254 "%s: %s loses to %s due to Router-ID comparison",
1255 pfx_buf, new_buf, exist_buf);
1256 return 0;
1257 }
9fbdd100 1258
d62a17ae 1259 /* 14. Cluster length comparision. */
1260 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1261 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1262
1263 if (new_cluster < exist_cluster) {
fdf81fa0 1264 *reason = bgp_path_selection_cluster_length;
d62a17ae 1265 if (debug)
1266 zlog_debug(
1267 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1268 pfx_buf, new_buf, exist_buf, new_cluster,
1269 exist_cluster);
1270 return 1;
1271 }
718e3744 1272
d62a17ae 1273 if (new_cluster > exist_cluster) {
fdf81fa0 1274 *reason = bgp_path_selection_cluster_length;
d62a17ae 1275 if (debug)
1276 zlog_debug(
1277 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1278 pfx_buf, new_buf, exist_buf, new_cluster,
1279 exist_cluster);
1280 return 0;
1281 }
9fbdd100 1282
d62a17ae 1283 /* 15. Neighbor address comparision. */
1284 /* Do this only if neither path is "stale" as stale paths do not have
1285 * valid peer information (as the connection may or may not be up).
1286 */
1defdda8 1287 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1288 *reason = bgp_path_selection_stale;
d62a17ae 1289 if (debug)
1290 zlog_debug(
1291 "%s: %s wins over %s due to latter path being STALE",
1292 pfx_buf, new_buf, exist_buf);
1293 return 1;
1294 }
0de5153c 1295
1defdda8 1296 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1297 *reason = bgp_path_selection_stale;
d62a17ae 1298 if (debug)
1299 zlog_debug(
1300 "%s: %s loses to %s due to former path being STALE",
1301 pfx_buf, new_buf, exist_buf);
1302 return 0;
1303 }
718e3744 1304
d62a17ae 1305 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1306 if (new->peer->su_remote == NULL) {
1307 *reason = bgp_path_selection_local_configured;
d62a17ae 1308 return 0;
fdf81fa0
DS
1309 }
1310 if (exist->peer->su_remote == NULL) {
1311 *reason = bgp_path_selection_local_configured;
d62a17ae 1312 return 1;
fdf81fa0 1313 }
9fbdd100 1314
d62a17ae 1315 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1316
1317 if (ret == 1) {
fdf81fa0 1318 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1319 if (debug)
1320 zlog_debug(
1321 "%s: %s loses to %s due to Neighor IP comparison",
1322 pfx_buf, new_buf, exist_buf);
1323 return 0;
1324 }
1325
1326 if (ret == -1) {
fdf81fa0 1327 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1328 if (debug)
1329 zlog_debug(
1330 "%s: %s wins over %s due to Neighor IP comparison",
1331 pfx_buf, new_buf, exist_buf);
1332 return 1;
1333 }
9fbdd100 1334
fdf81fa0 1335 *reason = bgp_path_selection_default;
d62a17ae 1336 if (debug)
1337 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1338 pfx_buf, new_buf, exist_buf);
718e3744 1339
d62a17ae 1340 return 1;
718e3744 1341}
1342
d071f237
AK
1343
1344int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1345 struct bgp_path_info *exist, int *paths_eq)
1346{
1347 enum bgp_path_selection_reason reason;
1348 char pfx_buf[PREFIX2STR_BUFFER];
1349
1350 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1351 AFI_L2VPN, SAFI_EVPN, &reason);
1352}
1353
65efcfce
LB
1354/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1355 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1356 * multipath is enabled
65efcfce 1357 * This version is compatible with */
18ee8310
DS
1358int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1359 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1360 afi_t afi, safi_t safi,
1361 enum bgp_path_selection_reason *reason)
d62a17ae 1362{
1363 int paths_eq;
1364 int ret;
18ee8310 1365 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1366 afi, safi, reason);
d62a17ae 1367
1368 if (paths_eq)
1369 ret = 0;
1370 else {
1371 if (ret == 1)
1372 ret = -1;
1373 else
1374 ret = 1;
1375 }
1376 return ret;
65efcfce
LB
1377}
1378
5a1ae2c2
DS
1379static enum filter_type bgp_input_filter(struct peer *peer,
1380 const struct prefix *p,
d62a17ae 1381 struct attr *attr, afi_t afi,
1382 safi_t safi)
718e3744 1383{
d62a17ae 1384 struct bgp_filter *filter;
6401252f 1385 enum filter_type ret = FILTER_PERMIT;
718e3744 1386
d62a17ae 1387 filter = &peer->filter[afi][safi];
718e3744 1388
d62a17ae 1389#define FILTER_EXIST_WARN(F, f, filter) \
1390 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1391 zlog_debug("%s: Could not find configured input %s-list %s!", \
1392 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1393
1394 if (DISTRIBUTE_IN_NAME(filter)) {
1395 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1396
6401252f
QY
1397 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1398 == FILTER_DENY) {
1399 ret = FILTER_DENY;
1400 goto done;
1401 }
d62a17ae 1402 }
1403
1404 if (PREFIX_LIST_IN_NAME(filter)) {
1405 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1406
6401252f
QY
1407 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1408 == PREFIX_DENY) {
1409 ret = FILTER_DENY;
1410 goto done;
1411 }
d62a17ae 1412 }
1413
1414 if (FILTER_LIST_IN_NAME(filter)) {
1415 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1416
1417 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1418 == AS_FILTER_DENY) {
1419 ret = FILTER_DENY;
1420 goto done;
1421 }
d62a17ae 1422 }
1423
6401252f 1424done:
c7bb4f00 1425 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1426 char pfxprint[PREFIX2STR_BUFFER];
1427
1428 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1429 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1430 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1431 }
1432
1433 return ret;
650f76c2 1434#undef FILTER_EXIST_WARN
718e3744 1435}
1436
b8685f9b
DS
1437static enum filter_type bgp_output_filter(struct peer *peer,
1438 const struct prefix *p,
d62a17ae 1439 struct attr *attr, afi_t afi,
1440 safi_t safi)
718e3744 1441{
d62a17ae 1442 struct bgp_filter *filter;
6401252f 1443 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1444
1445 filter = &peer->filter[afi][safi];
1446
1447#define FILTER_EXIST_WARN(F, f, filter) \
1448 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1449 zlog_debug("%s: Could not find configured output %s-list %s!", \
1450 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1451
d62a17ae 1452 if (DISTRIBUTE_OUT_NAME(filter)) {
1453 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1454
6401252f
QY
1455 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1456 == FILTER_DENY) {
1457 ret = FILTER_DENY;
1458 goto done;
1459 }
d62a17ae 1460 }
1461
1462 if (PREFIX_LIST_OUT_NAME(filter)) {
1463 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1464
d62a17ae 1465 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1466 == PREFIX_DENY) {
1467 ret = FILTER_DENY;
1468 goto done;
1469 }
d62a17ae 1470 }
718e3744 1471
d62a17ae 1472 if (FILTER_LIST_OUT_NAME(filter)) {
1473 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1474
d62a17ae 1475 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1476 == AS_FILTER_DENY) {
1477 ret = FILTER_DENY;
1478 goto done;
1479 }
1480 }
1481
c7bb4f00 1482 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1483 char pfxprint[PREFIX2STR_BUFFER];
1484
1485 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1486 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1487 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1488 }
718e3744 1489
6401252f
QY
1490done:
1491 return ret;
650f76c2 1492#undef FILTER_EXIST_WARN
718e3744 1493}
1494
1495/* If community attribute includes no_export then return 1. */
3dc339cd 1496static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1497{
1498 if (attr->community) {
1499 /* NO_ADVERTISE check. */
1500 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1501 return true;
d62a17ae 1502
1503 /* NO_EXPORT check. */
1504 if (peer->sort == BGP_PEER_EBGP
1505 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1506 return true;
d62a17ae 1507
1508 /* NO_EXPORT_SUBCONFED check. */
1509 if (peer->sort == BGP_PEER_EBGP
1510 || peer->sort == BGP_PEER_CONFED)
1511 if (community_include(attr->community,
1512 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1513 return true;
d62a17ae 1514 }
3dc339cd 1515 return false;
718e3744 1516}
1517
1518/* Route reflection loop check. */
3dc339cd 1519static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1520{
d62a17ae 1521 struct in_addr cluster_id;
779fee93 1522 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1523
779fee93 1524 if (cluster) {
d62a17ae 1525 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1526 cluster_id = peer->bgp->cluster_id;
1527 else
1528 cluster_id = peer->bgp->router_id;
1529
779fee93 1530 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1531 return true;
d62a17ae 1532 }
3dc339cd 1533 return false;
718e3744 1534}
6b0655a2 1535
5a1ae2c2 1536static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1537 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1538 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1539 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1540{
d62a17ae 1541 struct bgp_filter *filter;
82b692c0
LK
1542 struct bgp_path_info rmap_path = { 0 };
1543 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1544 route_map_result_t ret;
1545 struct route_map *rmap = NULL;
718e3744 1546
d62a17ae 1547 filter = &peer->filter[afi][safi];
718e3744 1548
d62a17ae 1549 /* Apply default weight value. */
1550 if (peer->weight[afi][safi])
1551 attr->weight = peer->weight[afi][safi];
718e3744 1552
d62a17ae 1553 if (rmap_name) {
1554 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1555
d62a17ae 1556 if (rmap == NULL)
1557 return RMAP_DENY;
1558 } else {
1559 if (ROUTE_MAP_IN_NAME(filter)) {
1560 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1561
d62a17ae 1562 if (rmap == NULL)
1563 return RMAP_DENY;
1564 }
1565 }
0b16f239 1566
d62a17ae 1567 /* Route map apply. */
1568 if (rmap) {
40381db7 1569 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1570 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1571 rmap_path.peer = peer;
1572 rmap_path.attr = attr;
82b692c0 1573 rmap_path.extra = &extra;
9bcb3eef 1574 rmap_path.net = dest;
196c6b09 1575
82b692c0
LK
1576 extra.num_labels = num_labels;
1577 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1578 memcpy(extra.label, label,
1579 num_labels * sizeof(mpls_label_t));
718e3744 1580
d62a17ae 1581 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1582
d62a17ae 1583 /* Apply BGP route map to the attribute. */
1782514f 1584 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1585
d62a17ae 1586 peer->rmap_type = 0;
0b16f239 1587
1f2263be 1588 if (ret == RMAP_DENYMATCH)
d62a17ae 1589 return RMAP_DENY;
0b16f239 1590 }
d62a17ae 1591 return RMAP_PERMIT;
0b16f239
DS
1592}
1593
5f040085 1594static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1595 struct attr *attr, afi_t afi, safi_t safi,
1596 const char *rmap_name)
0b16f239 1597{
40381db7 1598 struct bgp_path_info rmap_path;
d62a17ae 1599 route_map_result_t ret;
1600 struct route_map *rmap = NULL;
d7c0a89a 1601 uint8_t rmap_type;
0b16f239 1602
b787157a
DS
1603 /*
1604 * So if we get to this point and have no rmap_name
1605 * we want to just show the output as it currently
1606 * exists.
1607 */
1608 if (!rmap_name)
1609 return RMAP_PERMIT;
0b16f239 1610
d62a17ae 1611 /* Apply default weight value. */
1612 if (peer->weight[afi][safi])
1613 attr->weight = peer->weight[afi][safi];
0b16f239 1614
b787157a 1615 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1616
b787157a
DS
1617 /*
1618 * If we have a route map name and we do not find
1619 * the routemap that means we have an implicit
1620 * deny.
1621 */
1622 if (rmap == NULL)
1623 return RMAP_DENY;
0b16f239 1624
40381db7 1625 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1626 /* Route map apply. */
b787157a 1627 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1628 rmap_path.peer = peer;
1629 rmap_path.attr = attr;
0b16f239 1630
0f672529 1631 rmap_type = peer->rmap_type;
b787157a 1632 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1633
b787157a 1634 /* Apply BGP route map to the attribute. */
1782514f 1635 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1636
0f672529 1637 peer->rmap_type = rmap_type;
b787157a
DS
1638
1639 if (ret == RMAP_DENYMATCH)
1640 /*
1641 * caller has multiple error paths with bgp_attr_flush()
1642 */
1643 return RMAP_DENY;
ac41b2a2 1644
d62a17ae 1645 return RMAP_PERMIT;
718e3744 1646}
6b0655a2 1647
5000f21c 1648/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1649static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1650 struct peer *peer, struct attr *attr)
1651{
1652 if (peer->sort == BGP_PEER_EBGP
1653 && (peer_af_flag_check(peer, afi, safi,
1654 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1655 || peer_af_flag_check(peer, afi, safi,
1656 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1657 || peer_af_flag_check(peer, afi, safi,
1658 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1659 || peer_af_flag_check(peer, afi, safi,
1660 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1661 // Take action on the entire aspath
1662 if (peer_af_flag_check(peer, afi, safi,
1663 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1664 || peer_af_flag_check(peer, afi, safi,
1665 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1666 if (peer_af_flag_check(
1667 peer, afi, safi,
1668 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1669 attr->aspath = aspath_replace_private_asns(
bf26b80e 1670 attr->aspath, bgp->as, peer->as);
d62a17ae 1671
1672 // The entire aspath consists of private ASNs so create
1673 // an empty aspath
1674 else if (aspath_private_as_check(attr->aspath))
1675 attr->aspath = aspath_empty_get();
1676
1677 // There are some public and some private ASNs, remove
1678 // the private ASNs
1679 else
1680 attr->aspath = aspath_remove_private_asns(
bf26b80e 1681 attr->aspath, peer->as);
d62a17ae 1682 }
1683
1684 // 'all' was not specified so the entire aspath must be private
1685 // ASNs
1686 // for us to do anything
1687 else if (aspath_private_as_check(attr->aspath)) {
1688 if (peer_af_flag_check(
1689 peer, afi, safi,
1690 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1691 attr->aspath = aspath_replace_private_asns(
bf26b80e 1692 attr->aspath, bgp->as, peer->as);
d62a17ae 1693 else
1694 attr->aspath = aspath_empty_get();
1695 }
1696 }
5000f21c
DS
1697}
1698
c7122e14 1699/* If this is an EBGP peer with as-override */
d62a17ae 1700static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1701 struct peer *peer, struct attr *attr)
1702{
1703 if (peer->sort == BGP_PEER_EBGP
1704 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1705 if (aspath_single_asn_check(attr->aspath, peer->as))
1706 attr->aspath = aspath_replace_specific_asn(
1707 attr->aspath, peer->as, bgp->as);
1708 }
1709}
1710
7f323236
DW
1711void bgp_attr_add_gshut_community(struct attr *attr)
1712{
1713 struct community *old;
1714 struct community *new;
1715 struct community *merge;
1716 struct community *gshut;
1717
1718 old = attr->community;
1719 gshut = community_str2com("graceful-shutdown");
1720
990f4f91 1721 assert(gshut);
1722
7f323236
DW
1723 if (old) {
1724 merge = community_merge(community_dup(old), gshut);
1725
a4d82a8a 1726 if (old->refcnt == 0)
3c1f53de 1727 community_free(&old);
7f323236
DW
1728
1729 new = community_uniq_sort(merge);
3c1f53de 1730 community_free(&merge);
7f323236
DW
1731 } else {
1732 new = community_dup(gshut);
1733 }
1734
3c1f53de 1735 community_free(&gshut);
7f323236
DW
1736 attr->community = new;
1737 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1738
1739 /* When we add the graceful-shutdown community we must also
1740 * lower the local-preference */
1741 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1742 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1743}
1744
1745
e73c112e
MK
1746/* Notify BGP Conditional advertisement scanner process. */
1747void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1748{
1749 struct peer *temp_peer;
1750 struct peer *peer = SUBGRP_PEER(subgrp);
1751 struct listnode *temp_node, *temp_nnode = NULL;
1752 afi_t afi = SUBGRP_AFI(subgrp);
1753 safi_t safi = SUBGRP_SAFI(subgrp);
1754 struct bgp *bgp = SUBGRP_INST(subgrp);
1755 struct bgp_filter *filter = &peer->filter[afi][safi];
1756
1757 if (!ADVERTISE_MAP_NAME(filter))
1758 return;
1759
1760 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1761 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1762 continue;
1763
1764 if (peer != temp_peer)
1765 continue;
1766
1767 temp_peer->advmap_table_change = true;
1768 break;
1769 }
1770}
1771
1772
f2ee6d5c 1773void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1774{
960035b2 1775 if (family == AF_INET) {
975a328e
DA
1776 attr->nexthop.s_addr = INADDR_ANY;
1777 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1778 }
d62a17ae 1779 if (family == AF_INET6)
1780 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1781 if (family == AF_EVPN)
1782 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1783}
1784
9bcb3eef 1785bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1786 struct update_subgroup *subgrp,
7f7940e6
MK
1787 const struct prefix *p, struct attr *attr,
1788 bool skip_rmap_check)
d62a17ae 1789{
1790 struct bgp_filter *filter;
1791 struct peer *from;
1792 struct peer *peer;
1793 struct peer *onlypeer;
1794 struct bgp *bgp;
40381db7 1795 struct attr *piattr;
b68885f9 1796 route_map_result_t ret;
d62a17ae 1797 int transparent;
1798 int reflect;
1799 afi_t afi;
1800 safi_t safi;
1801 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1802 bool nh_reset = false;
1803 uint64_t cum_bw;
d62a17ae 1804
1805 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1806 return false;
d62a17ae 1807
1808 afi = SUBGRP_AFI(subgrp);
1809 safi = SUBGRP_SAFI(subgrp);
1810 peer = SUBGRP_PEER(subgrp);
1811 onlypeer = NULL;
1812 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1813 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1814
40381db7 1815 from = pi->peer;
d62a17ae 1816 filter = &peer->filter[afi][safi];
1817 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1818 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1819 : pi->attr;
3f9c7369 1820
49e5a4a0 1821#ifdef ENABLE_BGP_VNC
d62a17ae 1822 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1823 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1824 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1825
1826 /*
1827 * direct and direct_ext type routes originate internally even
1828 * though they can have peer pointers that reference other
1829 * systems
1830 */
8228a9a7
DS
1831 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1832 __func__, p);
d62a17ae 1833 samepeer_safe = 1;
1834 }
65efcfce
LB
1835#endif
1836
ddb5b488
PZ
1837 if (((afi == AFI_IP) || (afi == AFI_IP6))
1838 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1839 && (pi->type == ZEBRA_ROUTE_BGP)
1840 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1841
1842 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1843
1844 samepeer_safe = 1;
1845 }
1846
d62a17ae 1847 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1848 * pi is valid */
1849 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1850 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1851 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1852 return false;
d62a17ae 1853 }
adbac85e 1854
d62a17ae 1855 /* If this is not the bestpath then check to see if there is an enabled
1856 * addpath
1857 * feature that requires us to advertise it */
40381db7 1858 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1859 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1860 return false;
d62a17ae 1861 }
1862 }
06370dac 1863
d62a17ae 1864 /* Aggregate-address suppress check. */
4056a5f6
RZ
1865 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1866 return false;
3f9c7369 1867
13b7e7f0
DS
1868 /*
1869 * If we are doing VRF 2 VRF leaking via the import
1870 * statement, we want to prevent the route going
1871 * off box as that the RT and RD created are localy
1872 * significant and globaly useless.
1873 */
40381db7
DS
1874 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1875 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1876 return false;
13b7e7f0 1877
d62a17ae 1878 /* If it's labeled safi, make sure the route has a valid label. */
1879 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1880 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1881 if (!bgp_is_valid_label(&label)) {
1882 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1883 zlog_debug("u%" PRIu64 ":s%" PRIu64
1884 " %pFX is filtered - no label (%p)",
d62a17ae 1885 subgrp->update_group->id, subgrp->id,
8228a9a7 1886 p, &label);
3dc339cd 1887 return false;
d62a17ae 1888 }
1889 }
cd1964ff 1890
d62a17ae 1891 /* Do not send back route to sender. */
1892 if (onlypeer && from == onlypeer) {
3dc339cd 1893 return false;
d62a17ae 1894 }
3f9c7369 1895
d62a17ae 1896 /* Do not send the default route in the BGP table if the neighbor is
1897 * configured for default-originate */
1898 if (CHECK_FLAG(peer->af_flags[afi][safi],
1899 PEER_FLAG_DEFAULT_ORIGINATE)) {
1900 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1901 return false;
d62a17ae 1902 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1903 return false;
d62a17ae 1904 }
4125bb67 1905
d62a17ae 1906 /* Transparency check. */
1907 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1908 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1909 transparent = 1;
1910 else
1911 transparent = 0;
1912
1913 /* If community is not disabled check the no-export and local. */
40381db7 1914 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1915 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1916 zlog_debug("%s: community filter check fail for %pFX",
1917 __func__, p);
3dc339cd 1918 return false;
d62a17ae 1919 }
3f9c7369 1920
d62a17ae 1921 /* If the attribute has originator-id and it is same as remote
1922 peer's id. */
40381db7
DS
1923 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1924 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1925 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1926 zlog_debug(
8228a9a7
DS
1927 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1928 onlypeer->host, p);
3dc339cd 1929 return false;
d62a17ae 1930 }
3f9c7369 1931
d62a17ae 1932 /* ORF prefix-list filter check */
1933 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1934 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1935 || CHECK_FLAG(peer->af_cap[afi][safi],
1936 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1937 if (peer->orf_plist[afi][safi]) {
1938 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1939 == PREFIX_DENY) {
1940 if (bgp_debug_update(NULL, p,
1941 subgrp->update_group, 0))
1942 zlog_debug(
8228a9a7
DS
1943 "%s [Update:SEND] %pFX is filtered via ORF",
1944 peer->host, p);
3dc339cd 1945 return false;
d62a17ae 1946 }
1947 }
1948
1949 /* Output filter check. */
40381db7 1950 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1951 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1952 zlog_debug("%s [Update:SEND] %pFX is filtered",
1953 peer->host, p);
3dc339cd 1954 return false;
d62a17ae 1955 }
3f9c7369 1956
d62a17ae 1957 /* AS path loop check. */
2b31007c
RZ
1958 if (onlypeer && onlypeer->as_path_loop_detection
1959 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1960 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1961 zlog_debug(
3efd0893 1962 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1963 onlypeer->host, onlypeer->as);
3dc339cd 1964 return false;
d62a17ae 1965 }
3f9c7369 1966
d62a17ae 1967 /* If we're a CONFED we need to loop check the CONFED ID too */
1968 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1969 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1970 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1971 zlog_debug(
3efd0893 1972 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1973 peer->host, bgp->confed_id);
3dc339cd 1974 return false;
d62a17ae 1975 }
3f9c7369 1976 }
3f9c7369 1977
d62a17ae 1978 /* Route-Reflect check. */
1979 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1980 reflect = 1;
1981 else
1982 reflect = 0;
1983
1984 /* IBGP reflection check. */
1985 if (reflect && !samepeer_safe) {
1986 /* A route from a Client peer. */
1987 if (CHECK_FLAG(from->af_flags[afi][safi],
1988 PEER_FLAG_REFLECTOR_CLIENT)) {
1989 /* Reflect to all the Non-Client peers and also to the
1990 Client peers other than the originator. Originator
1991 check
1992 is already done. So there is noting to do. */
1993 /* no bgp client-to-client reflection check. */
892fedb6
DA
1994 if (CHECK_FLAG(bgp->flags,
1995 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1996 if (CHECK_FLAG(peer->af_flags[afi][safi],
1997 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1998 return false;
d62a17ae 1999 } else {
2000 /* A route from a Non-client peer. Reflect to all other
2001 clients. */
2002 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2003 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2004 return false;
d62a17ae 2005 }
2006 }
3f9c7369 2007
d62a17ae 2008 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 2009 *attr = *piattr;
d62a17ae 2010
2011 /* If local-preference is not set. */
2012 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2013 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2014 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2015 attr->local_pref = bgp->default_local_pref;
3f9c7369 2016 }
3f9c7369 2017
d62a17ae 2018 /* If originator-id is not set and the route is to be reflected,
2019 set the originator id */
2020 if (reflect
2021 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2022 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2023 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2024 }
3f9c7369 2025
d62a17ae 2026 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2027 */
2028 if (peer->sort == BGP_PEER_EBGP
2029 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2030 if (from != bgp->peer_self && !transparent
2031 && !CHECK_FLAG(peer->af_flags[afi][safi],
2032 PEER_FLAG_MED_UNCHANGED))
2033 attr->flag &=
2034 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2035 }
3f9c7369 2036
d62a17ae 2037 /* Since the nexthop attribute can vary per peer, it is not explicitly
2038 * set
2039 * in announce check, only certain flags and length (or number of
2040 * nexthops
2041 * -- for IPv6/MP_REACH) are set here in order to guide the update
2042 * formation
2043 * code in setting the nexthop(s) on a per peer basis in
2044 * reformat_peer().
2045 * Typically, the source nexthop in the attribute is preserved but in
2046 * the
2047 * scenarios where we know it will always be overwritten, we reset the
2048 * nexthop to "0" in an attempt to achieve better Update packing. An
2049 * example of this is when a prefix from each of 2 IBGP peers needs to
2050 * be
2051 * announced to an EBGP peer (and they have the same attributes barring
2052 * their nexthop).
2053 */
2054 if (reflect)
2055 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2056
2057#define NEXTHOP_IS_V6 \
2058 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2059 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2060 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2061 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2062
2063 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2064 * if
2065 * the peer (group) is configured to receive link-local nexthop
2066 * unchanged
c728d027
DA
2067 * and it is available in the prefix OR we're not reflecting the route,
2068 * link-local nexthop address is valid and
d62a17ae 2069 * the peer (group) to whom we're going to announce is on a shared
2070 * network
2071 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2072 * By checking if nexthop LL address is valid we are sure that
2073 * we do not announce LL address as `::`.
d62a17ae 2074 */
2075 if (NEXTHOP_IS_V6) {
2076 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2077 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2078 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2079 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2080 || (!reflect && !transparent
c728d027
DA
2081 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2082 && peer->shared_network
d62a17ae 2083 && (from == bgp->peer_self
2084 || peer->sort == BGP_PEER_EBGP))) {
2085 attr->mp_nexthop_len =
2086 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2087 }
3f9c7369 2088
d62a17ae 2089 /* Clear off link-local nexthop in source, whenever it is not
2090 * needed to
2091 * ensure more prefixes share the same attribute for
2092 * announcement.
2093 */
2094 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2095 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2096 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2097 }
3f9c7369 2098
d62a17ae 2099 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2100 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2101
2102 /* Route map & unsuppress-map apply. */
7f7940e6 2103 if (!skip_rmap_check
e73c112e 2104 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2105 struct bgp_path_info rmap_path = {0};
2106 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2107 struct attr dummy_attr = {0};
d62a17ae 2108
e34291b8 2109 /* Fill temp path_info */
9bcb3eef
DS
2110 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2111 pi, peer, attr);
16f7ce2b 2112
d62a17ae 2113 /* don't confuse inbound and outbound setting */
2114 RESET_FLAG(attr->rmap_change_flags);
2115
2116 /*
2117 * The route reflector is not allowed to modify the attributes
2118 * of the reflected IBGP routes unless explicitly allowed.
2119 */
2120 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2121 && !CHECK_FLAG(bgp->flags,
2122 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2123 dummy_attr = *attr;
40381db7 2124 rmap_path.attr = &dummy_attr;
d62a17ae 2125 }
3f9c7369 2126
d62a17ae 2127 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2128
4056a5f6 2129 if (bgp_path_suppressed(pi))
d62a17ae 2130 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2131 &rmap_path);
d62a17ae 2132 else
2133 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2134 &rmap_path);
d62a17ae 2135
2136 peer->rmap_type = 0;
2137
2138 if (ret == RMAP_DENYMATCH) {
778048bf 2139 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2140 zlog_debug(
2141 "%s [Update:SEND] %pFX is filtered by route-map",
2142 peer->host, p);
778048bf 2143
d62a17ae 2144 bgp_attr_flush(attr);
3dc339cd 2145 return false;
d62a17ae 2146 }
3f9c7369 2147 }
3f9c7369 2148
9dac9fc8
DA
2149 /* RFC 8212 to prevent route leaks.
2150 * This specification intends to improve this situation by requiring the
2151 * explicit configuration of both BGP Import and Export Policies for any
2152 * External BGP (EBGP) session such as customers, peers, or
2153 * confederation boundaries for all enabled address families. Through
2154 * codification of the aforementioned requirement, operators will
2155 * benefit from consistent behavior across different BGP
2156 * implementations.
2157 */
1d3fdccf 2158 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2159 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2160 return false;
9dac9fc8 2161
fb29348a
DA
2162 /* draft-ietf-idr-deprecate-as-set-confed-set
2163 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2164 * Eventually, This document (if approved) updates RFC 4271
2165 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2166 * and obsoletes RFC 6472.
2167 */
7f972cd8 2168 if (peer->bgp->reject_as_sets)
fb29348a 2169 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2170 return false;
fb29348a 2171
33d022bc
DA
2172 /* Codification of AS 0 Processing */
2173 if (aspath_check_as_zero(attr->aspath))
e2369003 2174 return false;
33d022bc 2175
637e5ba4 2176 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2177 if (peer->sort == BGP_PEER_IBGP
2178 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2179 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2180 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2181 } else {
2182 bgp_attr_add_gshut_community(attr);
2183 }
2184 }
2185
d62a17ae 2186 /* After route-map has been applied, we check to see if the nexthop to
2187 * be carried in the attribute (that is used for the announcement) can
2188 * be cleared off or not. We do this in all cases where we would be
2189 * setting the nexthop to "ourselves". For IPv6, we only need to
2190 * consider
2191 * the global nexthop here; the link-local nexthop would have been
2192 * cleared
2193 * already, and if not, it is required by the update formation code.
2194 * Also see earlier comments in this function.
2195 */
2196 /*
2197 * If route-map has performed some operation on the nexthop or the peer
2198 * configuration says to pass it unchanged, we cannot reset the nexthop
2199 * here, so only attempt to do it if these aren't true. Note that the
2200 * route-map handler itself might have cleared the nexthop, if for
2201 * example,
2202 * it is configured as 'peer-address'.
2203 */
2204 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2205 piattr->rmap_change_flags)
d62a17ae 2206 && !transparent
2207 && !CHECK_FLAG(peer->af_flags[afi][safi],
2208 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2209 /* We can reset the nexthop, if setting (or forcing) it to
2210 * 'self' */
2211 if (CHECK_FLAG(peer->af_flags[afi][safi],
2212 PEER_FLAG_NEXTHOP_SELF)
2213 || CHECK_FLAG(peer->af_flags[afi][safi],
2214 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2215 if (!reflect
2216 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2217 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2218 subgroup_announce_reset_nhop(
2219 (peer_cap_enhe(peer, afi, safi)
2220 ? AF_INET6
2221 : p->family),
2222 attr);
7b651a32 2223 nh_reset = true;
2224 }
d62a17ae 2225 } else if (peer->sort == BGP_PEER_EBGP) {
2226 /* Can also reset the nexthop if announcing to EBGP, but
2227 * only if
2228 * no peer in the subgroup is on a shared subnet.
2229 * Note: 3rd party nexthop currently implemented for
2230 * IPv4 only.
2231 */
737af885
BS
2232 if ((p->family == AF_INET) &&
2233 (!bgp_subgrp_multiaccess_check_v4(
2234 piattr->nexthop,
7b651a32 2235 subgrp, from))) {
d62a17ae 2236 subgroup_announce_reset_nhop(
2237 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2238 ? AF_INET6
2239 : p->family),
737af885 2240 attr);
7b651a32 2241 nh_reset = true;
2242 }
737af885
BS
2243
2244 if ((p->family == AF_INET6) &&
2245 (!bgp_subgrp_multiaccess_check_v6(
2246 piattr->mp_nexthop_global,
7b651a32 2247 subgrp, from))) {
737af885
BS
2248 subgroup_announce_reset_nhop(
2249 (peer_cap_enhe(peer, afi, safi)
2250 ? AF_INET6
2251 : p->family),
2252 attr);
7b651a32 2253 nh_reset = true;
2254 }
737af885
BS
2255
2256
2257
40381db7 2258 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2259 /*
2260 * This flag is used for leaked vpn-vrf routes
2261 */
2262 int family = p->family;
2263
2264 if (peer_cap_enhe(peer, afi, safi))
2265 family = AF_INET6;
2266
2267 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2268 zlog_debug(
1defdda8 2269 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2270 __func__, family2str(family));
2271 subgroup_announce_reset_nhop(family, attr);
7b651a32 2272 nh_reset = true;
d62a17ae 2273 }
63696f1d 2274 }
960035b2 2275
63696f1d 2276 /* If IPv6/MP and nexthop does not have any override and happens
2277 * to
2278 * be a link-local address, reset it so that we don't pass along
2279 * the
2280 * source's link-local IPv6 address to recipients who may not be
2281 * on
2282 * the same interface.
2283 */
2284 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2285 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2286 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2287 nh_reset = true;
2288 }
d62a17ae 2289 }
3f9c7369 2290
7b651a32 2291 /*
2292 * When the next hop is set to ourselves, if all multipaths have
2293 * link-bandwidth announce the cumulative bandwidth as that makes
2294 * the most sense. However, don't modify if the link-bandwidth has
2295 * been explicitly set by user policy.
2296 */
2297 if (nh_reset &&
f7e1c681 2298 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2299 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2300 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2301 attr->ecommunity = ecommunity_replace_linkbw(
27aa23a4
DA
2302 bgp->as, attr->ecommunity, cum_bw,
2303 CHECK_FLAG(peer->flags,
2304 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
7b651a32 2305
3dc339cd 2306 return true;
3f9c7369
DS
2307}
2308
f009ff26 2309static int bgp_route_select_timer_expire(struct thread *thread)
2310{
2311 struct afi_safi_info *info;
2312 afi_t afi;
2313 safi_t safi;
2314 struct bgp *bgp;
2315
2316 info = THREAD_ARG(thread);
2317 afi = info->afi;
2318 safi = info->safi;
2319 bgp = info->bgp;
2320
2321 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2322 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2323 safi);
f009ff26 2324
2325 bgp->gr_info[afi][safi].t_route_select = NULL;
2326
2327 XFREE(MTYPE_TMP, info);
2328
2329 /* Best path selection */
2330 return bgp_best_path_select_defer(bgp, afi, safi);
2331}
2332
9bcb3eef 2333void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2334 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2335 struct bgp_path_info_pair *result, afi_t afi,
2336 safi_t safi)
2337{
2338 struct bgp_path_info *new_select;
2339 struct bgp_path_info *old_select;
40381db7
DS
2340 struct bgp_path_info *pi;
2341 struct bgp_path_info *pi1;
2342 struct bgp_path_info *pi2;
2343 struct bgp_path_info *nextpi = NULL;
d62a17ae 2344 int paths_eq, do_mpath, debug;
2345 struct list mp_list;
2346 char pfx_buf[PREFIX2STR_BUFFER];
2347 char path_buf[PATH_ADDPATH_STR_BUFFER];
2348
2349 bgp_mp_list_init(&mp_list);
2350 do_mpath =
2351 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2352
9bcb3eef 2353 debug = bgp_debug_bestpath(dest);
d62a17ae 2354
2355 if (debug)
9bcb3eef 2356 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2357
9bcb3eef 2358 dest->reason = bgp_path_selection_none;
d62a17ae 2359 /* bgp deterministic-med */
2360 new_select = NULL;
892fedb6 2361 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2362
1defdda8 2363 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2364 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2365 pi1 = pi1->next)
9bcb3eef 2366 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2367 BGP_PATH_DMED_SELECTED);
d62a17ae 2368
9bcb3eef 2369 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2370 pi1 = pi1->next) {
40381db7 2371 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2372 continue;
40381db7 2373 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2374 continue;
ea8b2282 2375 if (pi1->peer != bgp->peer_self)
feb17238 2376 if (!peer_established(pi1->peer))
d62a17ae 2377 continue;
2378
40381db7
DS
2379 new_select = pi1;
2380 if (pi1->next) {
2381 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2382 if (CHECK_FLAG(pi2->flags,
1defdda8 2383 BGP_PATH_DMED_CHECK))
d62a17ae 2384 continue;
40381db7 2385 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2386 continue;
ea8b2282 2387 if (pi2->peer != bgp->peer_self
d62a17ae 2388 && !CHECK_FLAG(
ea8b2282
DS
2389 pi2->peer->sflags,
2390 PEER_STATUS_NSF_WAIT))
40381db7 2391 if (pi2->peer->status
d62a17ae 2392 != Established)
2393 continue;
2394
121e245d
DS
2395 if (!aspath_cmp_left(pi1->attr->aspath,
2396 pi2->attr->aspath)
2397 && !aspath_cmp_left_confed(
40381db7 2398 pi1->attr->aspath,
121e245d
DS
2399 pi2->attr->aspath))
2400 continue;
d62a17ae 2401
121e245d
DS
2402 if (bgp_path_info_cmp(
2403 bgp, pi2, new_select,
2404 &paths_eq, mpath_cfg, debug,
fdf81fa0 2405 pfx_buf, afi, safi,
9bcb3eef 2406 &dest->reason)) {
121e245d 2407 bgp_path_info_unset_flag(
9bcb3eef 2408 dest, new_select,
121e245d
DS
2409 BGP_PATH_DMED_SELECTED);
2410 new_select = pi2;
d62a17ae 2411 }
121e245d
DS
2412
2413 bgp_path_info_set_flag(
9bcb3eef 2414 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2415 }
2416 }
9bcb3eef 2417 bgp_path_info_set_flag(dest, new_select,
18ee8310 2418 BGP_PATH_DMED_CHECK);
9bcb3eef 2419 bgp_path_info_set_flag(dest, new_select,
18ee8310 2420 BGP_PATH_DMED_SELECTED);
d62a17ae 2421
2422 if (debug) {
18ee8310 2423 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2424 new_select, path_buf, sizeof(path_buf));
8228a9a7 2425 zlog_debug(
4378495a
DS
2426 "%pBD(%s): %s is the bestpath from AS %u",
2427 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2428 aspath_get_first_as(
2429 new_select->attr->aspath));
d62a17ae 2430 }
2431 }
2432 }
96450faf 2433
d62a17ae 2434 /* Check old selected route and new selected route. */
2435 old_select = NULL;
2436 new_select = NULL;
9bcb3eef 2437 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2438 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2439 enum bgp_path_selection_reason reason;
2440
40381db7
DS
2441 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2442 old_select = pi;
d62a17ae 2443
40381db7 2444 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2445 /* reap REMOVED routes, if needs be
2446 * selected route must stay for a while longer though
2447 */
40381db7
DS
2448 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2449 && (pi != old_select))
9bcb3eef 2450 bgp_path_info_reap(dest, pi);
d62a17ae 2451
ddb5b488 2452 if (debug)
40381db7
DS
2453 zlog_debug("%s: pi %p in holddown", __func__,
2454 pi);
ddb5b488 2455
d62a17ae 2456 continue;
2457 }
96450faf 2458
40381db7
DS
2459 if (pi->peer && pi->peer != bgp->peer_self
2460 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2461 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2462
2463 if (debug)
2464 zlog_debug(
40381db7
DS
2465 "%s: pi %p non self peer %s not estab state",
2466 __func__, pi, pi->peer->host);
ddb5b488 2467
d62a17ae 2468 continue;
ddb5b488 2469 }
9fbdd100 2470
892fedb6 2471 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2472 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2473 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2474 if (debug)
40381db7 2475 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2476 continue;
2477 }
9fbdd100 2478
9bcb3eef 2479 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2480
9bcb3eef 2481 reason = dest->reason;
40381db7 2482 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2483 debug, pfx_buf, afi, safi,
2484 &dest->reason)) {
19ea4cec
DS
2485 if (new_select == NULL &&
2486 reason != bgp_path_selection_none)
9bcb3eef 2487 dest->reason = reason;
40381db7 2488 new_select = pi;
d62a17ae 2489 }
2490 }
718e3744 2491
d62a17ae 2492 /* Now that we know which path is the bestpath see if any of the other
2493 * paths
2494 * qualify as multipaths
2495 */
2496 if (debug) {
2497 if (new_select)
7533cad7
QY
2498 bgp_path_info_path_with_addpath_rx_str(
2499 new_select, path_buf, sizeof(path_buf));
d62a17ae 2500 else
772270f3 2501 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2502 zlog_debug(
4378495a
DS
2503 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2504 dest, bgp->name_pretty, path_buf,
d62a17ae 2505 old_select ? old_select->peer->host : "NONE");
96450faf 2506 }
9fbdd100 2507
d62a17ae 2508 if (do_mpath && new_select) {
9bcb3eef 2509 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2510 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2511
2512 if (debug)
18ee8310 2513 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2514 pi, path_buf, sizeof(path_buf));
d62a17ae 2515
40381db7 2516 if (pi == new_select) {
d62a17ae 2517 if (debug)
2518 zlog_debug(
4378495a
DS
2519 "%pBD(%s): %s is the bestpath, add to the multipath list",
2520 dest, bgp->name_pretty,
2521 path_buf);
40381db7 2522 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2523 continue;
2524 }
2525
40381db7 2526 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2527 continue;
2528
40381db7
DS
2529 if (pi->peer && pi->peer != bgp->peer_self
2530 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2531 PEER_STATUS_NSF_WAIT))
feb17238 2532 if (!peer_established(pi->peer))
d62a17ae 2533 continue;
2534
40381db7 2535 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2536 if (debug)
2537 zlog_debug(
8228a9a7
DS
2538 "%pBD: %s has the same nexthop as the bestpath, skip it",
2539 dest, path_buf);
d62a17ae 2540 continue;
2541 }
2542
40381db7 2543 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2544 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2545 &dest->reason);
d62a17ae 2546
2547 if (paths_eq) {
2548 if (debug)
2549 zlog_debug(
8228a9a7
DS
2550 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2551 dest, path_buf);
40381db7 2552 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2553 }
2554 }
2555 }
fee0f4c6 2556
4378495a 2557 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2558 mpath_cfg);
2559 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2560 bgp_mp_list_clear(&mp_list);
96450faf 2561
9bcb3eef 2562 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2563
d62a17ae 2564 result->old = old_select;
2565 result->new = new_select;
96450faf 2566
d62a17ae 2567 return;
fee0f4c6 2568}
2569
3f9c7369
DS
2570/*
2571 * A new route/change in bestpath of an existing route. Evaluate the path
2572 * for advertisement to the subgroup.
2573 */
3dc339cd
DA
2574void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2575 struct bgp_path_info *selected,
9bcb3eef 2576 struct bgp_dest *dest,
3dc339cd 2577 uint32_t addpath_tx_id)
d62a17ae 2578{
b54892e0 2579 const struct prefix *p;
d62a17ae 2580 struct peer *onlypeer;
2581 struct attr attr;
2582 afi_t afi;
2583 safi_t safi;
a77e2f4b
S
2584 struct bgp *bgp;
2585 bool advertise;
adbac85e 2586
9bcb3eef 2587 p = bgp_dest_get_prefix(dest);
d62a17ae 2588 afi = SUBGRP_AFI(subgrp);
2589 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2590 bgp = SUBGRP_INST(subgrp);
d62a17ae 2591 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2592 : NULL);
2593
2dbe669b
DA
2594 if (BGP_DEBUG(update, UPDATE_OUT))
2595 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2596
d62a17ae 2597 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2598 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2599 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2600 return;
d62a17ae 2601
2602 memset(&attr, 0, sizeof(struct attr));
2603 /* It's initialized in bgp_announce_check() */
2604
a77e2f4b
S
2605 /* Announcement to the subgroup. If the route is filtered withdraw it.
2606 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2607 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2608 * route
d62a17ae 2609 */
a77e2f4b
S
2610 advertise = bgp_check_advertise(bgp, dest);
2611
d62a17ae 2612 if (selected) {
7f7940e6 2613 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2614 false)) {
2615 /* Route is selected, if the route is already installed
2616 * in FIB, then it is advertised
2617 */
be785e35
DS
2618 if (advertise) {
2619 if (!bgp_check_withdrawal(bgp, dest))
2620 bgp_adj_out_set_subgroup(
2621 dest, subgrp, &attr, selected);
2622 else
2623 bgp_adj_out_unset_subgroup(
2624 dest, subgrp, 1, addpath_tx_id);
2625 }
a77e2f4b 2626 } else
9bcb3eef 2627 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2628 addpath_tx_id);
d62a17ae 2629 }
2630
2631 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2632 else {
9bcb3eef 2633 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2634 }
200df115 2635}
fee0f4c6 2636
3064bf43 2637/*
e1072051 2638 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2639 * This is called at the end of route processing.
3064bf43 2640 */
9bcb3eef 2641void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2642{
40381db7 2643 struct bgp_path_info *pi;
3064bf43 2644
9bcb3eef 2645 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2646 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2647 continue;
40381db7
DS
2648 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2649 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2650 }
3064bf43 2651}
2652
2653/*
2654 * Has the route changed from the RIB's perspective? This is invoked only
2655 * if the route selection returns the same best route as earlier - to
2656 * determine if we need to update zebra or not.
2657 */
9bcb3eef 2658bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2659{
4b7e6066 2660 struct bgp_path_info *mpinfo;
d62a17ae 2661
2bb9eff4
DS
2662 /* If this is multipath, check all selected paths for any nexthop
2663 * change or attribute change. Some attribute changes (e.g., community)
2664 * aren't of relevance to the RIB, but we'll update zebra to ensure
2665 * we handle the case of BGP nexthop change. This is the behavior
2666 * when the best path has an attribute change anyway.
d62a17ae 2667 */
1defdda8 2668 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2669 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2670 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2671 return true;
d62a17ae 2672
2bb9eff4
DS
2673 /*
2674 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2675 */
18ee8310
DS
2676 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2677 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2678 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2679 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2680 return true;
d62a17ae 2681 }
3064bf43 2682
d62a17ae 2683 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2684 return false;
3064bf43 2685}
2686
d62a17ae 2687struct bgp_process_queue {
2688 struct bgp *bgp;
9bcb3eef 2689 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2690#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2691 unsigned int flags;
2692 unsigned int queued;
200df115 2693};
2694
3b0c17e1 2695static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2696 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2697 struct bgp_path_info *new_select,
2698 struct bgp_path_info *old_select)
2699{
9bcb3eef 2700 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2701
2702 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2703 return;
2704
2705 if (advertise_type5_routes(bgp, afi) && new_select
2706 && is_route_injectable_into_evpn(new_select)) {
2707
2708 /* apply the route-map */
2709 if (bgp->adv_cmd_rmap[afi][safi].map) {
2710 route_map_result_t ret;
2711 struct bgp_path_info rmap_path;
2712 struct bgp_path_info_extra rmap_path_extra;
2713 struct attr dummy_attr;
2714
2715 dummy_attr = *new_select->attr;
2716
2717 /* Fill temp path_info */
9bcb3eef 2718 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2719 new_select, new_select->peer,
2720 &dummy_attr);
2721
2722 RESET_FLAG(dummy_attr.rmap_change_flags);
2723
2724 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2725 p, &rmap_path);
3b0c17e1 2726
2727 if (ret == RMAP_DENYMATCH) {
2728 bgp_attr_flush(&dummy_attr);
2729 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2730 safi);
2731 } else
2732 bgp_evpn_advertise_type5_route(
2733 bgp, p, &dummy_attr, afi, safi);
2734 } else {
2735 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2736 afi, safi);
2737 }
2738 } else if (advertise_type5_routes(bgp, afi) && old_select
2739 && is_route_injectable_into_evpn(old_select))
2740 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2741}
2742
bb2ca692
MS
2743/*
2744 * Utility to determine whether a particular path_info should use
2745 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2746 * in a path where we basically _know_ this is a BGP-LU route.
2747 */
2748static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2749{
2750 /* Certain types get imp null; so do paths where the nexthop is
2751 * not labeled.
2752 */
2753 if (new_select->sub_type == BGP_ROUTE_STATIC
2754 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2755 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2756 return true;
2757 else if (new_select->extra == NULL ||
2758 !bgp_is_valid_label(&new_select->extra->label[0]))
2759 /* TODO -- should be configurable? */
2760 return true;
2761 else
2762 return false;
2763}
2764
3103e8d2
DS
2765/*
2766 * old_select = The old best path
2767 * new_select = the new best path
2768 *
2769 * if (!old_select && new_select)
2770 * We are sending new information on.
2771 *
2772 * if (old_select && new_select) {
2773 * if (new_select != old_select)
2774 * We have a new best path send a change
2775 * else
2776 * We've received a update with new attributes that needs
2777 * to be passed on.
2778 * }
2779 *
2780 * if (old_select && !new_select)
2781 * We have no eligible route that we can announce or the rn
2782 * is being removed.
2783 */
9bcb3eef 2784static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2785 afi_t afi, safi_t safi)
d62a17ae 2786{
4b7e6066
DS
2787 struct bgp_path_info *new_select;
2788 struct bgp_path_info *old_select;
2789 struct bgp_path_info_pair old_and_new;
ddb5b488 2790 int debug = 0;
d62a17ae 2791
892fedb6 2792 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2793 if (dest)
2794 debug = bgp_debug_bestpath(dest);
b54892e0 2795 if (debug)
f4c713ae 2796 zlog_debug(
56ca3b5b 2797 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2798 __func__, dest);
f4c713ae
LB
2799 return;
2800 }
d62a17ae 2801 /* Is it end of initial update? (after startup) */
9bcb3eef 2802 if (!dest) {
e36f61b5
DS
2803 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2804 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2805
2806 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2807 FOREACH_AFI_SAFI (afi, safi) {
2808 if (bgp_fibupd_safi(safi))
2809 bgp_zebra_announce_table(bgp, afi, safi);
2810 }
d62a17ae 2811 bgp->main_peers_update_hold = 0;
2812
2813 bgp_start_routeadv(bgp);
aac24838 2814 return;
d62a17ae 2815 }
cb1faec9 2816
9bcb3eef 2817 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2818
9bcb3eef 2819 debug = bgp_debug_bestpath(dest);
b54892e0 2820 if (debug)
4378495a
DS
2821 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2822 dest, bgp->name_pretty, afi2str(afi),
2823 safi2str(safi));
ddb5b488 2824
f009ff26 2825 /* The best path calculation for the route is deferred if
2826 * BGP_NODE_SELECT_DEFER is set
2827 */
9bcb3eef 2828 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2829 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2830 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2831 return;
2832 }
2833
d62a17ae 2834 /* Best path selection. */
9bcb3eef 2835 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2836 afi, safi);
2837 old_select = old_and_new.old;
2838 new_select = old_and_new.new;
2839
2840 /* Do we need to allocate or free labels?
2841 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2842 * necessary to do this upon changes to best path. Exceptions:
2843 * - label index has changed -> recalculate resulting label
2844 * - path_info sub_type changed -> switch to/from implicit-null
2845 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2846 */
318cac96 2847 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2848 if (new_select) {
2849 if (!old_select
2850 || bgp_label_index_differs(new_select, old_select)
57592a53 2851 || new_select->sub_type != old_select->sub_type
9bcb3eef 2852 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2853 /* Enforced penultimate hop popping:
2854 * implicit-null for local routes, aggregate
2855 * and redistributed routes
2856 */
bb2ca692 2857 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 2858 if (CHECK_FLAG(
9bcb3eef 2859 dest->flags,
992dd67e
PR
2860 BGP_NODE_REGISTERED_FOR_LABEL)
2861 || CHECK_FLAG(
2862 dest->flags,
2863 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2864 bgp_unregister_for_label(dest);
70e98a7f 2865 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2866 &dest->local_label);
2867 bgp_set_valid_label(&dest->local_label);
d62a17ae 2868 } else
9bcb3eef
DS
2869 bgp_register_for_label(dest,
2870 new_select);
d62a17ae 2871 }
9bcb3eef 2872 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2873 BGP_NODE_REGISTERED_FOR_LABEL)
2874 || CHECK_FLAG(dest->flags,
2875 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2876 bgp_unregister_for_label(dest);
318cac96 2877 }
992dd67e
PR
2878 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2879 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2880 bgp_unregister_for_label(dest);
d62a17ae 2881 }
cd1964ff 2882
b54892e0 2883 if (debug)
ddb5b488 2884 zlog_debug(
4378495a
DS
2885 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2886 __func__, dest, bgp->name_pretty, afi2str(afi),
2887 safi2str(safi), old_select, new_select);
ddb5b488 2888
d62a17ae 2889 /* If best route remains the same and this is not due to user-initiated
2890 * clear, see exactly what needs to be done.
2891 */
d62a17ae 2892 if (old_select && old_select == new_select
9bcb3eef 2893 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2894 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2895 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2896 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2897#ifdef ENABLE_BGP_VNC
d62a17ae 2898 vnc_import_bgp_add_route(bgp, p, old_select);
2899 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2900#endif
bb744275 2901 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2902 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2903
be785e35
DS
2904 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
2905 && new_select->sub_type == BGP_ROUTE_NORMAL)
2906 SET_FLAG(dest->flags,
2907 BGP_NODE_FIB_INSTALL_PENDING);
2908
ddb5b488
PZ
2909 if (new_select->type == ZEBRA_ROUTE_BGP
2910 && (new_select->sub_type == BGP_ROUTE_NORMAL
2911 || new_select->sub_type
2912 == BGP_ROUTE_IMPORTED))
2913
9bcb3eef 2914 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2915 bgp, afi, safi);
2916 }
d62a17ae 2917 }
d62a17ae 2918
2919 /* If there is a change of interest to peers, reannounce the
2920 * route. */
1defdda8 2921 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2922 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2923 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2924 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2925
2926 /* unicast routes must also be annouced to
2927 * labeled-unicast update-groups */
2928 if (safi == SAFI_UNICAST)
2929 group_announce_route(bgp, afi,
9bcb3eef 2930 SAFI_LABELED_UNICAST, dest,
d62a17ae 2931 new_select);
2932
1defdda8 2933 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2934 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2935 }
fee0f4c6 2936
3b0c17e1 2937 /* advertise/withdraw type-5 routes */
2938 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2939 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2940 bgp_process_evpn_route_injection(
9bcb3eef 2941 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2942
b1875e65 2943 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2944 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2945 bgp_zebra_clear_route_change_flags(dest);
2946 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2947 return;
d62a17ae 2948 }
8ad7271d 2949
d62a17ae 2950 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2951 */
9bcb3eef 2952 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2953
2954 /* bestpath has changed; bump version */
2955 if (old_select || new_select) {
9bcb3eef 2956 bgp_bump_version(dest);
d62a17ae 2957
2958 if (!bgp->t_rmap_def_originate_eval) {
2959 bgp_lock(bgp);
2960 thread_add_timer(
2961 bm->master,
2962 update_group_refresh_default_originate_route_map,
2963 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2964 &bgp->t_rmap_def_originate_eval);
2965 }
2966 }
3f9c7369 2967
d62a17ae 2968 if (old_select)
9bcb3eef 2969 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2970 if (new_select) {
ddb5b488
PZ
2971 if (debug)
2972 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2973 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2974 bgp_path_info_unset_flag(dest, new_select,
2975 BGP_PATH_ATTR_CHANGED);
1defdda8 2976 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2977 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2978 }
338b3424 2979
49e5a4a0 2980#ifdef ENABLE_BGP_VNC
d62a17ae 2981 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2982 if (old_select != new_select) {
2983 if (old_select) {
2984 vnc_import_bgp_exterior_del_route(bgp, p,
2985 old_select);
2986 vnc_import_bgp_del_route(bgp, p, old_select);
2987 }
2988 if (new_select) {
2989 vnc_import_bgp_exterior_add_route(bgp, p,
2990 new_select);
2991 vnc_import_bgp_add_route(bgp, p, new_select);
2992 }
2993 }
2994 }
65efcfce
LB
2995#endif
2996
9bcb3eef 2997 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2998
2999 /* unicast routes must also be annouced to labeled-unicast update-groups
3000 */
3001 if (safi == SAFI_UNICAST)
9bcb3eef 3002 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3003 new_select);
3004
3005 /* FIB update. */
3006 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3007 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3008
d62a17ae 3009 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3010 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3011 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3012 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3013
be785e35
DS
3014 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3015 SET_FLAG(dest->flags,
3016 BGP_NODE_FIB_INSTALL_PENDING);
3017
2b659f33
MK
3018 /* if this is an evpn imported type-5 prefix,
3019 * we need to withdraw the route first to clear
3020 * the nh neigh and the RMAC entry.
3021 */
3022 if (old_select &&
3023 is_route_parent_evpn(old_select))
3024 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3025
9bcb3eef 3026 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3027 } else {
d62a17ae 3028 /* Withdraw the route from the kernel. */
3029 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3030 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3031 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3032 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3033
568e10ca 3034 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3035 }
718e3744 3036 }
3064bf43 3037
9bcb3eef 3038 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3039 old_select);
5424b7ba 3040
d62a17ae 3041 /* Clear any route change flags. */
9bcb3eef 3042 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3043
18ee8310 3044 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3045 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3046 bgp_path_info_reap(dest, old_select);
d62a17ae 3047
9bcb3eef 3048 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3049 return;
718e3744 3050}
3051
f009ff26 3052/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3053int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3054{
9bcb3eef 3055 struct bgp_dest *dest;
f009ff26 3056 int cnt = 0;
3057 struct afi_safi_info *thread_info;
f009ff26 3058
56c226e7
DS
3059 if (bgp->gr_info[afi][safi].t_route_select) {
3060 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3061
3062 thread_info = THREAD_ARG(t);
3063 XFREE(MTYPE_TMP, thread_info);
f009ff26 3064 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3065 }
f009ff26 3066
3067 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3068 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3069 get_afi_safi_str(afi, safi, false),
26742171 3070 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3071 }
3072
3073 /* Process the route list */
6338d242
DS
3074 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3075 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3076 dest = bgp_route_next(dest)) {
3077 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3078 continue;
3079
3080 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3081 bgp->gr_info[afi][safi].gr_deferred--;
3082 bgp_process_main_one(bgp, dest, afi, safi);
3083 cnt++;
3084 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3085 bgp_dest_unlock_node(dest);
3086 break;
f009ff26 3087 }
f009ff26 3088 }
3089
9e3b51a7 3090 /* Send EOR message when all routes are processed */
6338d242 3091 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3092 bgp_send_delayed_eor(bgp);
8c48b3b6 3093 /* Send route processing complete message to RIB */
3094 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3095 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3096 return 0;
9e3b51a7 3097 }
f009ff26 3098
3099 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3100
3101 thread_info->afi = afi;
3102 thread_info->safi = safi;
3103 thread_info->bgp = bgp;
3104
3105 /* If there are more routes to be processed, start the
3106 * selection timer
3107 */
3108 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3109 BGP_ROUTE_SELECT_DELAY,
3110 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3111 return 0;
3112}
3113
aac24838 3114static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3115{
aac24838
JB
3116 struct bgp_process_queue *pqnode = data;
3117 struct bgp *bgp = pqnode->bgp;
d62a17ae 3118 struct bgp_table *table;
9bcb3eef 3119 struct bgp_dest *dest;
aac24838
JB
3120
3121 /* eoiu marker */
3122 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3123 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3124 /* should always have dedicated wq call */
3125 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3126 return WQ_SUCCESS;
3127 }
3128
ac021f40 3129 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3130 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3131 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3132 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3133 table = bgp_dest_table(dest);
3134 /* note, new DESTs may be added as part of processing */
3135 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3136
9bcb3eef 3137 bgp_dest_unlock_node(dest);
d62a17ae 3138 bgp_table_unlock(table);
3139 }
aac24838
JB
3140
3141 return WQ_SUCCESS;
3142}
3143
3144static void bgp_processq_del(struct work_queue *wq, void *data)
3145{
3146 struct bgp_process_queue *pqnode = data;
3147
3148 bgp_unlock(pqnode->bgp);
3149
3150 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3151}
3152
b6c386bb 3153void bgp_process_queue_init(struct bgp *bgp)
200df115 3154{
b6c386bb
DS
3155 if (!bgp->process_queue) {
3156 char name[BUFSIZ];
3157
3158 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3159 bgp->process_queue = work_queue_new(bm->master, name);
3160 }
3161
3162 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3163 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3164 bgp->process_queue->spec.max_retries = 0;
3165 bgp->process_queue->spec.hold = 50;
d62a17ae 3166 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3167 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3168}
3169
cfe8d15a 3170static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3171{
3172 struct bgp_process_queue *pqnode;
3173
a4d82a8a
PZ
3174 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3175 sizeof(struct bgp_process_queue));
aac24838
JB
3176
3177 /* unlocked in bgp_processq_del */
3178 pqnode->bgp = bgp_lock(bgp);
3179 STAILQ_INIT(&pqnode->pqueue);
3180
aac24838
JB
3181 return pqnode;
3182}
3183
9bcb3eef 3184void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3185{
aac24838 3186#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3187 struct work_queue *wq = bgp->process_queue;
d62a17ae 3188 struct bgp_process_queue *pqnode;
cfe8d15a 3189 int pqnode_reuse = 0;
495f0b13 3190
d62a17ae 3191 /* already scheduled for processing? */
9bcb3eef 3192 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3193 return;
2e02b9b2 3194
f009ff26 3195 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3196 * the workqueue
3197 */
9bcb3eef 3198 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3199 if (BGP_DEBUG(update, UPDATE_OUT))
3200 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3201 dest);
f009ff26 3202 return;
3203 }
3204
46aeabed
LS
3205 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3206 if (BGP_DEBUG(update, UPDATE_OUT))
3207 zlog_debug(
3208 "Soft reconfigure table in progress for route %p",
3209 dest);
3210 return;
3211 }
3212
aac24838 3213 if (wq == NULL)
d62a17ae 3214 return;
3215
aac24838 3216 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3217 limit only if is from the same BGP view and it's not an EOIU marker
3218 */
aac24838
JB
3219 if (work_queue_item_count(wq)) {
3220 struct work_queue_item *item = work_queue_last_item(wq);
3221 pqnode = item->data;
228da428 3222
a4d82a8a
PZ
3223 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3224 || pqnode->bgp != bgp
3225 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3226 pqnode = bgp_processq_alloc(bgp);
3227 else
3228 pqnode_reuse = 1;
aac24838 3229 } else
cfe8d15a 3230 pqnode = bgp_processq_alloc(bgp);
aac24838 3231 /* all unlocked in bgp_process_wq */
9bcb3eef 3232 bgp_table_lock(bgp_dest_table(dest));
aac24838 3233
9bcb3eef
DS
3234 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3235 bgp_dest_lock_node(dest);
aac24838 3236
60466a63 3237 /* can't be enqueued twice */
9bcb3eef
DS
3238 assert(STAILQ_NEXT(dest, pq) == NULL);
3239 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3240 pqnode->queued++;
3241
cfe8d15a
LB
3242 if (!pqnode_reuse)
3243 work_queue_add(wq, pqnode);
3244
d62a17ae 3245 return;
fee0f4c6 3246}
0a486e5f 3247
d62a17ae 3248void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3249{
d62a17ae 3250 struct bgp_process_queue *pqnode;
cb1faec9 3251
b6c386bb 3252 if (bgp->process_queue == NULL)
d62a17ae 3253 return;
2e02b9b2 3254
cfe8d15a 3255 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3256
aac24838 3257 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3258 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3259}
3260
d62a17ae 3261static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3262{
d62a17ae 3263 struct peer *peer;
0a486e5f 3264
d62a17ae 3265 peer = THREAD_ARG(thread);
3266 peer->t_pmax_restart = NULL;
0a486e5f 3267
d62a17ae 3268 if (bgp_debug_neighbor_events(peer))
3269 zlog_debug(
3270 "%s Maximum-prefix restart timer expired, restore peering",
3271 peer->host);
0a486e5f 3272
a9bafa95 3273 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3274 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3275
d62a17ae 3276 return 0;
0a486e5f 3277}
3278
9cbd06e0
DA
3279static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3280 safi_t safi)
3281{
3282 uint32_t count = 0;
f41b0459 3283 bool filtered = false;
9cbd06e0
DA
3284 struct bgp_dest *dest;
3285 struct bgp_adj_in *ain;
40bb2ccf 3286 struct attr attr = {};
9cbd06e0
DA
3287 struct bgp_table *table = peer->bgp->rib[afi][safi];
3288
3289 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3290 for (ain = dest->adj_in; ain; ain = ain->next) {
3291 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3292
3293 attr = *ain->attr;
9cbd06e0
DA
3294
3295 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3296 == FILTER_DENY)
f41b0459
DA
3297 filtered = true;
3298
3299 if (bgp_input_modifier(
3300 peer, rn_p, &attr, afi, safi,
3301 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3302 NULL, 0, NULL)
3303 == RMAP_DENY)
3304 filtered = true;
3305
3306 if (filtered)
9cbd06e0 3307 count++;
f41b0459
DA
3308
3309 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3310 }
3311 }
3312
3313 return count;
3314}
3315
3dc339cd
DA
3316bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3317 int always)
718e3744 3318{
d62a17ae 3319 iana_afi_t pkt_afi;
5c525538 3320 iana_safi_t pkt_safi;
9cbd06e0
DA
3321 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3322 PEER_FLAG_MAX_PREFIX_FORCE))
3323 ? bgp_filtered_routes_count(peer, afi, safi)
3324 + peer->pcount[afi][safi]
3325 : peer->pcount[afi][safi];
9cabb64b 3326
d62a17ae 3327 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3328 return false;
e0701b79 3329
9cbd06e0 3330 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3331 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3332 PEER_STATUS_PREFIX_LIMIT)
3333 && !always)
3dc339cd 3334 return false;
e0701b79 3335
d62a17ae 3336 zlog_info(
6cde4b45 3337 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3338 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3339 peer->pmax[afi][safi]);
d62a17ae 3340 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3341
3342 if (CHECK_FLAG(peer->af_flags[afi][safi],
3343 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3344 return false;
d62a17ae 3345
3346 /* Convert AFI, SAFI to values for packet. */
3347 pkt_afi = afi_int2iana(afi);
3348 pkt_safi = safi_int2iana(safi);
3349 {
d7c0a89a 3350 uint8_t ndata[7];
d62a17ae 3351
3352 ndata[0] = (pkt_afi >> 8);
3353 ndata[1] = pkt_afi;
3354 ndata[2] = pkt_safi;
3355 ndata[3] = (peer->pmax[afi][safi] >> 24);
3356 ndata[4] = (peer->pmax[afi][safi] >> 16);
3357 ndata[5] = (peer->pmax[afi][safi] >> 8);
3358 ndata[6] = (peer->pmax[afi][safi]);
3359
3360 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3361 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3362 BGP_NOTIFY_CEASE_MAX_PREFIX,
3363 ndata, 7);
3364 }
3365
3366 /* Dynamic peers will just close their connection. */
3367 if (peer_dynamic_neighbor(peer))
3dc339cd 3368 return true;
d62a17ae 3369
3370 /* restart timer start */
3371 if (peer->pmax_restart[afi][safi]) {
3372 peer->v_pmax_restart =
3373 peer->pmax_restart[afi][safi] * 60;
3374
3375 if (bgp_debug_neighbor_events(peer))
3376 zlog_debug(
3377 "%s Maximum-prefix restart timer started for %d secs",
3378 peer->host, peer->v_pmax_restart);
3379
3380 BGP_TIMER_ON(peer->t_pmax_restart,
3381 bgp_maximum_prefix_restart_timer,
3382 peer->v_pmax_restart);
3383 }
3384
3dc339cd 3385 return true;
d62a17ae 3386 } else
3387 UNSET_FLAG(peer->af_sflags[afi][safi],
3388 PEER_STATUS_PREFIX_LIMIT);
3389
b1823b69
DS
3390 if (pcount
3391 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3392 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3393 PEER_STATUS_PREFIX_THRESHOLD)
3394 && !always)
3dc339cd 3395 return false;
d62a17ae 3396
3397 zlog_info(
6cde4b45 3398 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3399 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3400 peer->pmax[afi][safi]);
d62a17ae 3401 SET_FLAG(peer->af_sflags[afi][safi],
3402 PEER_STATUS_PREFIX_THRESHOLD);
3403 } else
3404 UNSET_FLAG(peer->af_sflags[afi][safi],
3405 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3406 return false;
718e3744 3407}
3408
b40d939b 3409/* Unconditionally remove the route from the RIB, without taking
3410 * damping into consideration (eg, because the session went down)
3411 */
9bcb3eef 3412void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3413 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3414{
f009ff26 3415
3416 struct bgp *bgp = NULL;
3417 bool delete_route = false;
3418
9bcb3eef
DS
3419 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3420 safi);
d62a17ae 3421
f009ff26 3422 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3423 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3424
f009ff26 3425 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3426 * flag
3427 */
3428 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3429 delete_route = true;
9bcb3eef 3430 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3431 delete_route = true;
f009ff26 3432 if (delete_route) {
9bcb3eef
DS
3433 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3434 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3435 bgp = pi->peer->bgp;
26742171 3436 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3437 }
3438 }
3439 }
4a11bf2c 3440
9bcb3eef
DS
3441 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3442 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3443}
3444
9bcb3eef 3445static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3446 struct peer *peer, afi_t afi, safi_t safi,
3447 struct prefix_rd *prd)
3448{
9bcb3eef 3449 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3450
d62a17ae 3451 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3452 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3453 */
b4f7f45b
IR
3454 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3455 && peer->sort == BGP_PEER_EBGP)
3456 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3457 == BGP_DAMP_SUPPRESSED) {
3458 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3459 safi);
3460 return;
d62a17ae 3461 }
3462
49e5a4a0 3463#ifdef ENABLE_BGP_VNC
d62a17ae 3464 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3465 struct bgp_dest *pdest = NULL;
d62a17ae 3466 struct bgp_table *table = NULL;
3467
9bcb3eef
DS
3468 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3469 (struct prefix *)prd);
3470 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3471 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3472
3473 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3474 peer->bgp, prd, table, p, pi);
d62a17ae 3475 }
9bcb3eef 3476 bgp_dest_unlock_node(pdest);
d62a17ae 3477 }
3478 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3479 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3480
b54892e0
DS
3481 vnc_import_bgp_del_route(peer->bgp, p, pi);
3482 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3483 }
65efcfce 3484 }
d62a17ae 3485#endif
128ea8ab 3486
d62a17ae 3487 /* If this is an EVPN route, process for un-import. */
3488 if (safi == SAFI_EVPN)
b54892e0 3489 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3490
9bcb3eef 3491 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3492}
3493
4b7e6066
DS
3494struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3495 struct peer *peer, struct attr *attr,
9bcb3eef 3496 struct bgp_dest *dest)
fb018d25 3497{
4b7e6066 3498 struct bgp_path_info *new;
fb018d25 3499
d62a17ae 3500 /* Make new BGP info. */
4b7e6066 3501 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3502 new->type = type;
3503 new->instance = instance;
3504 new->sub_type = sub_type;
3505 new->peer = peer;
3506 new->attr = attr;
3507 new->uptime = bgp_clock();
9bcb3eef 3508 new->net = dest;
d62a17ae 3509 return new;
fb018d25
DS
3510}
3511
40381db7 3512static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3513 union gw_addr *gw_ip)
3514{
6c924775
DS
3515 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3516 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3517 union {
0a50c248 3518 esi_t esi;
11ebf4ed
DS
3519 union gw_addr ip;
3520 } temp;
d62a17ae 3521
3522 if (afi != AFI_L2VPN)
3523 return true;
11ebf4ed 3524
6c924775 3525 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3526
3527 if (gw_ip == NULL) {
3528 memset(&temp, 0, sizeof(temp));
40381db7 3529 path_gw_ip_remote = &temp.ip;
11ebf4ed 3530 } else
40381db7 3531 path_gw_ip_remote = gw_ip;
11ebf4ed 3532
6c924775 3533 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3534}
3535
c265ee22 3536/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3537bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3538 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3539 struct bgp_dest *dest)
d62a17ae 3540{
2dbe3fa9 3541 bool ret = false;
b099a5c8
DA
3542 bool is_bgp_static_route =
3543 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3544 : false;
d62a17ae 3545
e8442016
DS
3546 /*
3547 * Only validated for unicast and multicast currently.
3548 * Also valid for EVPN where the nexthop is an IP address.
3549 * If we are a bgp static route being checked then there is
3550 * no need to check to see if the nexthop is martian as
3551 * that it should be ok.
3552 */
3553 if (is_bgp_static_route ||
3554 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3555 return false;
d62a17ae 3556
3557 /* If NEXT_HOP is present, validate it. */
3558 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3559 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3560 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3561 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3562 return true;
d62a17ae 3563 }
c265ee22 3564
d62a17ae 3565 /* If MP_NEXTHOP is present, validate it. */
3566 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3567 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3568 * it is not an IPv6 link-local address.
0355b41d
DA
3569 *
3570 * If we receive an UPDATE with nexthop length set to 32 bytes
3571 * we shouldn't discard an UPDATE if it's set to (::).
3572 * The link-local (2st) is validated along the code path later.
d62a17ae 3573 */
3574 if (attr->mp_nexthop_len) {
3575 switch (attr->mp_nexthop_len) {
3576 case BGP_ATTR_NHLEN_IPV4:
3577 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3578 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3579 || IPV4_CLASS_DE(
3580 ntohl(attr->mp_nexthop_global_in.s_addr))
3581 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3582 dest));
d62a17ae 3583 break;
3584
3585 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3586 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3587 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3588 &attr->mp_nexthop_global)
d62a17ae 3589 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3590 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3591 &attr->mp_nexthop_global)
3592 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3593 dest));
d62a17ae 3594 break;
0355b41d
DA
3595 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3596 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3597 || IN6_IS_ADDR_MULTICAST(
3598 &attr->mp_nexthop_global)
3599 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3600 dest));
0355b41d 3601 break;
d62a17ae 3602
3603 default:
3dc339cd 3604 ret = true;
d62a17ae 3605 break;
3606 }
3607 }
c265ee22 3608
d62a17ae 3609 return ret;
3610}
3611
aade37d7 3612static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3613{
3614 struct community *old;
3615 struct community *new;
3616 struct community *merge;
aade37d7 3617 struct community *no_export;
2721dd61
DA
3618
3619 old = attr->community;
aade37d7 3620 no_export = community_str2com("no-export");
2721dd61 3621
b4efa101
DA
3622 assert(no_export);
3623
2721dd61 3624 if (old) {
aade37d7 3625 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3626
3627 if (!old->refcnt)
3628 community_free(&old);
3629
3630 new = community_uniq_sort(merge);
3631 community_free(&merge);
3632 } else {
aade37d7 3633 new = community_dup(no_export);
2721dd61
DA
3634 }
3635
aade37d7 3636 community_free(&no_export);
2721dd61
DA
3637
3638 attr->community = new;
3639 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3640}
3641
5a1ae2c2 3642int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3643 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3644 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3645 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3646 struct bgp_route_evpn *evpn)
d62a17ae 3647{
3648 int ret;
3649 int aspath_loop_count = 0;
9bcb3eef 3650 struct bgp_dest *dest;
d62a17ae 3651 struct bgp *bgp;
3652 struct attr new_attr;
3653 struct attr *attr_new;
40381db7 3654 struct bgp_path_info *pi;
4b7e6066
DS
3655 struct bgp_path_info *new;
3656 struct bgp_path_info_extra *extra;
d62a17ae 3657 const char *reason;
3658 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3659 int connected = 0;
3660 int do_loop_check = 1;
3661 int has_valid_label = 0;
7c312383 3662 afi_t nh_afi;
949b0f24 3663 uint8_t pi_type = 0;
3664 uint8_t pi_sub_type = 0;
9146341f 3665 bool force_evpn_import = false;
907707db 3666 safi_t orig_safi = safi;
949b0f24 3667
c7bb4f00 3668 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3669 char pfxprint[PREFIX2STR_BUFFER];
3670
3671 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3672 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3673 afi, safi, attr);
6401252f
QY
3674 }
3675
49e5a4a0 3676#ifdef ENABLE_BGP_VNC
d62a17ae 3677 int vnc_implicit_withdraw = 0;
65efcfce 3678#endif
d62a17ae 3679 int same_attr = 0;
718e3744 3680
907707db
MS
3681 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3682 if (orig_safi == SAFI_LABELED_UNICAST)
3683 safi = SAFI_UNICAST;
3684
d62a17ae 3685 memset(&new_attr, 0, sizeof(struct attr));
3686 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3687 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3688
d62a17ae 3689 bgp = peer->bgp;
9bcb3eef 3690 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3691 /* TODO: Check to see if we can get rid of "is_valid_label" */
3692 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3693 has_valid_label = (num_labels > 0) ? 1 : 0;
3694 else
3695 has_valid_label = bgp_is_valid_label(label);
718e3744 3696
28f66de2
MS
3697 if (has_valid_label)
3698 assert(label != NULL);
3699
66ff6089
AD
3700 /* Update overlay index of the attribute */
3701 if (afi == AFI_L2VPN && evpn)
3702 memcpy(&attr->evpn_overlay, evpn,
3703 sizeof(struct bgp_route_evpn));
3704
d62a17ae 3705 /* When peer's soft reconfiguration enabled. Record input packet in
3706 Adj-RIBs-In. */
3707 if (!soft_reconfig
3708 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3709 && peer != bgp->peer_self)
9bcb3eef 3710 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3711
3712 /* Check previously received route. */
9bcb3eef 3713 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3714 if (pi->peer == peer && pi->type == type
3715 && pi->sub_type == sub_type
3716 && pi->addpath_rx_id == addpath_id)
d62a17ae 3717 break;
3718
3719 /* AS path local-as loop check. */
3720 if (peer->change_local_as) {
c4368918
DW
3721 if (peer->allowas_in[afi][safi])
3722 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3723 else if (!CHECK_FLAG(peer->flags,
3724 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3725 aspath_loop_count = 1;
3726
3727 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3728 > aspath_loop_count) {
b4d46cc9 3729 peer->stat_pfx_aspath_loop++;
692174a1 3730 reason = "as-path contains our own AS;";
d62a17ae 3731 goto filtered;
3732 }
718e3744 3733 }
718e3744 3734
d62a17ae 3735 /* If the peer is configured for "allowas-in origin" and the last ASN in
3736 * the
3737 * as-path is our ASN then we do not need to call aspath_loop_check
3738 */
3739 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3740 if (aspath_get_last_as(attr->aspath) == bgp->as)
3741 do_loop_check = 0;
3742
3743 /* AS path loop check. */
3744 if (do_loop_check) {
3745 if (aspath_loop_check(attr->aspath, bgp->as)
3746 > peer->allowas_in[afi][safi]
3747 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3748 && aspath_loop_check(attr->aspath, bgp->confed_id)
3749 > peer->allowas_in[afi][safi])) {
b4d46cc9 3750 peer->stat_pfx_aspath_loop++;
d62a17ae 3751 reason = "as-path contains our own AS;";
3752 goto filtered;
3753 }
3754 }
aac9ef6c 3755
d62a17ae 3756 /* Route reflector originator ID check. */
3757 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3758 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3759 peer->stat_pfx_originator_loop++;
d62a17ae 3760 reason = "originator is us;";
3761 goto filtered;
3762 }
718e3744 3763
d62a17ae 3764 /* Route reflector cluster ID check. */
3765 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3766 peer->stat_pfx_cluster_loop++;
d62a17ae 3767 reason = "reflected from the same cluster;";
3768 goto filtered;
3769 }
718e3744 3770
d62a17ae 3771 /* Apply incoming filter. */
907707db 3772 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3773 peer->stat_pfx_filter++;
d62a17ae 3774 reason = "filter;";
3775 goto filtered;
3776 }
718e3744 3777
a8b72dc6
DA
3778 /* RFC 8212 to prevent route leaks.
3779 * This specification intends to improve this situation by requiring the
3780 * explicit configuration of both BGP Import and Export Policies for any
3781 * External BGP (EBGP) session such as customers, peers, or
3782 * confederation boundaries for all enabled address families. Through
3783 * codification of the aforementioned requirement, operators will
3784 * benefit from consistent behavior across different BGP
3785 * implementations.
3786 */
1d3fdccf 3787 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3788 if (!bgp_inbound_policy_exists(peer,
3789 &peer->filter[afi][safi])) {
3790 reason = "inbound policy missing";
3791 goto filtered;
3792 }
3793
fb29348a
DA
3794 /* draft-ietf-idr-deprecate-as-set-confed-set
3795 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3796 * Eventually, This document (if approved) updates RFC 4271
3797 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3798 * and obsoletes RFC 6472.
3799 */
7f972cd8 3800 if (peer->bgp->reject_as_sets)
fb29348a
DA
3801 if (aspath_check_as_sets(attr->aspath)) {
3802 reason =
3803 "as-path contains AS_SET or AS_CONFED_SET type;";
3804 goto filtered;
3805 }
3806
6f4f49b2 3807 new_attr = *attr;
d62a17ae 3808
3809 /* Apply incoming route-map.
3810 * NB: new_attr may now contain newly allocated values from route-map
3811 * "set"
3812 * commands, so we need bgp_attr_flush in the error paths, until we
3813 * intern
3814 * the attr (which takes over the memory references) */
907707db 3815 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3816 num_labels, dest)
3817 == RMAP_DENY) {
b4d46cc9 3818 peer->stat_pfx_filter++;
d62a17ae 3819 reason = "route-map;";
3820 bgp_attr_flush(&new_attr);
3821 goto filtered;
3822 }
718e3744 3823
05864da7 3824 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3825 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3826 /* remove from RIB previous entry */
3827 bgp_zebra_withdraw(p, pi, bgp, safi);
3828 }
3829
7f323236
DW
3830 if (peer->sort == BGP_PEER_EBGP) {
3831
2721dd61
DA
3832 /* rfc7999:
3833 * A BGP speaker receiving an announcement tagged with the
3834 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3835 * NO_EXPORT community as defined in RFC1997, or a
3836 * similar community, to prevent propagation of the
3837 * prefix outside the local AS. The community to prevent
3838 * propagation SHOULD be chosen according to the operator's
3839 * routing policy.
3840 */
3841 if (new_attr.community
3842 && community_include(new_attr.community,
3843 COMMUNITY_BLACKHOLE))
aade37d7 3844 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3845
a4d82a8a
PZ
3846 /* If we receive the graceful-shutdown community from an eBGP
3847 * peer we must lower local-preference */
3848 if (new_attr.community
3849 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3850 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3851 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3852
a4d82a8a
PZ
3853 /* If graceful-shutdown is configured then add the GSHUT
3854 * community to all paths received from eBGP peers */
637e5ba4 3855 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3856 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3857 }
3858
949b0f24 3859 if (pi) {
3860 pi_type = pi->type;
3861 pi_sub_type = pi->sub_type;
3862 }
3863
d62a17ae 3864 /* next hop check. */
a4d82a8a 3865 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3866 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3867 &new_attr, dest)) {
b4d46cc9 3868 peer->stat_pfx_nh_invalid++;
d62a17ae 3869 reason = "martian or self next-hop;";
3870 bgp_attr_flush(&new_attr);
3871 goto filtered;
3872 }
718e3744 3873
5c14a191 3874 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3875 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3876 reason = "self mac;";
3877 goto filtered;
3878 }
3879
a1b773e2
DS
3880 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3881 * condition :
3882 * Suppress fib is enabled
3883 * BGP_OPT_NO_FIB is not enabled
3884 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3885 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3886 */
3887 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3888 && (sub_type == BGP_ROUTE_NORMAL)
3889 && (!bgp_option_check(BGP_OPT_NO_FIB))
3890 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3891 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3892
d62a17ae 3893 attr_new = bgp_attr_intern(&new_attr);
3894
9cbd06e0
DA
3895 /* If maximum prefix count is configured and current prefix
3896 * count exeed it.
3897 */
3898 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3899 return -1;
3900
d62a17ae 3901 /* If the update is implicit withdraw. */
40381db7
DS
3902 if (pi) {
3903 pi->uptime = bgp_clock();
3904 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3905
9bcb3eef 3906 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3907
d62a17ae 3908 /* Same attribute comes in. */
40381db7 3909 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3910 && same_attr
d62a17ae 3911 && (!has_valid_label
40381db7 3912 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3913 num_labels * sizeof(mpls_label_t))
66ff6089 3914 == 0)) {
b4f7f45b
IR
3915 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3916 BGP_CONFIG_DAMPENING)
d62a17ae 3917 && peer->sort == BGP_PEER_EBGP
40381db7 3918 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3919 if (bgp_debug_update(peer, p, NULL, 1)) {
3920 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3921 afi, safi, prd, p, label,
3922 num_labels, addpath_id ? 1 : 0,
66ff6089 3923 addpath_id, evpn, pfx_buf,
a4d82a8a 3924 sizeof(pfx_buf));
d62a17ae 3925 zlog_debug("%s rcvd %s", peer->host,
3926 pfx_buf);
3927 }
3928
9bcb3eef 3929 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3930 != BGP_DAMP_SUPPRESSED) {
40381db7 3931 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3932 safi);
9bcb3eef 3933 bgp_process(bgp, dest, afi, safi);
d62a17ae 3934 }
3935 } else /* Duplicate - odd */
3936 {
3937 if (bgp_debug_update(peer, p, NULL, 1)) {
3938 if (!peer->rcvd_attr_printed) {
3939 zlog_debug(
3940 "%s rcvd UPDATE w/ attr: %s",
3941 peer->host,
3942 peer->rcvd_attr_str);
3943 peer->rcvd_attr_printed = 1;
3944 }
3945
3946 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3947 afi, safi, prd, p, label,
3948 num_labels, addpath_id ? 1 : 0,
66ff6089 3949 addpath_id, evpn, pfx_buf,
a4d82a8a 3950 sizeof(pfx_buf));
d62a17ae 3951 zlog_debug(
3952 "%s rcvd %s...duplicate ignored",
3953 peer->host, pfx_buf);
3954 }
3955
3956 /* graceful restart STALE flag unset. */
40381db7 3957 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3958 bgp_path_info_unset_flag(
9bcb3eef
DS
3959 dest, pi, BGP_PATH_STALE);
3960 bgp_dest_set_defer_flag(dest, false);
3961 bgp_process(bgp, dest, afi, safi);
d62a17ae 3962 }
3963 }
3964
9bcb3eef 3965 bgp_dest_unlock_node(dest);
d62a17ae 3966 bgp_attr_unintern(&attr_new);
3967
3968 return 0;
3969 }
718e3744 3970
d62a17ae 3971 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3972 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3973 if (bgp_debug_update(peer, p, NULL, 1)) {
3974 bgp_debug_rdpfxpath2str(
a4d82a8a 3975 afi, safi, prd, p, label, num_labels,
66ff6089 3976 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 3977 pfx_buf, sizeof(pfx_buf));
d62a17ae 3978 zlog_debug(
3979 "%s rcvd %s, flapped quicker than processing",
3980 peer->host, pfx_buf);
3981 }
3982
9bcb3eef 3983 bgp_path_info_restore(dest, pi);
9146341f 3984
3985 /*
3986 * If the BGP_PATH_REMOVED flag is set, then EVPN
3987 * routes would have been unimported already when a
3988 * prior BGP withdraw processing happened. Such routes
3989 * need to be imported again, so flag accordingly.
3990 */
3991 force_evpn_import = true;
d62a17ae 3992 }
718e3744 3993
d62a17ae 3994 /* Received Logging. */
3995 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3996 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3997 num_labels, addpath_id ? 1 : 0,
66ff6089 3998 addpath_id, evpn, pfx_buf,
a4d82a8a 3999 sizeof(pfx_buf));
d62a17ae 4000 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4001 }
718e3744 4002
d62a17ae 4003 /* graceful restart STALE flag unset. */
f009ff26 4004 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4005 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4006 bgp_dest_set_defer_flag(dest, false);
f009ff26 4007 }
d62a17ae 4008
4009 /* The attribute is changed. */
9bcb3eef 4010 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4011
4012 /* implicit withdraw, decrement aggregate and pcount here.
4013 * only if update is accepted, they'll increment below.
4014 */
40381db7 4015 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4016
4017 /* Update bgp route dampening information. */
b4f7f45b 4018 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4019 && peer->sort == BGP_PEER_EBGP) {
4020 /* This is implicit withdraw so we should update
b4f7f45b
IR
4021 dampening
4022 information. */
40381db7 4023 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4024 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4025 }
49e5a4a0 4026#ifdef ENABLE_BGP_VNC
d62a17ae 4027 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4028 struct bgp_dest *pdest = NULL;
d62a17ae 4029 struct bgp_table *table = NULL;
4030
9bcb3eef
DS
4031 pdest = bgp_node_get(bgp->rib[afi][safi],
4032 (struct prefix *)prd);
4033 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4034 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4035
4036 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4037 bgp, prd, table, p, pi);
d62a17ae 4038 }
9bcb3eef 4039 bgp_dest_unlock_node(pdest);
d62a17ae 4040 }
4041 if ((afi == AFI_IP || afi == AFI_IP6)
4042 && (safi == SAFI_UNICAST)) {
40381db7 4043 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4044 /*
4045 * Implicit withdraw case.
4046 */
4047 ++vnc_implicit_withdraw;
40381db7
DS
4048 vnc_import_bgp_del_route(bgp, p, pi);
4049 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4050 }
4051 }
65efcfce 4052#endif
128ea8ab 4053
d62a17ae 4054 /* Special handling for EVPN update of an existing route. If the
4055 * extended community attribute has changed, we need to
4056 * un-import
4057 * the route using its existing extended community. It will be
4058 * subsequently processed for import with the new extended
4059 * community.
4060 */
6f8c9c11
PR
4061 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4062 && !same_attr) {
40381db7 4063 if ((pi->attr->flag
d62a17ae 4064 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4065 && (attr_new->flag
4066 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4067 int cmp;
4068
40381db7 4069 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 4070 attr_new->ecommunity);
4071 if (!cmp) {
4072 if (bgp_debug_update(peer, p, NULL, 1))
4073 zlog_debug(
4074 "Change in EXT-COMM, existing %s new %s",
4075 ecommunity_str(
40381db7 4076 pi->attr->ecommunity),
d62a17ae 4077 ecommunity_str(
4078 attr_new->ecommunity));
6f8c9c11
PR
4079 if (safi == SAFI_EVPN)
4080 bgp_evpn_unimport_route(
4081 bgp, afi, safi, p, pi);
4082 else /* SAFI_MPLS_VPN */
4083 vpn_leak_to_vrf_withdraw(bgp,
4084 pi);
d62a17ae 4085 }
4086 }
4087 }
718e3744 4088
d62a17ae 4089 /* Update to new attribute. */
40381db7
DS
4090 bgp_attr_unintern(&pi->attr);
4091 pi->attr = attr_new;
d62a17ae 4092
4093 /* Update MPLS label */
4094 if (has_valid_label) {
40381db7 4095 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4096 if (extra->label != label) {
4097 memcpy(&extra->label, label,
dbd587da 4098 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4099 extra->num_labels = num_labels;
4100 }
b57ba6d2
MK
4101 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4102 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4103 }
718e3744 4104
e496b420
HS
4105 /* Update SRv6 SID */
4106 if (attr->srv6_l3vpn) {
4107 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4108 if (sid_diff(&extra->sid[0].sid,
4109 &attr->srv6_l3vpn->sid)) {
4110 sid_copy(&extra->sid[0].sid,
e496b420
HS
4111 &attr->srv6_l3vpn->sid);
4112 extra->num_sids = 1;
cc8f05df 4113
16f3db2d
RS
4114 extra->sid[0].loc_block_len = 0;
4115 extra->sid[0].loc_node_len = 0;
4116 extra->sid[0].func_len = 0;
4117 extra->sid[0].arg_len = 0;
4118
4119 if (attr->srv6_l3vpn->loc_block_len != 0) {
4120 extra->sid[0].loc_block_len =
4121 attr->srv6_l3vpn->loc_block_len;
4122 extra->sid[0].loc_node_len =
4123 attr->srv6_l3vpn->loc_node_len;
4124 extra->sid[0].func_len =
4125 attr->srv6_l3vpn->func_len;
4126 extra->sid[0].arg_len =
4127 attr->srv6_l3vpn->arg_len;
4128 }
4129
cc8f05df
RS
4130 /*
4131 * draft-ietf-bess-srv6-services-07
4132 * The part of SRv6 SID may be encoded as MPLS
4133 * Label for the efficient packing.
4134 */
4135 if (attr->srv6_l3vpn->transposition_len != 0)
4136 transpose_sid(
16f3db2d 4137 &extra->sid[0].sid,
cc8f05df
RS
4138 decode_label(label),
4139 attr->srv6_l3vpn
4140 ->transposition_offset,
4141 attr->srv6_l3vpn
4142 ->transposition_len);
e496b420
HS
4143 }
4144 } else if (attr->srv6_vpn) {
4145 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4146 if (sid_diff(&extra->sid[0].sid,
4147 &attr->srv6_vpn->sid)) {
4148 sid_copy(&extra->sid[0].sid,
4149 &attr->srv6_vpn->sid);
e496b420
HS
4150 extra->num_sids = 1;
4151 }
4152 }
4153
49e5a4a0 4154#ifdef ENABLE_BGP_VNC
d62a17ae 4155 if ((afi == AFI_IP || afi == AFI_IP6)
4156 && (safi == SAFI_UNICAST)) {
4157 if (vnc_implicit_withdraw) {
4158 /*
4159 * Add back the route with its new attributes
4160 * (e.g., nexthop).
4161 * The route is still selected, until the route
4162 * selection
4163 * queued by bgp_process actually runs. We have
4164 * to make this
4165 * update to the VNC side immediately to avoid
4166 * racing against
4167 * configuration changes (e.g., route-map
4168 * changes) which
4169 * trigger re-importation of the entire RIB.
4170 */
40381db7
DS
4171 vnc_import_bgp_add_route(bgp, p, pi);
4172 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4173 }
4174 }
65efcfce
LB
4175#endif
4176
d62a17ae 4177 /* Update bgp route dampening information. */
b4f7f45b 4178 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4179 && peer->sort == BGP_PEER_EBGP) {
4180 /* Now we do normal update dampening. */
9bcb3eef 4181 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4182 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4183 bgp_dest_unlock_node(dest);
d62a17ae 4184 return 0;
4185 }
4186 }
128ea8ab 4187
d62a17ae 4188 /* Nexthop reachability check - for unicast and
4189 * labeled-unicast.. */
7c312383
AD
4190 if (((afi == AFI_IP || afi == AFI_IP6)
4191 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4192 || (safi == SAFI_EVPN &&
4193 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4194 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4195 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4196 && !CHECK_FLAG(peer->flags,
4197 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4198 && !CHECK_FLAG(bgp->flags,
4199 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4200 connected = 1;
4201 else
4202 connected = 0;
4203
960035b2
PZ
4204 struct bgp *bgp_nexthop = bgp;
4205
40381db7
DS
4206 if (pi->extra && pi->extra->bgp_orig)
4207 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4208
7c312383
AD
4209 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4210
4211 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4212 safi, pi, NULL, connected,
4213 p)
a4d82a8a 4214 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4215 bgp_path_info_set_flag(dest, pi,
4216 BGP_PATH_VALID);
d62a17ae 4217 else {
4218 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4219 zlog_debug("%s(%pI4): NH unresolved",
4220 __func__,
4221 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4222 }
9bcb3eef 4223 bgp_path_info_unset_flag(dest, pi,
18ee8310 4224 BGP_PATH_VALID);
d62a17ae 4225 }
4226 } else
9bcb3eef 4227 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4228
49e5a4a0 4229#ifdef ENABLE_BGP_VNC
d62a17ae 4230 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4231 struct bgp_dest *pdest = NULL;
d62a17ae 4232 struct bgp_table *table = NULL;
4233
9bcb3eef
DS
4234 pdest = bgp_node_get(bgp->rib[afi][safi],
4235 (struct prefix *)prd);
4236 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4237 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4238
4239 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4240 bgp, prd, table, p, pi);
d62a17ae 4241 }
9bcb3eef 4242 bgp_dest_unlock_node(pdest);
d62a17ae 4243 }
4244#endif
718e3744 4245
d62a17ae 4246 /* If this is an EVPN route and some attribute has changed,
9146341f 4247 * or we are explicitly told to perform a route import, process
d62a17ae 4248 * route for import. If the extended community has changed, we
4249 * would
4250 * have done the un-import earlier and the import would result
4251 * in the
4252 * route getting injected into appropriate L2 VNIs. If it is
4253 * just
4254 * some other attribute change, the import will result in
4255 * updating
4256 * the attributes for the route in the VNI(s).
4257 */
9146341f 4258 if (safi == SAFI_EVPN &&
4259 (!same_attr || force_evpn_import) &&
7c312383 4260 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4261 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4262
4263 /* Process change. */
40381db7 4264 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4265
9bcb3eef
DS
4266 bgp_process(bgp, dest, afi, safi);
4267 bgp_dest_unlock_node(dest);
558d1fec 4268
ddb5b488
PZ
4269 if (SAFI_UNICAST == safi
4270 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4271 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4272
40381db7 4273 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4274 }
4275 if ((SAFI_MPLS_VPN == safi)
4276 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4277
40381db7 4278 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4279 }
4280
49e5a4a0 4281#ifdef ENABLE_BGP_VNC
d62a17ae 4282 if (SAFI_MPLS_VPN == safi) {
4283 mpls_label_t label_decoded = decode_label(label);
28070ee3 4284
d62a17ae 4285 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4286 type, sub_type, &label_decoded);
4287 }
4288 if (SAFI_ENCAP == safi) {
4289 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4290 type, sub_type, NULL);
4291 }
28070ee3
PZ
4292#endif
4293
d62a17ae 4294 return 0;
4295 } // End of implicit withdraw
718e3744 4296
d62a17ae 4297 /* Received Logging. */
4298 if (bgp_debug_update(peer, p, NULL, 1)) {
4299 if (!peer->rcvd_attr_printed) {
4300 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4301 peer->rcvd_attr_str);
4302 peer->rcvd_attr_printed = 1;
4303 }
718e3744 4304
a4d82a8a 4305 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4306 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4307 pfx_buf, sizeof(pfx_buf));
d62a17ae 4308 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4309 }
718e3744 4310
d62a17ae 4311 /* Make new BGP info. */
9bcb3eef 4312 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4313
d62a17ae 4314 /* Update MPLS label */
4315 if (has_valid_label) {
18ee8310 4316 extra = bgp_path_info_extra_get(new);
8ba71050 4317 if (extra->label != label) {
dbd587da
QY
4318 memcpy(&extra->label, label,
4319 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4320 extra->num_labels = num_labels;
4321 }
b57ba6d2
MK
4322 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4323 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4324 }
718e3744 4325
e496b420
HS
4326 /* Update SRv6 SID */
4327 if (safi == SAFI_MPLS_VPN) {
4328 extra = bgp_path_info_extra_get(new);
4329 if (attr->srv6_l3vpn) {
16f3db2d 4330 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4331 extra->num_sids = 1;
cc8f05df 4332
16f3db2d
RS
4333 extra->sid[0].loc_block_len =
4334 attr->srv6_l3vpn->loc_block_len;
4335 extra->sid[0].loc_node_len =
4336 attr->srv6_l3vpn->loc_node_len;
4337 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4338 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
4339
cc8f05df
RS
4340 /*
4341 * draft-ietf-bess-srv6-services-07
4342 * The part of SRv6 SID may be encoded as MPLS Label for
4343 * the efficient packing.
4344 */
4345 if (attr->srv6_l3vpn->transposition_len != 0)
4346 transpose_sid(
16f3db2d 4347 &extra->sid[0].sid, decode_label(label),
cc8f05df
RS
4348 attr->srv6_l3vpn->transposition_offset,
4349 attr->srv6_l3vpn->transposition_len);
e496b420 4350 } else if (attr->srv6_vpn) {
16f3db2d 4351 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4352 extra->num_sids = 1;
4353 }
4354 }
4355
d62a17ae 4356 /* Nexthop reachability check. */
7c312383
AD
4357 if (((afi == AFI_IP || afi == AFI_IP6)
4358 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4359 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4360 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4361 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4362 && !CHECK_FLAG(peer->flags,
4363 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4364 && !CHECK_FLAG(bgp->flags,
4365 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4366 connected = 1;
4367 else
4368 connected = 0;
4369
7c312383
AD
4370 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4371
4053e952 4372 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4373 connected, p)
a4d82a8a 4374 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4375 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4376 else {
4377 if (BGP_DEBUG(nht, NHT)) {
4378 char buf1[INET6_ADDRSTRLEN];
4379 inet_ntop(AF_INET,
4380 (const void *)&attr_new->nexthop,
4381 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4382 zlog_debug("%s(%s): NH unresolved", __func__,
4383 buf1);
d62a17ae 4384 }
9bcb3eef 4385 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4386 }
4387 } else
9bcb3eef 4388 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4389
d62a17ae 4390 /* Addpath ID */
4391 new->addpath_rx_id = addpath_id;
4392
4393 /* Increment prefix */
4394 bgp_aggregate_increment(bgp, p, new, afi, safi);
4395
4396 /* Register new BGP information. */
9bcb3eef 4397 bgp_path_info_add(dest, new);
d62a17ae 4398
4399 /* route_node_get lock */
9bcb3eef 4400 bgp_dest_unlock_node(dest);
558d1fec 4401
49e5a4a0 4402#ifdef ENABLE_BGP_VNC
d62a17ae 4403 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4404 struct bgp_dest *pdest = NULL;
d62a17ae 4405 struct bgp_table *table = NULL;
4406
9bcb3eef
DS
4407 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4408 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4409 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4410
4411 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4412 bgp, prd, table, p, new);
4413 }
9bcb3eef 4414 bgp_dest_unlock_node(pdest);
d62a17ae 4415 }
65efcfce
LB
4416#endif
4417
d62a17ae 4418 /* If this is an EVPN route, process for import. */
7c312383 4419 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4420 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4421
9bcb3eef 4422 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4423
d62a17ae 4424 /* Process change. */
9bcb3eef 4425 bgp_process(bgp, dest, afi, safi);
718e3744 4426
ddb5b488
PZ
4427 if (SAFI_UNICAST == safi
4428 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4429 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4430 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4431 }
4432 if ((SAFI_MPLS_VPN == safi)
4433 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4434
4435 vpn_leak_to_vrf_update(bgp, new);
4436 }
49e5a4a0 4437#ifdef ENABLE_BGP_VNC
d62a17ae 4438 if (SAFI_MPLS_VPN == safi) {
4439 mpls_label_t label_decoded = decode_label(label);
28070ee3 4440
d62a17ae 4441 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4442 sub_type, &label_decoded);
4443 }
4444 if (SAFI_ENCAP == safi) {
4445 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4446 sub_type, NULL);
4447 }
28070ee3
PZ
4448#endif
4449
d62a17ae 4450 return 0;
718e3744 4451
d62a17ae 4452/* This BGP update is filtered. Log the reason then update BGP
4453 entry. */
4454filtered:
9bcb3eef 4455 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4456
d62a17ae 4457 if (bgp_debug_update(peer, p, NULL, 1)) {
4458 if (!peer->rcvd_attr_printed) {
4459 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4460 peer->rcvd_attr_str);
4461 peer->rcvd_attr_printed = 1;
4462 }
718e3744 4463
a4d82a8a 4464 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4465 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4466 pfx_buf, sizeof(pfx_buf));
d62a17ae 4467 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4468 peer->host, pfx_buf, reason);
4469 }
128ea8ab 4470
40381db7 4471 if (pi) {
d62a17ae 4472 /* If this is an EVPN route, un-import it as it is now filtered.
4473 */
4474 if (safi == SAFI_EVPN)
40381db7 4475 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4476
ddb5b488
PZ
4477 if (SAFI_UNICAST == safi
4478 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4479 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4480
40381db7 4481 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4482 }
4483 if ((SAFI_MPLS_VPN == safi)
4484 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4485
40381db7 4486 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4487 }
4488
9bcb3eef 4489 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4490 }
4491
9bcb3eef 4492 bgp_dest_unlock_node(dest);
558d1fec 4493
49e5a4a0 4494#ifdef ENABLE_BGP_VNC
d62a17ae 4495 /*
4496 * Filtered update is treated as an implicit withdrawal (see
4497 * bgp_rib_remove()
4498 * a few lines above)
4499 */
4500 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4501 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4502 0);
4503 }
97736e32
PZ
4504#endif
4505
d62a17ae 4506 return 0;
718e3744 4507}
4508
26a3ffd6 4509int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4510 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4511 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4512 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4513{
d62a17ae 4514 struct bgp *bgp;
4515 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4516 struct bgp_dest *dest;
40381db7 4517 struct bgp_path_info *pi;
718e3744 4518
49e5a4a0 4519#ifdef ENABLE_BGP_VNC
d62a17ae 4520 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4521 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4522 0);
4523 }
28070ee3
PZ
4524#endif
4525
d62a17ae 4526 bgp = peer->bgp;
4527
4528 /* Lookup node. */
9bcb3eef 4529 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4530
4531 /* If peer is soft reconfiguration enabled. Record input packet for
4532 * further calculation.
4533 *
4534 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4535 * routes that are filtered. This tanks out Quagga RS pretty badly due
4536 * to
4537 * the iteration over all RS clients.
4538 * Since we need to remove the entry from adj_in anyway, do that first
4539 * and
4540 * if there was no entry, we don't need to do anything more.
4541 */
4542 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4543 && peer != bgp->peer_self)
9bcb3eef 4544 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4545 peer->stat_pfx_dup_withdraw++;
4546
d62a17ae 4547 if (bgp_debug_update(peer, p, NULL, 1)) {
4548 bgp_debug_rdpfxpath2str(
a4d82a8a 4549 afi, safi, prd, p, label, num_labels,
6c995628
AD
4550 addpath_id ? 1 : 0, addpath_id, NULL,
4551 pfx_buf, sizeof(pfx_buf));
d62a17ae 4552 zlog_debug(
4553 "%s withdrawing route %s not in adj-in",
4554 peer->host, pfx_buf);
4555 }
9bcb3eef 4556 bgp_dest_unlock_node(dest);
d62a17ae 4557 return 0;
4558 }
cd808e74 4559
d62a17ae 4560 /* Lookup withdrawn route. */
9bcb3eef 4561 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4562 if (pi->peer == peer && pi->type == type
4563 && pi->sub_type == sub_type
4564 && pi->addpath_rx_id == addpath_id)
d62a17ae 4565 break;
4566
4567 /* Logging. */
4568 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4569 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4570 addpath_id ? 1 : 0, addpath_id, NULL,
4571 pfx_buf, sizeof(pfx_buf));
d62a17ae 4572 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4573 pfx_buf);
4574 }
718e3744 4575
d62a17ae 4576 /* Withdraw specified route from routing table. */
40381db7 4577 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4578 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4579 if (SAFI_UNICAST == safi
4580 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4581 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4582 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4583 }
4584 if ((SAFI_MPLS_VPN == safi)
4585 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4586
40381db7 4587 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4588 }
4589 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4590 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4591 addpath_id ? 1 : 0, addpath_id, NULL,
4592 pfx_buf, sizeof(pfx_buf));
d62a17ae 4593 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4594 }
718e3744 4595
d62a17ae 4596 /* Unlock bgp_node_get() lock. */
9bcb3eef 4597 bgp_dest_unlock_node(dest);
d62a17ae 4598
4599 return 0;
718e3744 4600}
6b0655a2 4601
d62a17ae 4602void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4603 int withdraw)
718e3744 4604{
d62a17ae 4605 struct update_subgroup *subgrp;
4606 subgrp = peer_subgroup(peer, afi, safi);
4607 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4608}
6182d65b 4609
718e3744 4610
3f9c7369
DS
4611/*
4612 * bgp_stop_announce_route_timer
4613 */
d62a17ae 4614void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4615{
d62a17ae 4616 if (!paf->t_announce_route)
4617 return;
4618
50478845 4619 thread_cancel(&paf->t_announce_route);
718e3744 4620}
6b0655a2 4621
3f9c7369
DS
4622/*
4623 * bgp_announce_route_timer_expired
4624 *
4625 * Callback that is invoked when the route announcement timer for a
4626 * peer_af expires.
4627 */
d62a17ae 4628static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4629{
d62a17ae 4630 struct peer_af *paf;
4631 struct peer *peer;
558d1fec 4632
d62a17ae 4633 paf = THREAD_ARG(t);
4634 peer = paf->peer;
718e3744 4635
feb17238 4636 if (!peer_established(peer))
d62a17ae 4637 return 0;
3f9c7369 4638
d62a17ae 4639 if (!peer->afc_nego[paf->afi][paf->safi])
4640 return 0;
3f9c7369 4641
d62a17ae 4642 peer_af_announce_route(paf, 1);
c5aec50b
MK
4643
4644 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4645 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4646
d62a17ae 4647 return 0;
718e3744 4648}
4649
3f9c7369
DS
4650/*
4651 * bgp_announce_route
4652 *
4653 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4654 *
4655 * if force is true we will force an update even if the update
4656 * limiting code is attempted to kick in.
3f9c7369 4657 */
e1a32ec1 4658void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4659{
4660 struct peer_af *paf;
4661 struct update_subgroup *subgrp;
4662
4663 paf = peer_af_find(peer, afi, safi);
4664 if (!paf)
4665 return;
4666 subgrp = PAF_SUBGRP(paf);
4667
4668 /*
4669 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4670 * or a refresh has already been triggered.
4671 */
4672 if (!subgrp || paf->t_announce_route)
4673 return;
4674
e1a32ec1
DS
4675 if (force)
4676 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4677
d62a17ae 4678 /*
4679 * Start a timer to stagger/delay the announce. This serves
4680 * two purposes - announcement can potentially be combined for
4681 * multiple peers and the announcement doesn't happen in the
4682 * vty context.
4683 */
4684 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4685 (subgrp->peer_count == 1)
4686 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4687 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4688 &paf->t_announce_route);
3f9c7369
DS
4689}
4690
4691/*
4692 * Announce routes from all AF tables to a peer.
4693 *
4694 * This should ONLY be called when there is a need to refresh the
4695 * routes to the peer based on a policy change for this peer alone
4696 * or a route refresh request received from the peer.
4697 * The operation will result in splitting the peer from its existing
4698 * subgroups and putting it in new subgroups.
4699 */
d62a17ae 4700void bgp_announce_route_all(struct peer *peer)
718e3744 4701{
d62a17ae 4702 afi_t afi;
4703 safi_t safi;
4704
05c7a1cc 4705 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4706 bgp_announce_route(peer, afi, safi, false);
718e3744 4707}
6b0655a2 4708
46aeabed
LS
4709/* Flag or unflag bgp_dest to determine whether it should be treated by
4710 * bgp_soft_reconfig_table_task.
4711 * Flag if flag is true. Unflag if flag is false.
4712 */
4713static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4714{
4715 struct bgp_dest *dest;
4716 struct bgp_adj_in *ain;
4717
4718 if (!table)
4719 return;
4720
4721 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4722 for (ain = dest->adj_in; ain; ain = ain->next) {
4723 if (ain->peer != NULL)
4724 break;
4725 }
4726 if (flag && ain != NULL && ain->peer != NULL)
4727 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4728 else
4729 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4730 }
4731}
4732
4733static int bgp_soft_reconfig_table_update(struct peer *peer,
4734 struct bgp_dest *dest,
4735 struct bgp_adj_in *ain, afi_t afi,
4736 safi_t safi, struct prefix_rd *prd)
4737{
4738 struct bgp_path_info *pi;
4739 uint32_t num_labels = 0;
4740 mpls_label_t *label_pnt = NULL;
4741 struct bgp_route_evpn evpn;
4742
4743 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4744 if (pi->peer == peer)
4745 break;
4746
4747 if (pi && pi->extra)
4748 num_labels = pi->extra->num_labels;
4749 if (num_labels)
4750 label_pnt = &pi->extra->label[0];
4751 if (pi)
4752 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4753 sizeof(evpn));
4754 else
4755 memset(&evpn, 0, sizeof(evpn));
4756
4757 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4758 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4759 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4760 &evpn);
4761}
4762
d62a17ae 4763static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4764 struct bgp_table *table,
4765 struct prefix_rd *prd)
718e3744 4766{
d62a17ae 4767 int ret;
9bcb3eef 4768 struct bgp_dest *dest;
d62a17ae 4769 struct bgp_adj_in *ain;
718e3744 4770
d62a17ae 4771 if (!table)
4772 table = peer->bgp->rib[afi][safi];
718e3744 4773
9bcb3eef
DS
4774 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4775 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4776 if (ain->peer != peer)
4777 continue;
8692c506 4778
46aeabed
LS
4779 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4780 afi, safi, prd);
ea47320b
DL
4781
4782 if (ret < 0) {
9bcb3eef 4783 bgp_dest_unlock_node(dest);
ea47320b 4784 return;
d62a17ae 4785 }
4786 }
718e3744 4787}
4788
46aeabed
LS
4789/* Do soft reconfig table per bgp table.
4790 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4791 * when BGP_NODE_SOFT_RECONFIG is set,
4792 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4793 * Schedule a new thread to continue the job.
4794 * Without splitting the full job into several part,
4795 * vtysh waits for the job to finish before responding to a BGP command
4796 */
4797static int bgp_soft_reconfig_table_task(struct thread *thread)
4798{
4799 uint32_t iter, max_iter;
4800 int ret;
4801 struct bgp_dest *dest;
4802 struct bgp_adj_in *ain;
4803 struct peer *peer;
4804 struct bgp_table *table;
4805 struct prefix_rd *prd;
4806 struct listnode *node, *nnode;
4807
4808 table = THREAD_ARG(thread);
4809 prd = NULL;
4810
4811 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4812 if (table->soft_reconfig_init) {
4813 /* first call of the function with a new srta structure.
4814 * Don't do any treatment this time on nodes
4815 * in order vtysh to respond quickly
4816 */
4817 max_iter = 0;
4818 }
4819
4820 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4821 dest = bgp_route_next(dest)) {
4822 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4823 continue;
4824
4825 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4826
4827 for (ain = dest->adj_in; ain; ain = ain->next) {
4828 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4829 nnode, peer)) {
4830 if (ain->peer != peer)
4831 continue;
4832
4833 ret = bgp_soft_reconfig_table_update(
4834 peer, dest, ain, table->afi,
4835 table->safi, prd);
4836 iter++;
4837
4838 if (ret < 0) {
4839 bgp_dest_unlock_node(dest);
4840 listnode_delete(
4841 table->soft_reconfig_peers,
4842 peer);
4843 bgp_announce_route(peer, table->afi,
e1a32ec1 4844 table->safi, false);
46aeabed
LS
4845 if (list_isempty(
4846 table->soft_reconfig_peers)) {
4847 list_delete(
4848 &table->soft_reconfig_peers);
4849 bgp_soft_reconfig_table_flag(
4850 table, false);
4851 return 0;
4852 }
4853 }
4854 }
4855 }
4856 }
4857
4858 /* we're either starting the initial iteration,
4859 * or we're going to continue an ongoing iteration
4860 */
4861 if (dest || table->soft_reconfig_init) {
4862 table->soft_reconfig_init = false;
4863 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4864 table, 0, &table->soft_reconfig_thread);
4865 return 0;
4866 }
4867 /* we're done, clean up the background iteration context info and
4868 schedule route annoucement
4869 */
4870 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4871 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 4872 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
4873 }
4874
4875 list_delete(&table->soft_reconfig_peers);
4876
4877 return 0;
4878}
4879
4880
4881/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4882 * and peer.
4883 * - bgp cannot be NULL
4884 * - if table and peer are NULL, cancel all threads within the bgp instance
4885 * - if table is NULL and peer is not,
4886 * remove peer in all threads within the bgp instance
4887 * - if peer is NULL, cancel all threads matching table within the bgp instance
4888 */
4889void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4890 const struct bgp_table *table,
4891 const struct peer *peer)
4892{
4893 struct peer *npeer;
4894 struct listnode *node, *nnode;
4895 int afi, safi;
4896 struct bgp_table *ntable;
4897
4898 if (!bgp)
4899 return;
4900
4901 FOREACH_AFI_SAFI (afi, safi) {
4902 ntable = bgp->rib[afi][safi];
4903 if (!ntable)
4904 continue;
4905 if (table && table != ntable)
4906 continue;
4907
4908 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4909 npeer)) {
4910 if (peer && peer != npeer)
4911 continue;
4912 listnode_delete(ntable->soft_reconfig_peers, npeer);
4913 }
4914
4915 if (!ntable->soft_reconfig_peers
4916 || !list_isempty(ntable->soft_reconfig_peers))
4917 continue;
4918
4919 list_delete(&ntable->soft_reconfig_peers);
4920 bgp_soft_reconfig_table_flag(ntable, false);
4921 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4922 }
4923}
4924
d62a17ae 4925void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4926{
9bcb3eef 4927 struct bgp_dest *dest;
d62a17ae 4928 struct bgp_table *table;
46aeabed
LS
4929 struct listnode *node, *nnode;
4930 struct peer *npeer;
4931 struct peer_af *paf;
718e3744 4932
feb17238 4933 if (!peer_established(peer))
d62a17ae 4934 return;
718e3744 4935
d62a17ae 4936 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
4937 && (safi != SAFI_EVPN)) {
4938 table = peer->bgp->rib[afi][safi];
4939 if (!table)
4940 return;
4941
4942 table->soft_reconfig_init = true;
4943
4944 if (!table->soft_reconfig_peers)
4945 table->soft_reconfig_peers = list_new();
4946 npeer = NULL;
4947 /* add peer to the table soft_reconfig_peers if not already
4948 * there
4949 */
4950 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
4951 npeer)) {
4952 if (peer == npeer)
4953 break;
4954 }
4955 if (peer != npeer)
4956 listnode_add(table->soft_reconfig_peers, peer);
4957
4958 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4959 * on table would start back at the beginning.
4960 */
4961 bgp_soft_reconfig_table_flag(table, true);
4962
4963 if (!table->soft_reconfig_thread)
4964 thread_add_event(bm->master,
4965 bgp_soft_reconfig_table_task, table, 0,
4966 &table->soft_reconfig_thread);
4967 /* Cancel bgp_announce_route_timer_expired threads.
4968 * bgp_announce_route_timer_expired threads have been scheduled
4969 * to announce routes as soon as the soft_reconfigure process
4970 * finishes.
4971 * In this case, soft_reconfigure is also scheduled by using
4972 * a thread but is planned after the
4973 * bgp_announce_route_timer_expired threads. It means that,
4974 * without cancelling the threads, the route announcement task
4975 * would run before the soft reconfiguration one. That would
4976 * useless and would block vtysh during several seconds. Route
4977 * announcements are rescheduled as soon as the soft_reconfigure
4978 * process finishes.
4979 */
4980 paf = peer_af_find(peer, afi, safi);
4981 if (paf)
4982 bgp_stop_announce_route_timer(paf);
4983 } else
9bcb3eef
DS
4984 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4985 dest = bgp_route_next(dest)) {
4986 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4987
b54892e0
DS
4988 if (table == NULL)
4989 continue;
8692c506 4990
9bcb3eef 4991 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4992 struct prefix_rd prd;
4993
4994 prd.family = AF_UNSPEC;
4995 prd.prefixlen = 64;
4996 memcpy(&prd.val, p->u.val, 8);
4997
4998 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4999 }
718e3744 5000}
6b0655a2 5001
228da428 5002
d62a17ae 5003struct bgp_clear_node_queue {
9bcb3eef 5004 struct bgp_dest *dest;
228da428
CC
5005};
5006
d62a17ae 5007static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5008{
d62a17ae 5009 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5010 struct bgp_dest *dest = cnq->dest;
d62a17ae 5011 struct peer *peer = wq->spec.data;
40381db7 5012 struct bgp_path_info *pi;
3103e8d2 5013 struct bgp *bgp;
9bcb3eef
DS
5014 afi_t afi = bgp_dest_table(dest)->afi;
5015 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5016
9bcb3eef 5017 assert(dest && peer);
3103e8d2 5018 bgp = peer->bgp;
d62a17ae 5019
5020 /* It is possible that we have multiple paths for a prefix from a peer
5021 * if that peer is using AddPath.
5022 */
9bcb3eef 5023 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5024 if (pi->peer != peer)
ea47320b
DL
5025 continue;
5026
5027 /* graceful restart STALE flag set. */
9af52ccf
DA
5028 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5029 && peer->nsf[afi][safi])
5030 || CHECK_FLAG(peer->af_sflags[afi][safi],
5031 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5032 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5033 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5034 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5035 else {
5036 /* If this is an EVPN route, process for
5037 * un-import. */
5038 if (safi == SAFI_EVPN)
9bcb3eef
DS
5039 bgp_evpn_unimport_route(
5040 bgp, afi, safi,
5041 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5042 /* Handle withdraw for VRF route-leaking and L3VPN */
5043 if (SAFI_UNICAST == safi
5044 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5045 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5046 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5047 bgp, pi);
960035b2 5048 }
3103e8d2 5049 if (SAFI_MPLS_VPN == safi &&
960035b2 5050 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5051 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5052 }
3103e8d2 5053
9bcb3eef 5054 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5055 }
ea47320b 5056 }
d62a17ae 5057 return WQ_SUCCESS;
200df115 5058}
5059
d62a17ae 5060static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5061{
d62a17ae 5062 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5063 struct bgp_dest *dest = cnq->dest;
5064 struct bgp_table *table = bgp_dest_table(dest);
228da428 5065
9bcb3eef 5066 bgp_dest_unlock_node(dest);
d62a17ae 5067 bgp_table_unlock(table);
5068 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5069}
5070
d62a17ae 5071static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5072{
d62a17ae 5073 struct peer *peer = wq->spec.data;
64e580a7 5074
d62a17ae 5075 /* Tickle FSM to start moving again */
5076 BGP_EVENT_ADD(peer, Clearing_Completed);
5077
5078 peer_unlock(peer); /* bgp_clear_route */
200df115 5079}
718e3744 5080
d62a17ae 5081static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5082{
d62a17ae 5083 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5084
5085 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5086#undef CLEAR_QUEUE_NAME_LEN
5087
0ce1ca80 5088 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5089 peer->clear_node_queue->spec.hold = 10;
5090 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5091 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5092 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5093 peer->clear_node_queue->spec.max_retries = 0;
5094
5095 /* we only 'lock' this peer reference when the queue is actually active
5096 */
5097 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5098}
5099
d62a17ae 5100static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5101 struct bgp_table *table)
65ca75e0 5102{
9bcb3eef 5103 struct bgp_dest *dest;
b6c386bb 5104 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5105
d62a17ae 5106 if (!table)
5107 table = peer->bgp->rib[afi][safi];
dc83d712 5108
d62a17ae 5109 /* If still no table => afi/safi isn't configured at all or smth. */
5110 if (!table)
5111 return;
dc83d712 5112
9bcb3eef 5113 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5114 struct bgp_path_info *pi, *next;
d62a17ae 5115 struct bgp_adj_in *ain;
5116 struct bgp_adj_in *ain_next;
5117
5118 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5119 * queued for every clearing peer, regardless of whether it is
5120 * relevant to the peer at hand.
5121 *
5122 * Overview: There are 3 different indices which need to be
5123 * scrubbed, potentially, when a peer is removed:
5124 *
5125 * 1 peer's routes visible via the RIB (ie accepted routes)
5126 * 2 peer's routes visible by the (optional) peer's adj-in index
5127 * 3 other routes visible by the peer's adj-out index
5128 *
5129 * 3 there is no hurry in scrubbing, once the struct peer is
5130 * removed from bgp->peer, we could just GC such deleted peer's
5131 * adj-outs at our leisure.
5132 *
5133 * 1 and 2 must be 'scrubbed' in some way, at least made
5134 * invisible via RIB index before peer session is allowed to be
5135 * brought back up. So one needs to know when such a 'search' is
5136 * complete.
5137 *
5138 * Ideally:
5139 *
5140 * - there'd be a single global queue or a single RIB walker
5141 * - rather than tracking which route_nodes still need to be
5142 * examined on a peer basis, we'd track which peers still
5143 * aren't cleared
5144 *
5145 * Given that our per-peer prefix-counts now should be reliable,
5146 * this may actually be achievable. It doesn't seem to be a huge
5147 * problem at this time,
5148 *
5149 * It is possible that we have multiple paths for a prefix from
5150 * a peer
5151 * if that peer is using AddPath.
5152 */
9bcb3eef 5153 ain = dest->adj_in;
d62a17ae 5154 while (ain) {
5155 ain_next = ain->next;
5156
6a840fd9 5157 if (ain->peer == peer)
9bcb3eef 5158 bgp_adj_in_remove(dest, ain);
d62a17ae 5159
5160 ain = ain_next;
5161 }
5162
9bcb3eef 5163 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5164 next = pi->next;
5165 if (pi->peer != peer)
d62a17ae 5166 continue;
5167
5168 if (force)
9bcb3eef 5169 bgp_path_info_reap(dest, pi);
d62a17ae 5170 else {
5171 struct bgp_clear_node_queue *cnq;
5172
5173 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5174 bgp_table_lock(bgp_dest_table(dest));
5175 bgp_dest_lock_node(dest);
d62a17ae 5176 cnq = XCALLOC(
5177 MTYPE_BGP_CLEAR_NODE_QUEUE,
5178 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5179 cnq->dest = dest;
d62a17ae 5180 work_queue_add(peer->clear_node_queue, cnq);
5181 break;
5182 }
5183 }
5184 }
5185 return;
5186}
5187
5188void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5189{
9bcb3eef 5190 struct bgp_dest *dest;
d62a17ae 5191 struct bgp_table *table;
5192
5193 if (peer->clear_node_queue == NULL)
5194 bgp_clear_node_queue_init(peer);
5195
5196 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5197 * Idle until it receives a Clearing_Completed event. This protects
5198 * against peers which flap faster than we can we clear, which could
5199 * lead to:
5200 *
5201 * a) race with routes from the new session being installed before
5202 * clear_route_node visits the node (to delete the route of that
5203 * peer)
5204 * b) resource exhaustion, clear_route_node likely leads to an entry
5205 * on the process_main queue. Fast-flapping could cause that queue
5206 * to grow and grow.
5207 */
5208
5209 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5210 * the unlock will happen upon work-queue completion; other wise, the
5211 * unlock happens at the end of this function.
5212 */
5213 if (!peer->clear_node_queue->thread)
5214 peer_lock(peer);
5215
5216 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5217 bgp_clear_route_table(peer, afi, safi, NULL);
5218 else
9bcb3eef
DS
5219 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5220 dest = bgp_route_next(dest)) {
5221 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5222 if (!table)
5223 continue;
5224
5225 bgp_clear_route_table(peer, afi, safi, table);
5226 }
d62a17ae 5227
5228 /* unlock if no nodes got added to the clear-node-queue. */
5229 if (!peer->clear_node_queue->thread)
5230 peer_unlock(peer);
718e3744 5231}
d62a17ae 5232
5233void bgp_clear_route_all(struct peer *peer)
718e3744 5234{
d62a17ae 5235 afi_t afi;
5236 safi_t safi;
718e3744 5237
05c7a1cc
QY
5238 FOREACH_AFI_SAFI (afi, safi)
5239 bgp_clear_route(peer, afi, safi);
65efcfce 5240
49e5a4a0 5241#ifdef ENABLE_BGP_VNC
d62a17ae 5242 rfapiProcessPeerDown(peer);
65efcfce 5243#endif
718e3744 5244}
5245
d62a17ae 5246void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5247{
d62a17ae 5248 struct bgp_table *table;
9bcb3eef 5249 struct bgp_dest *dest;
d62a17ae 5250 struct bgp_adj_in *ain;
5251 struct bgp_adj_in *ain_next;
718e3744 5252
d62a17ae 5253 table = peer->bgp->rib[afi][safi];
718e3744 5254
d62a17ae 5255 /* It is possible that we have multiple paths for a prefix from a peer
5256 * if that peer is using AddPath.
5257 */
9bcb3eef
DS
5258 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5259 ain = dest->adj_in;
43143c8f 5260
d62a17ae 5261 while (ain) {
5262 ain_next = ain->next;
43143c8f 5263
6a840fd9 5264 if (ain->peer == peer)
9bcb3eef 5265 bgp_adj_in_remove(dest, ain);
43143c8f 5266
d62a17ae 5267 ain = ain_next;
5268 }
5269 }
718e3744 5270}
93406d87 5271
d62a17ae 5272void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5273{
9bcb3eef 5274 struct bgp_dest *dest;
40381db7 5275 struct bgp_path_info *pi;
d62a17ae 5276 struct bgp_table *table;
5277
9af52ccf 5278 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5279 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5280 dest = bgp_route_next(dest)) {
5281 struct bgp_dest *rm;
d62a17ae 5282
5283 /* look for neighbor in tables */
9bcb3eef 5284 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5285 if (!table)
ea47320b
DL
5286 continue;
5287
5288 for (rm = bgp_table_top(table); rm;
5289 rm = bgp_route_next(rm))
9bcb3eef 5290 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5291 pi = pi->next) {
40381db7 5292 if (pi->peer != peer)
ea47320b 5293 continue;
40381db7 5294 if (!CHECK_FLAG(pi->flags,
1defdda8 5295 BGP_PATH_STALE))
ea47320b
DL
5296 break;
5297
40381db7 5298 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5299 break;
5300 }
d62a17ae 5301 }
5302 } else {
9bcb3eef
DS
5303 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5304 dest = bgp_route_next(dest))
5305 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5306 pi = pi->next) {
40381db7 5307 if (pi->peer != peer)
ea47320b 5308 continue;
40381db7 5309 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 5310 break;
9bcb3eef 5311 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5312 break;
5313 }
d62a17ae 5314 }
93406d87 5315}
6b0655a2 5316
9af52ccf
DA
5317void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5318{
5319 struct bgp_dest *dest, *ndest;
5320 struct bgp_path_info *pi;
5321 struct bgp_table *table;
5322
5323 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5324 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5325 dest = bgp_route_next(dest)) {
5326 table = bgp_dest_get_bgp_table_info(dest);
5327 if (!table)
5328 continue;
5329
5330 for (ndest = bgp_table_top(table); ndest;
5331 ndest = bgp_route_next(ndest)) {
5332 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5333 pi = pi->next) {
5334 if (pi->peer != peer)
5335 continue;
5336
5337 if ((CHECK_FLAG(
5338 peer->af_sflags[afi][safi],
5339 PEER_STATUS_ENHANCED_REFRESH))
5340 && !CHECK_FLAG(pi->flags,
5341 BGP_PATH_STALE)
5342 && !CHECK_FLAG(
5343 pi->flags,
5344 BGP_PATH_UNUSEABLE)) {
5345 if (bgp_debug_neighbor_events(
5346 peer))
5347 zlog_debug(
5348 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5349 peer->host,
5350 afi2str(afi),
5351 safi2str(safi),
5352 bgp_dest_get_prefix(
5353 ndest));
5354
5355 bgp_path_info_set_flag(
5356 ndest, pi,
5357 BGP_PATH_STALE);
5358 }
5359 }
5360 }
5361 }
5362 } else {
5363 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5364 dest = bgp_route_next(dest)) {
5365 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5366 pi = pi->next) {
5367 if (pi->peer != peer)
5368 continue;
5369
5370 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5371 PEER_STATUS_ENHANCED_REFRESH))
5372 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5373 && !CHECK_FLAG(pi->flags,
5374 BGP_PATH_UNUSEABLE)) {
5375 if (bgp_debug_neighbor_events(peer))
5376 zlog_debug(
5377 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5378 peer->host,
5379 afi2str(afi),
5380 safi2str(safi),
5381 bgp_dest_get_prefix(
5382 dest));
5383
5384 bgp_path_info_set_flag(dest, pi,
5385 BGP_PATH_STALE);
5386 }
5387 }
5388 }
5389 }
5390}
5391
3dc339cd 5392bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5393{
e0df4c04 5394 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5395 return true;
e0df4c04 5396
9dac9fc8
DA
5397 if (peer->sort == BGP_PEER_EBGP
5398 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5399 || FILTER_LIST_OUT_NAME(filter)
5400 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5401 return true;
5402 return false;
9dac9fc8
DA
5403}
5404
3dc339cd 5405bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5406{
e0df4c04 5407 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5408 return true;
e0df4c04 5409
9dac9fc8
DA
5410 if (peer->sort == BGP_PEER_EBGP
5411 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5412 || FILTER_LIST_IN_NAME(filter)
5413 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5414 return true;
5415 return false;
9dac9fc8
DA
5416}
5417
568e10ca 5418static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5419 safi_t safi)
bb86c601 5420{
9bcb3eef 5421 struct bgp_dest *dest;
40381db7 5422 struct bgp_path_info *pi;
4b7e6066 5423 struct bgp_path_info *next;
bb86c601 5424
9bcb3eef
DS
5425 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5426 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5427 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5428
40381db7 5429 next = pi->next;
1b7bb747
CS
5430
5431 /* Unimport EVPN routes from VRFs */
5432 if (safi == SAFI_EVPN)
5433 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5434 SAFI_EVPN, p, pi);
1b7bb747 5435
40381db7
DS
5436 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5437 && pi->type == ZEBRA_ROUTE_BGP
5438 && (pi->sub_type == BGP_ROUTE_NORMAL
5439 || pi->sub_type == BGP_ROUTE_AGGREGATE
5440 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5441
d62a17ae 5442 if (bgp_fibupd_safi(safi))
b54892e0 5443 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5444 }
9514b37d 5445
9bcb3eef 5446 bgp_path_info_reap(dest, pi);
d62a17ae 5447 }
bb86c601
LB
5448}
5449
718e3744 5450/* Delete all kernel routes. */
d62a17ae 5451void bgp_cleanup_routes(struct bgp *bgp)
5452{
5453 afi_t afi;
9bcb3eef 5454 struct bgp_dest *dest;
67009e22 5455 struct bgp_table *table;
d62a17ae 5456
5457 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5458 if (afi == AFI_L2VPN)
5459 continue;
568e10ca 5460 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5461 SAFI_UNICAST);
d62a17ae 5462 /*
5463 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5464 */
5465 if (afi != AFI_L2VPN) {
5466 safi_t safi;
5467 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5468 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5469 dest = bgp_route_next(dest)) {
5470 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5471 if (table != NULL) {
5472 bgp_cleanup_table(bgp, table, safi);
5473 bgp_table_finish(&table);
9bcb3eef
DS
5474 bgp_dest_set_bgp_table_info(dest, NULL);
5475 bgp_dest_unlock_node(dest);
d62a17ae 5476 }
5477 }
5478 safi = SAFI_ENCAP;
9bcb3eef
DS
5479 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5480 dest = bgp_route_next(dest)) {
5481 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5482 if (table != NULL) {
5483 bgp_cleanup_table(bgp, table, safi);
5484 bgp_table_finish(&table);
9bcb3eef
DS
5485 bgp_dest_set_bgp_table_info(dest, NULL);
5486 bgp_dest_unlock_node(dest);
d62a17ae 5487 }
5488 }
5489 }
5490 }
9bcb3eef
DS
5491 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5492 dest = bgp_route_next(dest)) {
5493 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5494 if (table != NULL) {
5495 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5496 bgp_table_finish(&table);
9bcb3eef
DS
5497 bgp_dest_set_bgp_table_info(dest, NULL);
5498 bgp_dest_unlock_node(dest);
d62a17ae 5499 }
bb86c601 5500 }
718e3744 5501}
5502
d62a17ae 5503void bgp_reset(void)
718e3744 5504{
d62a17ae 5505 vty_reset();
5506 bgp_zclient_reset();
5507 access_list_reset();
5508 prefix_list_reset();
718e3744 5509}
6b0655a2 5510
d62a17ae 5511static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5512{
d62a17ae 5513 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5514 && CHECK_FLAG(peer->af_cap[afi][safi],
5515 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5516}
5517
718e3744 5518/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5519 value. */
d62a17ae 5520int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5521 struct bgp_nlri *packet)
5522{
d7c0a89a
QY
5523 uint8_t *pnt;
5524 uint8_t *lim;
d62a17ae 5525 struct prefix p;
5526 int psize;
5527 int ret;
5528 afi_t afi;
5529 safi_t safi;
5530 int addpath_encoded;
d7c0a89a 5531 uint32_t addpath_id;
d62a17ae 5532
d62a17ae 5533 pnt = packet->nlri;
5534 lim = pnt + packet->length;
5535 afi = packet->afi;
5536 safi = packet->safi;
5537 addpath_id = 0;
5538 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5539
5540 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5541 syntactic validity. If the field is syntactically incorrect,
5542 then the Error Subcode is set to Invalid Network Field. */
5543 for (; pnt < lim; pnt += psize) {
5544 /* Clear prefix structure. */
5545 memset(&p, 0, sizeof(struct prefix));
5546
5547 if (addpath_encoded) {
5548
5549 /* When packet overflow occurs return immediately. */
761ed665 5550 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5551 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5552
a3a850a1 5553 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5554 addpath_id = ntohl(addpath_id);
d62a17ae 5555 pnt += BGP_ADDPATH_ID_LEN;
5556 }
718e3744 5557
d62a17ae 5558 /* Fetch prefix length. */
5559 p.prefixlen = *pnt++;
5560 /* afi/safi validity already verified by caller,
5561 * bgp_update_receive */
5562 p.family = afi2family(afi);
5563
5564 /* Prefix length check. */
5565 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5566 flog_err(
e50f7cfd 5567 EC_BGP_UPDATE_RCV,
14454c9f 5568 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5569 peer->host, p.prefixlen, packet->afi);
513386b5 5570 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5571 }
6b0655a2 5572
d62a17ae 5573 /* Packet size overflow check. */
5574 psize = PSIZE(p.prefixlen);
5575
5576 /* When packet overflow occur return immediately. */
5577 if (pnt + psize > lim) {
af4c2728 5578 flog_err(
e50f7cfd 5579 EC_BGP_UPDATE_RCV,
d62a17ae 5580 "%s [Error] Update packet error (prefix length %d overflows packet)",
5581 peer->host, p.prefixlen);
513386b5 5582 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5583 }
5584
5585 /* Defensive coding, double-check the psize fits in a struct
5586 * prefix */
5587 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5588 flog_err(
e50f7cfd 5589 EC_BGP_UPDATE_RCV,
d62a17ae 5590 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5591 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5592 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5593 }
5594
5595 /* Fetch prefix from NLRI packet. */
a85297a7 5596 memcpy(p.u.val, pnt, psize);
d62a17ae 5597
5598 /* Check address. */
5599 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5600 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5601 /* From RFC4271 Section 6.3:
5602 *
5603 * If a prefix in the NLRI field is semantically
5604 * incorrect
5605 * (e.g., an unexpected multicast IP address),
5606 * an error SHOULD
5607 * be logged locally, and the prefix SHOULD be
5608 * ignored.
a4d82a8a 5609 */
af4c2728 5610 flog_err(
e50f7cfd 5611 EC_BGP_UPDATE_RCV,
23d0a753
DA
5612 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5613 peer->host, &p.u.prefix4);
d62a17ae 5614 continue;
5615 }
5616 }
5617
5618 /* Check address. */
5619 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5620 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5621 flog_err(
e50f7cfd 5622 EC_BGP_UPDATE_RCV,
c0d72166
DS
5623 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5624 peer->host, &p.u.prefix6);
d62a17ae 5625
5626 continue;
5627 }
5628 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5629 flog_err(
e50f7cfd 5630 EC_BGP_UPDATE_RCV,
c0d72166
DS
5631 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5632 peer->host, &p.u.prefix6);
d62a17ae 5633
5634 continue;
5635 }
5636 }
5637
5638 /* Normal process. */
5639 if (attr)
5640 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5641 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5642 NULL, NULL, 0, 0, NULL);
d62a17ae 5643 else
5644 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5645 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5646 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5647 NULL);
d62a17ae 5648
513386b5
DA
5649 /* Do not send BGP notification twice when maximum-prefix count
5650 * overflow. */
5651 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5652 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5653
5654 /* Address family configuration mismatch. */
d62a17ae 5655 if (ret < 0)
513386b5 5656 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5657 }
5658
5659 /* Packet length consistency check. */
5660 if (pnt != lim) {
af4c2728 5661 flog_err(
e50f7cfd 5662 EC_BGP_UPDATE_RCV,
d62a17ae 5663 "%s [Error] Update packet error (prefix length mismatch with total length)",
5664 peer->host);
513386b5 5665 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5666 }
6b0655a2 5667
513386b5 5668 return BGP_NLRI_PARSE_OK;
718e3744 5669}
5670
d62a17ae 5671static struct bgp_static *bgp_static_new(void)
718e3744 5672{
d62a17ae 5673 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5674}
5675
d62a17ae 5676static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5677{
0a22ddfb 5678 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5679 route_map_counter_decrement(bgp_static->rmap.map);
5680
0a22ddfb 5681 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5682 XFREE(MTYPE_BGP_STATIC, bgp_static);
5683}
5684
5f040085 5685void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5686 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5687{
9bcb3eef 5688 struct bgp_dest *dest;
40381db7 5689 struct bgp_path_info *pi;
4b7e6066 5690 struct bgp_path_info *new;
40381db7 5691 struct bgp_path_info rmap_path;
d62a17ae 5692 struct attr attr;
5693 struct attr *attr_new;
b68885f9 5694 route_map_result_t ret;
49e5a4a0 5695#ifdef ENABLE_BGP_VNC
d62a17ae 5696 int vnc_implicit_withdraw = 0;
65efcfce 5697#endif
fee0f4c6 5698
d62a17ae 5699 assert(bgp_static);
dd8103a9 5700
9bcb3eef 5701 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5702
d62a17ae 5703 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5704
d62a17ae 5705 attr.nexthop = bgp_static->igpnexthop;
5706 attr.med = bgp_static->igpmetric;
5707 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5708
d62a17ae 5709 if (bgp_static->atomic)
5710 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5711
d62a17ae 5712 /* Store label index, if required. */
5713 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5714 attr.label_index = bgp_static->label_index;
5715 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5716 }
718e3744 5717
d62a17ae 5718 /* Apply route-map. */
5719 if (bgp_static->rmap.name) {
5720 struct attr attr_tmp = attr;
80ced710 5721
40381db7
DS
5722 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5723 rmap_path.peer = bgp->peer_self;
5724 rmap_path.attr = &attr_tmp;
fee0f4c6 5725
d62a17ae 5726 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5727
1782514f 5728 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5729
d62a17ae 5730 bgp->peer_self->rmap_type = 0;
718e3744 5731
d62a17ae 5732 if (ret == RMAP_DENYMATCH) {
5733 /* Free uninterned attribute. */
5734 bgp_attr_flush(&attr_tmp);
718e3744 5735
d62a17ae 5736 /* Unintern original. */
5737 aspath_unintern(&attr.aspath);
5738 bgp_static_withdraw(bgp, p, afi, safi);
5739 return;
5740 }
7f323236 5741
637e5ba4 5742 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5743 bgp_attr_add_gshut_community(&attr_tmp);
5744
d62a17ae 5745 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5746 } else {
5747
637e5ba4 5748 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5749 bgp_attr_add_gshut_community(&attr);
5750
d62a17ae 5751 attr_new = bgp_attr_intern(&attr);
7f323236 5752 }
718e3744 5753
9bcb3eef 5754 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5755 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5756 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5757 break;
5758
40381db7
DS
5759 if (pi) {
5760 if (attrhash_cmp(pi->attr, attr_new)
5761 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5762 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5763 bgp_dest_unlock_node(dest);
d62a17ae 5764 bgp_attr_unintern(&attr_new);
5765 aspath_unintern(&attr.aspath);
5766 return;
5767 } else {
5768 /* The attribute is changed. */
9bcb3eef 5769 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5770
5771 /* Rewrite BGP route information. */
40381db7 5772 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5773 bgp_path_info_restore(dest, pi);
d62a17ae 5774 else
40381db7 5775 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5776#ifdef ENABLE_BGP_VNC
d62a17ae 5777 if ((afi == AFI_IP || afi == AFI_IP6)
5778 && (safi == SAFI_UNICAST)) {
40381db7 5779 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5780 /*
5781 * Implicit withdraw case.
40381db7 5782 * We have to do this before pi is
d62a17ae 5783 * changed
5784 */
5785 ++vnc_implicit_withdraw;
40381db7 5786 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5787 vnc_import_bgp_exterior_del_route(
40381db7 5788 bgp, p, pi);
d62a17ae 5789 }
5790 }
65efcfce 5791#endif
40381db7
DS
5792 bgp_attr_unintern(&pi->attr);
5793 pi->attr = attr_new;
5794 pi->uptime = bgp_clock();
49e5a4a0 5795#ifdef ENABLE_BGP_VNC
d62a17ae 5796 if ((afi == AFI_IP || afi == AFI_IP6)
5797 && (safi == SAFI_UNICAST)) {
5798 if (vnc_implicit_withdraw) {
40381db7 5799 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5800 vnc_import_bgp_exterior_add_route(
40381db7 5801 bgp, p, pi);
d62a17ae 5802 }
5803 }
65efcfce 5804#endif
718e3744 5805
d62a17ae 5806 /* Nexthop reachability check. */
892fedb6 5807 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5808 && (safi == SAFI_UNICAST
5809 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5810
5811 struct bgp *bgp_nexthop = bgp;
5812
40381db7
DS
5813 if (pi->extra && pi->extra->bgp_orig)
5814 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5815
5816 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5817 afi, safi, pi, NULL,
654a5978 5818 0, p))
9bcb3eef 5819 bgp_path_info_set_flag(dest, pi,
18ee8310 5820 BGP_PATH_VALID);
d62a17ae 5821 else {
5822 if (BGP_DEBUG(nht, NHT)) {
5823 char buf1[INET6_ADDRSTRLEN];
5824 inet_ntop(p->family,
5825 &p->u.prefix, buf1,
5826 INET6_ADDRSTRLEN);
5827 zlog_debug(
5828 "%s(%s): Route not in table, not advertising",
15569c58 5829 __func__, buf1);
d62a17ae 5830 }
18ee8310 5831 bgp_path_info_unset_flag(
9bcb3eef 5832 dest, pi, BGP_PATH_VALID);
d62a17ae 5833 }
5834 } else {
5835 /* Delete the NHT structure if any, if we're
5836 * toggling between
5837 * enabling/disabling import check. We
5838 * deregister the route
5839 * from NHT to avoid overloading NHT and the
5840 * process interaction
5841 */
40381db7 5842 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5843 bgp_path_info_set_flag(dest, pi,
5844 BGP_PATH_VALID);
d62a17ae 5845 }
5846 /* Process change. */
40381db7 5847 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5848 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5849
5850 if (SAFI_UNICAST == safi
5851 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5852 || bgp->inst_type
5853 == BGP_INSTANCE_TYPE_DEFAULT)) {
5854 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5855 pi);
ddb5b488
PZ
5856 }
5857
9bcb3eef 5858 bgp_dest_unlock_node(dest);
d62a17ae 5859 aspath_unintern(&attr.aspath);
5860 return;
5861 }
718e3744 5862 }
718e3744 5863
d62a17ae 5864 /* Make new BGP info. */
5865 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5866 attr_new, dest);
d62a17ae 5867 /* Nexthop reachability check. */
892fedb6 5868 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5869 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5870 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5871 p))
9bcb3eef 5872 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5873 else {
5874 if (BGP_DEBUG(nht, NHT)) {
5875 char buf1[INET6_ADDRSTRLEN];
5876 inet_ntop(p->family, &p->u.prefix, buf1,
5877 INET6_ADDRSTRLEN);
5878 zlog_debug(
5879 "%s(%s): Route not in table, not advertising",
15569c58 5880 __func__, buf1);
d62a17ae 5881 }
9bcb3eef 5882 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5883 }
5884 } else {
5885 /* Delete the NHT structure if any, if we're toggling between
5886 * enabling/disabling import check. We deregister the route
5887 * from NHT to avoid overloading NHT and the process interaction
5888 */
5889 bgp_unlink_nexthop(new);
5890
9bcb3eef 5891 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5892 }
078430f6 5893
d62a17ae 5894 /* Aggregate address increment. */
5895 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5896
d62a17ae 5897 /* Register new BGP information. */
9bcb3eef 5898 bgp_path_info_add(dest, new);
718e3744 5899
d62a17ae 5900 /* route_node_get lock */
9bcb3eef 5901 bgp_dest_unlock_node(dest);
d62a17ae 5902
5903 /* Process change. */
9bcb3eef 5904 bgp_process(bgp, dest, afi, safi);
d62a17ae 5905
ddb5b488
PZ
5906 if (SAFI_UNICAST == safi
5907 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5908 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5909 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5910 }
5911
d62a17ae 5912 /* Unintern original. */
5913 aspath_unintern(&attr.aspath);
718e3744 5914}
5915
5f040085 5916void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5917 safi_t safi)
718e3744 5918{
9bcb3eef 5919 struct bgp_dest *dest;
40381db7 5920 struct bgp_path_info *pi;
718e3744 5921
9bcb3eef 5922 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5923
d62a17ae 5924 /* Check selected route and self inserted route. */
9bcb3eef 5925 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5926 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5927 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5928 break;
5929
5930 /* Withdraw static BGP route from routing table. */
40381db7 5931 if (pi) {
ddb5b488
PZ
5932 if (SAFI_UNICAST == safi
5933 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5934 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5935 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5936 }
40381db7
DS
5937 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5938 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5939 bgp_path_info_delete(dest, pi);
5940 bgp_process(bgp, dest, afi, safi);
d62a17ae 5941 }
718e3744 5942
d62a17ae 5943 /* Unlock bgp_node_lookup. */
9bcb3eef 5944 bgp_dest_unlock_node(dest);
718e3744 5945}
5946
137446f9
LB
5947/*
5948 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5949 */
5f040085 5950static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5951 afi_t afi, safi_t safi,
5952 struct prefix_rd *prd)
718e3744 5953{
9bcb3eef 5954 struct bgp_dest *dest;
40381db7 5955 struct bgp_path_info *pi;
718e3744 5956
9bcb3eef 5957 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5958
d62a17ae 5959 /* Check selected route and self inserted route. */
9bcb3eef 5960 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5961 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5962 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5963 break;
718e3744 5964
d62a17ae 5965 /* Withdraw static BGP route from routing table. */
40381db7 5966 if (pi) {
49e5a4a0 5967#ifdef ENABLE_BGP_VNC
d62a17ae 5968 rfapiProcessWithdraw(
40381db7 5969 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5970 1); /* Kill, since it is an administrative change */
65efcfce 5971#endif
ddb5b488
PZ
5972 if (SAFI_MPLS_VPN == safi
5973 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5974 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5975 }
40381db7 5976 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5977 bgp_path_info_delete(dest, pi);
5978 bgp_process(bgp, dest, afi, safi);
d62a17ae 5979 }
718e3744 5980
d62a17ae 5981 /* Unlock bgp_node_lookup. */
9bcb3eef 5982 bgp_dest_unlock_node(dest);
718e3744 5983}
5984
5f040085 5985static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5986 struct bgp_static *bgp_static, afi_t afi,
5987 safi_t safi)
137446f9 5988{
9bcb3eef 5989 struct bgp_dest *dest;
4b7e6066 5990 struct bgp_path_info *new;
d62a17ae 5991 struct attr *attr_new;
5992 struct attr attr = {0};
40381db7 5993 struct bgp_path_info *pi;
49e5a4a0 5994#ifdef ENABLE_BGP_VNC
d62a17ae 5995 mpls_label_t label = 0;
65efcfce 5996#endif
d7c0a89a 5997 uint32_t num_labels = 0;
d62a17ae 5998 union gw_addr add;
137446f9 5999
d62a17ae 6000 assert(bgp_static);
137446f9 6001
b57ba6d2
MK
6002 if (bgp_static->label != MPLS_INVALID_LABEL)
6003 num_labels = 1;
9bcb3eef
DS
6004 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6005 &bgp_static->prd);
137446f9 6006
d62a17ae 6007 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 6008
d62a17ae 6009 attr.nexthop = bgp_static->igpnexthop;
6010 attr.med = bgp_static->igpmetric;
6011 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6012
d62a17ae 6013 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6014 || (safi == SAFI_ENCAP)) {
6015 if (afi == AFI_IP) {
6016 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6017 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6018 }
6019 }
6020 if (afi == AFI_L2VPN) {
6021 if (bgp_static->gatewayIp.family == AF_INET)
6022 add.ipv4.s_addr =
6023 bgp_static->gatewayIp.u.prefix4.s_addr;
6024 else if (bgp_static->gatewayIp.family == AF_INET6)
6025 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
6026 sizeof(struct in6_addr));
0a50c248 6027 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6028 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6029 struct bgp_encap_type_vxlan bet;
6030 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 6031 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6032 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6033 }
6034 if (bgp_static->router_mac) {
6035 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6036 }
6037 }
6038 /* Apply route-map. */
6039 if (bgp_static->rmap.name) {
6040 struct attr attr_tmp = attr;
40381db7 6041 struct bgp_path_info rmap_path;
b68885f9 6042 route_map_result_t ret;
137446f9 6043
40381db7
DS
6044 rmap_path.peer = bgp->peer_self;
6045 rmap_path.attr = &attr_tmp;
137446f9 6046
d62a17ae 6047 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6048
1782514f 6049 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6050
d62a17ae 6051 bgp->peer_self->rmap_type = 0;
137446f9 6052
d62a17ae 6053 if (ret == RMAP_DENYMATCH) {
6054 /* Free uninterned attribute. */
6055 bgp_attr_flush(&attr_tmp);
137446f9 6056
d62a17ae 6057 /* Unintern original. */
6058 aspath_unintern(&attr.aspath);
6059 bgp_static_withdraw_safi(bgp, p, afi, safi,
6060 &bgp_static->prd);
6061 return;
6062 }
137446f9 6063
d62a17ae 6064 attr_new = bgp_attr_intern(&attr_tmp);
6065 } else {
6066 attr_new = bgp_attr_intern(&attr);
6067 }
137446f9 6068
9bcb3eef 6069 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6070 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6071 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6072 break;
6073
40381db7 6074 if (pi) {
d62a17ae 6075 memset(&add, 0, sizeof(union gw_addr));
40381db7 6076 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 6077 && overlay_index_equal(afi, pi, &add)
40381db7 6078 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6079 bgp_dest_unlock_node(dest);
d62a17ae 6080 bgp_attr_unintern(&attr_new);
6081 aspath_unintern(&attr.aspath);
6082 return;
6083 } else {
6084 /* The attribute is changed. */
9bcb3eef 6085 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6086
6087 /* Rewrite BGP route information. */
40381db7 6088 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6089 bgp_path_info_restore(dest, pi);
d62a17ae 6090 else
40381db7
DS
6091 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6092 bgp_attr_unintern(&pi->attr);
6093 pi->attr = attr_new;
6094 pi->uptime = bgp_clock();
49e5a4a0 6095#ifdef ENABLE_BGP_VNC
40381db7
DS
6096 if (pi->extra)
6097 label = decode_label(&pi->extra->label[0]);
65efcfce 6098#endif
137446f9 6099
d62a17ae 6100 /* Process change. */
40381db7 6101 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6102 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6103
6104 if (SAFI_MPLS_VPN == safi
6105 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6106 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6107 }
49e5a4a0 6108#ifdef ENABLE_BGP_VNC
40381db7
DS
6109 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6110 pi->attr, afi, safi, pi->type,
6111 pi->sub_type, &label);
65efcfce 6112#endif
9bcb3eef 6113 bgp_dest_unlock_node(dest);
d62a17ae 6114 aspath_unintern(&attr.aspath);
6115 return;
6116 }
6117 }
137446f9
LB
6118
6119
d62a17ae 6120 /* Make new BGP info. */
6121 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6122 attr_new, dest);
1defdda8 6123 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 6124 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
6125 if (num_labels) {
6126 new->extra->label[0] = bgp_static->label;
6127 new->extra->num_labels = num_labels;
6128 }
49e5a4a0 6129#ifdef ENABLE_BGP_VNC
d62a17ae 6130 label = decode_label(&bgp_static->label);
65efcfce 6131#endif
137446f9 6132
d62a17ae 6133 /* Aggregate address increment. */
6134 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6135
d62a17ae 6136 /* Register new BGP information. */
9bcb3eef 6137 bgp_path_info_add(dest, new);
d62a17ae 6138 /* route_node_get lock */
9bcb3eef 6139 bgp_dest_unlock_node(dest);
137446f9 6140
d62a17ae 6141 /* Process change. */
9bcb3eef 6142 bgp_process(bgp, dest, afi, safi);
137446f9 6143
ddb5b488
PZ
6144 if (SAFI_MPLS_VPN == safi
6145 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6146 vpn_leak_to_vrf_update(bgp, new);
6147 }
49e5a4a0 6148#ifdef ENABLE_BGP_VNC
d62a17ae 6149 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6150 safi, new->type, new->sub_type, &label);
65efcfce
LB
6151#endif
6152
d62a17ae 6153 /* Unintern original. */
6154 aspath_unintern(&attr.aspath);
137446f9
LB
6155}
6156
718e3744 6157/* Configure static BGP network. When user don't run zebra, static
6158 route should be installed as valid. */
585f1adc
IR
6159static int bgp_static_set(struct vty *vty, const char *negate,
6160 const char *ip_str, afi_t afi, safi_t safi,
6161 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6162{
585f1adc
IR
6163 VTY_DECLVAR_CONTEXT(bgp, bgp);
6164 int ret;
d62a17ae 6165 struct prefix p;
6166 struct bgp_static *bgp_static;
9bcb3eef 6167 struct bgp_dest *dest;
d7c0a89a 6168 uint8_t need_update = 0;
d62a17ae 6169
585f1adc
IR
6170 /* Convert IP prefix string to struct prefix. */
6171 ret = str2prefix(ip_str, &p);
6172 if (!ret) {
6173 vty_out(vty, "%% Malformed prefix\n");
6174 return CMD_WARNING_CONFIG_FAILED;
6175 }
6176 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6177 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6178 return CMD_WARNING_CONFIG_FAILED;
6179 }
6180
d62a17ae 6181 apply_mask(&p);
718e3744 6182
e2a86ad9 6183 if (negate) {
718e3744 6184
e2a86ad9 6185 /* Set BGP static route configuration. */
9bcb3eef 6186 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6187
9bcb3eef 6188 if (!dest) {
585f1adc
IR
6189 vty_out(vty, "%% Can't find static route specified\n");
6190 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6191 }
6192
9bcb3eef 6193 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6194
e2a86ad9
DS
6195 if ((label_index != BGP_INVALID_LABEL_INDEX)
6196 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6197 vty_out(vty,
6198 "%% label-index doesn't match static route\n");
70d9b134 6199 bgp_dest_unlock_node(dest);
585f1adc 6200 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6201 }
d62a17ae 6202
e2a86ad9
DS
6203 if ((rmap && bgp_static->rmap.name)
6204 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6205 vty_out(vty,
6206 "%% route-map name doesn't match static route\n");
70d9b134 6207 bgp_dest_unlock_node(dest);
585f1adc 6208 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6209 }
718e3744 6210
e2a86ad9
DS
6211 /* Update BGP RIB. */
6212 if (!bgp_static->backdoor)
6213 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6214
e2a86ad9
DS
6215 /* Clear configuration. */
6216 bgp_static_free(bgp_static);
9bcb3eef
DS
6217 bgp_dest_set_bgp_static_info(dest, NULL);
6218 bgp_dest_unlock_node(dest);
6219 bgp_dest_unlock_node(dest);
e2a86ad9 6220 } else {
718e3744 6221
e2a86ad9 6222 /* Set BGP static route configuration. */
9bcb3eef
DS
6223 dest = bgp_node_get(bgp->route[afi][safi], &p);
6224 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6225 if (bgp_static) {
e2a86ad9 6226 /* Configuration change. */
e2a86ad9
DS
6227 /* Label index cannot be changed. */
6228 if (bgp_static->label_index != label_index) {
585f1adc
IR
6229 vty_out(vty, "%% cannot change label-index\n");
6230 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6231 }
d62a17ae 6232
e2a86ad9 6233 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6234 if (bgp_static->valid
6235 && bgp_static->backdoor != backdoor)
e2a86ad9 6236 need_update = 1;
718e3744 6237
e2a86ad9 6238 bgp_static->backdoor = backdoor;
718e3744 6239
e2a86ad9 6240 if (rmap) {
0a22ddfb
QY
6241 XFREE(MTYPE_ROUTE_MAP_NAME,
6242 bgp_static->rmap.name);
b4897fa5 6243 route_map_counter_decrement(
6244 bgp_static->rmap.map);
e2a86ad9
DS
6245 bgp_static->rmap.name =
6246 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6247 bgp_static->rmap.map =
6248 route_map_lookup_by_name(rmap);
b4897fa5 6249 route_map_counter_increment(
6250 bgp_static->rmap.map);
e2a86ad9 6251 } else {
0a22ddfb
QY
6252 XFREE(MTYPE_ROUTE_MAP_NAME,
6253 bgp_static->rmap.name);
b4897fa5 6254 route_map_counter_decrement(
6255 bgp_static->rmap.map);
e2a86ad9
DS
6256 bgp_static->rmap.map = NULL;
6257 bgp_static->valid = 0;
6258 }
9bcb3eef 6259 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6260 } else {
6261 /* New configuration. */
6262 bgp_static = bgp_static_new();
6263 bgp_static->backdoor = backdoor;
6264 bgp_static->valid = 0;
6265 bgp_static->igpmetric = 0;
975a328e 6266 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6267 bgp_static->label_index = label_index;
718e3744 6268
e2a86ad9 6269 if (rmap) {
0a22ddfb
QY
6270 XFREE(MTYPE_ROUTE_MAP_NAME,
6271 bgp_static->rmap.name);
b4897fa5 6272 route_map_counter_decrement(
6273 bgp_static->rmap.map);
e2a86ad9
DS
6274 bgp_static->rmap.name =
6275 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6276 bgp_static->rmap.map =
6277 route_map_lookup_by_name(rmap);
b4897fa5 6278 route_map_counter_increment(
6279 bgp_static->rmap.map);
e2a86ad9 6280 }
9bcb3eef 6281 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6282 }
d62a17ae 6283
e2a86ad9
DS
6284 bgp_static->valid = 1;
6285 if (need_update)
6286 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6287
e2a86ad9
DS
6288 if (!bgp_static->backdoor)
6289 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6290 }
d62a17ae 6291
585f1adc 6292 return CMD_SUCCESS;
d62a17ae 6293}
6294
6295void bgp_static_add(struct bgp *bgp)
6296{
6297 afi_t afi;
6298 safi_t safi;
9bcb3eef
DS
6299 struct bgp_dest *dest;
6300 struct bgp_dest *rm;
d62a17ae 6301 struct bgp_table *table;
6302 struct bgp_static *bgp_static;
6303
47fc6261 6304 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6305 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6306 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6307 dest = bgp_route_next(dest)) {
6308 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6309 continue;
ea47320b 6310
05c7a1cc
QY
6311 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6312 || (safi == SAFI_EVPN)) {
9bcb3eef 6313 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6314
6315 for (rm = bgp_table_top(table); rm;
6316 rm = bgp_route_next(rm)) {
a78beeb5 6317 bgp_static =
9bcb3eef 6318 bgp_dest_get_bgp_static_info(
5a8ba9fc 6319 rm);
9bcb3eef
DS
6320 bgp_static_update_safi(
6321 bgp, bgp_dest_get_prefix(rm),
6322 bgp_static, afi, safi);
d62a17ae 6323 }
05c7a1cc 6324 } else {
5a8ba9fc 6325 bgp_static_update(
9bcb3eef
DS
6326 bgp, bgp_dest_get_prefix(dest),
6327 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6328 safi);
ea47320b 6329 }
05c7a1cc 6330 }
47fc6261 6331 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6332}
6333
718e3744 6334/* Called from bgp_delete(). Delete all static routes from the BGP
6335 instance. */
d62a17ae 6336void bgp_static_delete(struct bgp *bgp)
6337{
6338 afi_t afi;
6339 safi_t safi;
9bcb3eef
DS
6340 struct bgp_dest *dest;
6341 struct bgp_dest *rm;
d62a17ae 6342 struct bgp_table *table;
6343 struct bgp_static *bgp_static;
6344
05c7a1cc 6345 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6346 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6347 dest = bgp_route_next(dest)) {
6348 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6349 continue;
ea47320b 6350
05c7a1cc
QY
6351 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6352 || (safi == SAFI_EVPN)) {
9bcb3eef 6353 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6354
6355 for (rm = bgp_table_top(table); rm;
6356 rm = bgp_route_next(rm)) {
a78beeb5 6357 bgp_static =
9bcb3eef 6358 bgp_dest_get_bgp_static_info(
5a8ba9fc 6359 rm);
c7d14ba6
PG
6360 if (!bgp_static)
6361 continue;
6362
05c7a1cc 6363 bgp_static_withdraw_safi(
9bcb3eef 6364 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6365 AFI_IP, safi,
6366 (struct prefix_rd *)
9bcb3eef
DS
6367 bgp_dest_get_prefix(
6368 dest));
ea47320b 6369 bgp_static_free(bgp_static);
811c6797 6370 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6371 NULL);
811c6797 6372 bgp_dest_unlock_node(rm);
d62a17ae 6373 }
05c7a1cc 6374 } else {
9bcb3eef 6375 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6376 bgp_static_withdraw(bgp,
9bcb3eef 6377 bgp_dest_get_prefix(dest),
b54892e0 6378 afi, safi);
05c7a1cc 6379 bgp_static_free(bgp_static);
9bcb3eef
DS
6380 bgp_dest_set_bgp_static_info(dest, NULL);
6381 bgp_dest_unlock_node(dest);
ea47320b 6382 }
05c7a1cc 6383 }
d62a17ae 6384}
6385
6386void bgp_static_redo_import_check(struct bgp *bgp)
6387{
6388 afi_t afi;
6389 safi_t safi;
9bcb3eef
DS
6390 struct bgp_dest *dest;
6391 struct bgp_dest *rm;
d62a17ae 6392 struct bgp_table *table;
6393 struct bgp_static *bgp_static;
6394
6395 /* Use this flag to force reprocessing of the route */
892fedb6 6396 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6397 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6398 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6399 dest = bgp_route_next(dest)) {
6400 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6401 continue;
ea47320b 6402
05c7a1cc
QY
6403 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6404 || (safi == SAFI_EVPN)) {
9bcb3eef 6405 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6406
6407 for (rm = bgp_table_top(table); rm;
6408 rm = bgp_route_next(rm)) {
a78beeb5 6409 bgp_static =
9bcb3eef 6410 bgp_dest_get_bgp_static_info(
5a8ba9fc 6411 rm);
9bcb3eef
DS
6412 bgp_static_update_safi(
6413 bgp, bgp_dest_get_prefix(rm),
6414 bgp_static, afi, safi);
d62a17ae 6415 }
05c7a1cc 6416 } else {
9bcb3eef
DS
6417 bgp_static = bgp_dest_get_bgp_static_info(dest);
6418 bgp_static_update(bgp,
6419 bgp_dest_get_prefix(dest),
6420 bgp_static, afi, safi);
ea47320b 6421 }
05c7a1cc
QY
6422 }
6423 }
892fedb6 6424 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6425}
6426
6427static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6428 safi_t safi)
6429{
6430 struct bgp_table *table;
9bcb3eef 6431 struct bgp_dest *dest;
40381db7 6432 struct bgp_path_info *pi;
d62a17ae 6433
dfb6fd1d
NT
6434 /* Do not install the aggregate route if BGP is in the
6435 * process of termination.
6436 */
892fedb6
DA
6437 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6438 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6439 return;
6440
d62a17ae 6441 table = bgp->rib[afi][safi];
9bcb3eef
DS
6442 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6443 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6444 if (pi->peer == bgp->peer_self
6445 && ((pi->type == ZEBRA_ROUTE_BGP
6446 && pi->sub_type == BGP_ROUTE_STATIC)
6447 || (pi->type != ZEBRA_ROUTE_BGP
6448 && pi->sub_type
d62a17ae 6449 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6450 bgp_aggregate_decrement(
6451 bgp, bgp_dest_get_prefix(dest), pi, afi,
6452 safi);
40381db7 6453 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6454 bgp_path_info_delete(dest, pi);
6455 bgp_process(bgp, dest, afi, safi);
d62a17ae 6456 }
6457 }
6458 }
ad4cbda1 6459}
6460
6461/*
6462 * Purge all networks and redistributed routes from routing table.
6463 * Invoked upon the instance going down.
6464 */
d62a17ae 6465void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6466{
d62a17ae 6467 afi_t afi;
6468 safi_t safi;
ad4cbda1 6469
05c7a1cc
QY
6470 FOREACH_AFI_SAFI (afi, safi)
6471 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6472}
6473
137446f9
LB
6474/*
6475 * gpz 110624
6476 * Currently this is used to set static routes for VPN and ENCAP.
6477 * I think it can probably be factored with bgp_static_set.
6478 */
d62a17ae 6479int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6480 const char *ip_str, const char *rd_str,
6481 const char *label_str, const char *rmap_str,
6482 int evpn_type, const char *esi, const char *gwip,
6483 const char *ethtag, const char *routermac)
6484{
6485 VTY_DECLVAR_CONTEXT(bgp, bgp);
6486 int ret;
6487 struct prefix p;
6488 struct prefix_rd prd;
9bcb3eef
DS
6489 struct bgp_dest *pdest;
6490 struct bgp_dest *dest;
d62a17ae 6491 struct bgp_table *table;
6492 struct bgp_static *bgp_static;
6493 mpls_label_t label = MPLS_INVALID_LABEL;
6494 struct prefix gw_ip;
6495
6496 /* validate ip prefix */
6497 ret = str2prefix(ip_str, &p);
6498 if (!ret) {
6499 vty_out(vty, "%% Malformed prefix\n");
6500 return CMD_WARNING_CONFIG_FAILED;
6501 }
6502 apply_mask(&p);
6503 if ((afi == AFI_L2VPN)
6504 && (bgp_build_evpn_prefix(evpn_type,
6505 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6506 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6507 return CMD_WARNING_CONFIG_FAILED;
6508 }
718e3744 6509
d62a17ae 6510 ret = str2prefix_rd(rd_str, &prd);
6511 if (!ret) {
6512 vty_out(vty, "%% Malformed rd\n");
6513 return CMD_WARNING_CONFIG_FAILED;
6514 }
718e3744 6515
d62a17ae 6516 if (label_str) {
6517 unsigned long label_val;
6518 label_val = strtoul(label_str, NULL, 10);
6519 encode_label(label_val, &label);
6520 }
9bedbb1e 6521
d62a17ae 6522 if (safi == SAFI_EVPN) {
6523 if (esi && str2esi(esi, NULL) == 0) {
6524 vty_out(vty, "%% Malformed ESI\n");
6525 return CMD_WARNING_CONFIG_FAILED;
6526 }
6527 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6528 vty_out(vty, "%% Malformed Router MAC\n");
6529 return CMD_WARNING_CONFIG_FAILED;
6530 }
6531 if (gwip) {
6532 memset(&gw_ip, 0, sizeof(struct prefix));
6533 ret = str2prefix(gwip, &gw_ip);
6534 if (!ret) {
6535 vty_out(vty, "%% Malformed GatewayIp\n");
6536 return CMD_WARNING_CONFIG_FAILED;
6537 }
6538 if ((gw_ip.family == AF_INET
3714a385 6539 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6540 (struct prefix_evpn *)&p))
6541 || (gw_ip.family == AF_INET6
3714a385 6542 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6543 (struct prefix_evpn *)&p))) {
6544 vty_out(vty,
6545 "%% GatewayIp family differs with IP prefix\n");
6546 return CMD_WARNING_CONFIG_FAILED;
6547 }
6548 }
6549 }
9bcb3eef
DS
6550 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6551 if (!bgp_dest_has_bgp_path_info_data(pdest))
6552 bgp_dest_set_bgp_table_info(pdest,
67009e22 6553 bgp_table_init(bgp, afi, safi));
9bcb3eef 6554 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6555
9bcb3eef 6556 dest = bgp_node_get(table, &p);
d62a17ae 6557
9bcb3eef 6558 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6559 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6560 bgp_dest_unlock_node(dest);
d62a17ae 6561 } else {
6562 /* New configuration. */
6563 bgp_static = bgp_static_new();
6564 bgp_static->backdoor = 0;
6565 bgp_static->valid = 0;
6566 bgp_static->igpmetric = 0;
975a328e 6567 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6568 bgp_static->label = label;
6569 bgp_static->prd = prd;
6570
6571 if (rmap_str) {
0a22ddfb 6572 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6573 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6574 bgp_static->rmap.name =
6575 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6576 bgp_static->rmap.map =
6577 route_map_lookup_by_name(rmap_str);
b4897fa5 6578 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6579 }
718e3744 6580
d62a17ae 6581 if (safi == SAFI_EVPN) {
6582 if (esi) {
6583 bgp_static->eth_s_id =
6584 XCALLOC(MTYPE_ATTR,
0a50c248 6585 sizeof(esi_t));
d62a17ae 6586 str2esi(esi, bgp_static->eth_s_id);
6587 }
6588 if (routermac) {
6589 bgp_static->router_mac =
28328ea9 6590 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6591 (void)prefix_str2mac(routermac,
6592 bgp_static->router_mac);
d62a17ae 6593 }
6594 if (gwip)
6595 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6596 }
9bcb3eef 6597 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6598
d62a17ae 6599 bgp_static->valid = 1;
6600 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6601 }
718e3744 6602
d62a17ae 6603 return CMD_SUCCESS;
718e3744 6604}
6605
6606/* Configure static BGP network. */
d62a17ae 6607int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6608 const char *ip_str, const char *rd_str,
6609 const char *label_str, int evpn_type, const char *esi,
6610 const char *gwip, const char *ethtag)
6611{
6612 VTY_DECLVAR_CONTEXT(bgp, bgp);
6613 int ret;
6614 struct prefix p;
6615 struct prefix_rd prd;
9bcb3eef
DS
6616 struct bgp_dest *pdest;
6617 struct bgp_dest *dest;
d62a17ae 6618 struct bgp_table *table;
6619 struct bgp_static *bgp_static;
6620 mpls_label_t label = MPLS_INVALID_LABEL;
6621
6622 /* Convert IP prefix string to struct prefix. */
6623 ret = str2prefix(ip_str, &p);
6624 if (!ret) {
6625 vty_out(vty, "%% Malformed prefix\n");
6626 return CMD_WARNING_CONFIG_FAILED;
6627 }
6628 apply_mask(&p);
6629 if ((afi == AFI_L2VPN)
6630 && (bgp_build_evpn_prefix(evpn_type,
6631 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6632 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6633 return CMD_WARNING_CONFIG_FAILED;
6634 }
6635 ret = str2prefix_rd(rd_str, &prd);
6636 if (!ret) {
6637 vty_out(vty, "%% Malformed rd\n");
6638 return CMD_WARNING_CONFIG_FAILED;
6639 }
718e3744 6640
d62a17ae 6641 if (label_str) {
6642 unsigned long label_val;
6643 label_val = strtoul(label_str, NULL, 10);
6644 encode_label(label_val, &label);
6645 }
718e3744 6646
9bcb3eef
DS
6647 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6648 if (!bgp_dest_has_bgp_path_info_data(pdest))
6649 bgp_dest_set_bgp_table_info(pdest,
67009e22 6650 bgp_table_init(bgp, afi, safi));
d62a17ae 6651 else
9bcb3eef
DS
6652 bgp_dest_unlock_node(pdest);
6653 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6654
9bcb3eef 6655 dest = bgp_node_lookup(table, &p);
6b0655a2 6656
9bcb3eef 6657 if (dest) {
d62a17ae 6658 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6659
9bcb3eef 6660 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6661 bgp_static_free(bgp_static);
9bcb3eef
DS
6662 bgp_dest_set_bgp_static_info(dest, NULL);
6663 bgp_dest_unlock_node(dest);
6664 bgp_dest_unlock_node(dest);
d62a17ae 6665 } else
6666 vty_out(vty, "%% Can't find the route\n");
6667
6668 return CMD_SUCCESS;
6669}
6670
6671static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6672 const char *rmap_name)
6673{
6674 VTY_DECLVAR_CONTEXT(bgp, bgp);
6675 struct bgp_rmap *rmap;
6676
6677 rmap = &bgp->table_map[afi][safi];
6678 if (rmap_name) {
0a22ddfb 6679 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6680 route_map_counter_decrement(rmap->map);
d62a17ae 6681 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6682 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6683 route_map_counter_increment(rmap->map);
d62a17ae 6684 } else {
0a22ddfb 6685 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6686 route_map_counter_decrement(rmap->map);
d62a17ae 6687 rmap->map = NULL;
6688 }
73ac8160 6689
d62a17ae 6690 if (bgp_fibupd_safi(safi))
6691 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6692
d62a17ae 6693 return CMD_SUCCESS;
73ac8160
DS
6694}
6695
d62a17ae 6696static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6697 const char *rmap_name)
73ac8160 6698{
d62a17ae 6699 VTY_DECLVAR_CONTEXT(bgp, bgp);
6700 struct bgp_rmap *rmap;
73ac8160 6701
d62a17ae 6702 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6703 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6704 route_map_counter_decrement(rmap->map);
d62a17ae 6705 rmap->map = NULL;
73ac8160 6706
d62a17ae 6707 if (bgp_fibupd_safi(safi))
6708 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6709
d62a17ae 6710 return CMD_SUCCESS;
73ac8160
DS
6711}
6712
2b791107 6713void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6714 safi_t safi)
73ac8160 6715{
d62a17ae 6716 if (bgp->table_map[afi][safi].name) {
d62a17ae 6717 vty_out(vty, " table-map %s\n",
6718 bgp->table_map[afi][safi].name);
6719 }
73ac8160
DS
6720}
6721
73ac8160
DS
6722DEFUN (bgp_table_map,
6723 bgp_table_map_cmd,
6724 "table-map WORD",
6725 "BGP table to RIB route download filter\n"
6726 "Name of the route map\n")
6727{
d62a17ae 6728 int idx_word = 1;
6729 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6730 argv[idx_word]->arg);
73ac8160
DS
6731}
6732DEFUN (no_bgp_table_map,
6733 no_bgp_table_map_cmd,
6734 "no table-map WORD",
3a2d747c 6735 NO_STR
73ac8160
DS
6736 "BGP table to RIB route download filter\n"
6737 "Name of the route map\n")
6738{
d62a17ae 6739 int idx_word = 2;
6740 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6741 argv[idx_word]->arg);
73ac8160
DS
6742}
6743
585f1adc
IR
6744DEFPY(bgp_network,
6745 bgp_network_cmd,
6746 "[no] network \
6747 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6748 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6749 backdoor$backdoor}]",
6750 NO_STR
6751 "Specify a network to announce via BGP\n"
6752 "IPv4 prefix\n"
6753 "Network number\n"
6754 "Network mask\n"
6755 "Network mask\n"
6756 "Route-map to modify the attributes\n"
6757 "Name of the route map\n"
6758 "Label index to associate with the prefix\n"
6759 "Label index value\n"
6760 "Specify a BGP backdoor route\n")
6761{
6762 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6763
6764 if (address_str) {
6765 int ret;
718e3744 6766
e2a86ad9 6767 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6768 addr_prefix_str,
6769 sizeof(addr_prefix_str));
e2a86ad9
DS
6770 if (!ret) {
6771 vty_out(vty, "%% Inconsistent address and mask\n");
6772 return CMD_WARNING_CONFIG_FAILED;
6773 }
d62a17ae 6774 }
718e3744 6775
585f1adc
IR
6776 return bgp_static_set(
6777 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6778 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6779 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6780}
6781
585f1adc
IR
6782DEFPY(ipv6_bgp_network,
6783 ipv6_bgp_network_cmd,
6784 "[no] network X:X::X:X/M$prefix \
6785 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6786 NO_STR
6787 "Specify a network to announce via BGP\n"
6788 "IPv6 prefix\n"
6789 "Route-map to modify the attributes\n"
6790 "Name of the route map\n"
6791 "Label index to associate with the prefix\n"
6792 "Label index value\n")
37a87b8f 6793{
585f1adc
IR
6794 return bgp_static_set(
6795 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6796 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6797}
6798
d62a17ae 6799static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6800{
d62a17ae 6801 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6802}
6803
d62a17ae 6804static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6805{
365ab2e7
RZ
6806 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6807 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6808 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6809 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6810 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6811}
718e3744 6812
365ab2e7
RZ
6813/**
6814 * Helper function to avoid repeated code: prepare variables for a
6815 * `route_map_apply` call.
6816 *
6817 * \returns `true` on route map match, otherwise `false`.
6818 */
6819static bool aggr_suppress_map_test(struct bgp *bgp,
6820 struct bgp_aggregate *aggregate,
6821 struct bgp_path_info *pi)
6822{
6823 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6824 route_map_result_t rmr = RMAP_DENYMATCH;
6825 struct bgp_path_info rmap_path = {};
6826 struct attr attr = {};
6827
6828 /* No route map entries created, just don't match. */
6829 if (aggregate->suppress_map == NULL)
6830 return false;
6831
6832 /* Call route map matching and return result. */
6833 attr.aspath = aspath_empty();
6834 rmap_path.peer = bgp->peer_self;
6835 rmap_path.attr = &attr;
6836
6837 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6838 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6839 bgp->peer_self->rmap_type = 0;
6840
6841 bgp_attr_flush(&attr);
6842
6843 return rmr == RMAP_PERMITMATCH;
6844}
6845
4056a5f6
RZ
6846/** Test whether the aggregation has suppressed this path or not. */
6847static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6848 struct bgp_path_info *pi)
6849{
6850 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6851 return false;
6852
6853 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6854}
6855
6856/**
6857 * Suppress this path and keep the reference.
6858 *
6859 * \returns `true` if needs processing otherwise `false`.
6860 */
6861static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6862 struct bgp_path_info *pi)
6863{
6864 struct bgp_path_info_extra *pie;
6865
6866 /* Path is already suppressed by this aggregation. */
6867 if (aggr_suppress_exists(aggregate, pi))
6868 return false;
6869
6870 pie = bgp_path_info_extra_get(pi);
6871
6872 /* This is the first suppression, allocate memory and list it. */
6873 if (pie->aggr_suppressors == NULL)
6874 pie->aggr_suppressors = list_new();
6875
6876 listnode_add(pie->aggr_suppressors, aggregate);
6877
6878 /* Only mark for processing if suppressed. */
6879 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6880 if (BGP_DEBUG(update, UPDATE_OUT))
6881 zlog_debug("aggregate-address suppressing: %pFX",
6882 bgp_dest_get_prefix(pi->net));
6883
4056a5f6
RZ
6884 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6885 return true;
6886 }
6887
6888 return false;
6889}
6890
6891/**
6892 * Unsuppress this path and remove the reference.
6893 *
6894 * \returns `true` if needs processing otherwise `false`.
6895 */
6896static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6897 struct bgp_path_info *pi)
6898{
6899 /* Path wasn't suppressed. */
6900 if (!aggr_suppress_exists(aggregate, pi))
6901 return false;
6902
6903 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6904
6905 /* Unsuppress and free extra memory if last item. */
6906 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6907 if (BGP_DEBUG(update, UPDATE_OUT))
6908 zlog_debug("aggregate-address unsuppressing: %pFX",
6909 bgp_dest_get_prefix(pi->net));
6910
4056a5f6
RZ
6911 list_delete(&pi->extra->aggr_suppressors);
6912 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6913 return true;
6914 }
6915
6916 return false;
6917}
6918
3dc339cd
DA
6919static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6920 struct aspath *aspath,
6921 struct community *comm,
6922 struct ecommunity *ecomm,
6923 struct lcommunity *lcomm)
eaaf8adb
DS
6924{
6925 static struct aspath *ae = NULL;
6926
6927 if (!ae)
6928 ae = aspath_empty();
6929
40381db7 6930 if (!pi)
3dc339cd 6931 return false;
eaaf8adb 6932
40381db7 6933 if (origin != pi->attr->origin)
3dc339cd 6934 return false;
eaaf8adb 6935
40381db7 6936 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6937 return false;
29f7d023 6938
40381db7 6939 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6940 return false;
eaaf8adb 6941
3da2cc32 6942 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6943 return false;
eaaf8adb 6944
dd18c5a9 6945 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6946 return false;
dd18c5a9 6947
40381db7 6948 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6949 return false;
7ce8a8e0 6950
3dc339cd 6951 return true;
eaaf8adb
DS
6952}
6953
5f040085
DS
6954static void bgp_aggregate_install(
6955 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6956 uint8_t origin, struct aspath *aspath, struct community *community,
6957 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6958 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6959{
9bcb3eef 6960 struct bgp_dest *dest;
c701010e 6961 struct bgp_table *table;
6f94b685 6962 struct bgp_path_info *pi, *orig, *new;
20894f50 6963 struct attr *attr;
c701010e
DS
6964
6965 table = bgp->rib[afi][safi];
6966
9bcb3eef 6967 dest = bgp_node_get(table, p);
eaaf8adb 6968
9bcb3eef 6969 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6970 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6971 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6972 break;
6973
6aabb15d
RZ
6974 /*
6975 * If we have paths with different MEDs, then don't install
6976 * (or uninstall) the aggregate route.
6977 */
6978 if (aggregate->match_med && aggregate->med_mismatched)
6979 goto uninstall_aggregate_route;
6980
c701010e 6981 if (aggregate->count > 0) {
eaaf8adb
DS
6982 /*
6983 * If the aggregate information has not changed
6984 * no need to re-install it again.
6985 */
6f94b685 6986 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6987 ecommunity, lcommunity)) {
9bcb3eef 6988 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6989
6990 if (aspath)
6991 aspath_free(aspath);
6992 if (community)
3c1f53de 6993 community_free(&community);
3da2cc32
DS
6994 if (ecommunity)
6995 ecommunity_free(&ecommunity);
dd18c5a9
DS
6996 if (lcommunity)
6997 lcommunity_free(&lcommunity);
eaaf8adb
DS
6998
6999 return;
7000 }
7001
7002 /*
7003 * Mark the old as unusable
7004 */
40381db7 7005 if (pi)
9bcb3eef 7006 bgp_path_info_delete(dest, pi);
eaaf8adb 7007
20894f50
DA
7008 attr = bgp_attr_aggregate_intern(
7009 bgp, origin, aspath, community, ecommunity, lcommunity,
7010 aggregate, atomic_aggregate, p);
7011
7012 if (!attr) {
7013 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7014 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7015 zlog_debug("%s: %pFX null attribute", __func__,
7016 p);
20894f50
DA
7017 return;
7018 }
7019
3da2cc32 7020 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7021 bgp->peer_self, attr, dest);
20894f50 7022
1defdda8 7023 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7024
9bcb3eef
DS
7025 bgp_path_info_add(dest, new);
7026 bgp_process(bgp, dest, afi, safi);
c701010e 7027 } else {
6aabb15d 7028 uninstall_aggregate_route:
6f94b685 7029 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7030 if (pi->peer == bgp->peer_self
7031 && pi->type == ZEBRA_ROUTE_BGP
7032 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7033 break;
7034
7035 /* Withdraw static BGP route from routing table. */
40381db7 7036 if (pi) {
9bcb3eef
DS
7037 bgp_path_info_delete(dest, pi);
7038 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7039 }
7040 }
7041
9bcb3eef 7042 bgp_dest_unlock_node(dest);
c701010e
DS
7043}
7044
6aabb15d
RZ
7045/**
7046 * Check if the current path has different MED than other known paths.
7047 *
7048 * \returns `true` if the MED matched the others else `false`.
7049 */
7050static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7051 struct bgp *bgp, struct bgp_path_info *pi)
7052{
7053 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7054
7055 /* This is the first route being analyzed. */
7056 if (!aggregate->med_initialized) {
7057 aggregate->med_initialized = true;
7058 aggregate->med_mismatched = false;
7059 aggregate->med_matched_value = cur_med;
7060 } else {
7061 /* Check if routes with different MED showed up. */
7062 if (cur_med != aggregate->med_matched_value)
7063 aggregate->med_mismatched = true;
7064 }
7065
7066 return !aggregate->med_mismatched;
7067}
7068
7069/**
7070 * Initializes and tests all routes in the aggregate address path for MED
7071 * values.
7072 *
7073 * \returns `true` if all MEDs are the same otherwise `false`.
7074 */
7075static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7076 struct bgp *bgp, const struct prefix *p,
7077 afi_t afi, safi_t safi)
7078{
7079 struct bgp_table *table = bgp->rib[afi][safi];
7080 const struct prefix *dest_p;
7081 struct bgp_dest *dest, *top;
7082 struct bgp_path_info *pi;
7083 bool med_matched = true;
7084
7085 aggregate->med_initialized = false;
7086
7087 top = bgp_node_get(table, p);
7088 for (dest = bgp_node_get(table, p); dest;
7089 dest = bgp_route_next_until(dest, top)) {
7090 dest_p = bgp_dest_get_prefix(dest);
7091 if (dest_p->prefixlen <= p->prefixlen)
7092 continue;
7093
7094 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7095 if (BGP_PATH_HOLDDOWN(pi))
7096 continue;
7097 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7098 continue;
7099 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7100 med_matched = false;
7101 break;
7102 }
7103 }
7104 if (!med_matched)
7105 break;
7106 }
7107 bgp_dest_unlock_node(top);
7108
7109 return med_matched;
7110}
7111
7112/**
7113 * Toggles the route suppression status for this aggregate address
7114 * configuration.
7115 */
4056a5f6
RZ
7116void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7117 struct bgp *bgp, const struct prefix *p,
7118 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7119{
7120 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7121 const struct prefix *dest_p;
7122 struct bgp_dest *dest, *top;
7123 struct bgp_path_info *pi;
7124 bool toggle_suppression;
7125
7126 /* We've found a different MED we must revert any suppressed routes. */
7127 top = bgp_node_get(table, p);
7128 for (dest = bgp_node_get(table, p); dest;
7129 dest = bgp_route_next_until(dest, top)) {
7130 dest_p = bgp_dest_get_prefix(dest);
7131 if (dest_p->prefixlen <= p->prefixlen)
7132 continue;
7133
7134 toggle_suppression = false;
7135 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7136 if (BGP_PATH_HOLDDOWN(pi))
7137 continue;
7138 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7139 continue;
7140
6aabb15d
RZ
7141 /* We are toggling suppression back. */
7142 if (suppress) {
6aabb15d 7143 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7144 if (aggr_suppress_path(aggregate, pi))
7145 toggle_suppression = true;
6aabb15d
RZ
7146 continue;
7147 }
7148
6aabb15d 7149 /* Install route if there is no more suppression. */
4056a5f6 7150 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7151 toggle_suppression = true;
6aabb15d
RZ
7152 }
7153
7154 if (toggle_suppression)
7155 bgp_process(bgp, dest, afi, safi);
7156 }
7157 bgp_dest_unlock_node(top);
7158}
7159
7160/**
7161 * Aggregate address MED matching incremental test: this function is called
7162 * when the initial aggregation occurred and we are only testing a single
7163 * new path.
7164 *
7165 * In addition to testing and setting the MED validity it also installs back
7166 * suppressed routes (if summary is configured).
7167 *
7168 * Must not be called in `bgp_aggregate_route`.
7169 */
7170static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7171 struct bgp *bgp, const struct prefix *p,
7172 afi_t afi, safi_t safi,
7173 struct bgp_path_info *pi, bool is_adding)
7174{
7175 /* MED matching disabled. */
7176 if (!aggregate->match_med)
7177 return;
7178
7179 /* Aggregation with different MED, nothing to do. */
7180 if (aggregate->med_mismatched)
7181 return;
7182
7183 /*
7184 * Test the current entry:
7185 *
7186 * is_adding == true: if the new entry doesn't match then we must
7187 * install all suppressed routes.
7188 *
7189 * is_adding == false: if the entry being removed was the last
7190 * unmatching entry then we can suppress all routes.
7191 */
7192 if (!is_adding) {
7193 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7194 && aggregate->summary_only)
7195 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7196 safi, true);
7197 } else
7198 bgp_aggregate_med_match(aggregate, bgp, pi);
7199
7200 /* No mismatches, just quit. */
7201 if (!aggregate->med_mismatched)
7202 return;
7203
7204 /* Route summarization is disabled. */
7205 if (!aggregate->summary_only)
7206 return;
7207
7208 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7209}
7210
b5d58c32 7211/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7212void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7213 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7214{
7215 struct bgp_table *table;
9bcb3eef
DS
7216 struct bgp_dest *top;
7217 struct bgp_dest *dest;
d7c0a89a 7218 uint8_t origin;
d62a17ae 7219 struct aspath *aspath = NULL;
d62a17ae 7220 struct community *community = NULL;
3da2cc32 7221 struct ecommunity *ecommunity = NULL;
dd18c5a9 7222 struct lcommunity *lcommunity = NULL;
40381db7 7223 struct bgp_path_info *pi;
d62a17ae 7224 unsigned long match = 0;
d7c0a89a 7225 uint8_t atomic_aggregate = 0;
d62a17ae 7226
9f822fa2
S
7227 /* If the bgp instance is being deleted or self peer is deleted
7228 * then do not create aggregate route
7229 */
892fedb6
DA
7230 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7231 || (bgp->peer_self == NULL))
9f822fa2
S
7232 return;
7233
6aabb15d
RZ
7234 /* Initialize and test routes for MED difference. */
7235 if (aggregate->match_med)
7236 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7237
4056a5f6
RZ
7238 /*
7239 * Reset aggregate count: we might've been called from route map
7240 * update so in that case we must retest all more specific routes.
7241 *
7242 * \see `bgp_route_map_process_update`.
7243 */
7244 aggregate->count = 0;
7245 aggregate->incomplete_origin_count = 0;
7246 aggregate->incomplete_origin_count = 0;
7247 aggregate->egp_origin_count = 0;
7248
d62a17ae 7249 /* ORIGIN attribute: If at least one route among routes that are
7250 aggregated has ORIGIN with the value INCOMPLETE, then the
7251 aggregated route must have the ORIGIN attribute with the value
7252 INCOMPLETE. Otherwise, if at least one route among routes that
7253 are aggregated has ORIGIN with the value EGP, then the aggregated
7254 route must have the origin attribute with the value EGP. In all
7255 other case the value of the ORIGIN attribute of the aggregated
7256 route is INTERNAL. */
7257 origin = BGP_ORIGIN_IGP;
718e3744 7258
d62a17ae 7259 table = bgp->rib[afi][safi];
718e3744 7260
d62a17ae 7261 top = bgp_node_get(table, p);
9bcb3eef
DS
7262 for (dest = bgp_node_get(table, p); dest;
7263 dest = bgp_route_next_until(dest, top)) {
7264 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7265
9bcb3eef 7266 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7267 continue;
d62a17ae 7268
a77e2f4b
S
7269 /* If suppress fib is enabled and route not installed
7270 * in FIB, skip the route
7271 */
7272 if (!bgp_check_advertise(bgp, dest))
7273 continue;
7274
c2ff8b3e 7275 match = 0;
d62a17ae 7276
9bcb3eef 7277 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7278 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7279 continue;
718e3744 7280
40381db7 7281 if (pi->attr->flag
c2ff8b3e
DS
7282 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7283 atomic_aggregate = 1;
d62a17ae 7284
40381db7 7285 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7286 continue;
d62a17ae 7287
f273fef1
DS
7288 /*
7289 * summary-only aggregate route suppress
7290 * aggregated route announcements.
6aabb15d
RZ
7291 *
7292 * MED matching:
7293 * Don't create summaries if MED didn't match
7294 * otherwise neither the specific routes and the
7295 * aggregation will be announced.
f273fef1 7296 */
6aabb15d
RZ
7297 if (aggregate->summary_only
7298 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7299 if (aggr_suppress_path(aggregate, pi))
7300 match++;
d62a17ae 7301 }
c2ff8b3e 7302
365ab2e7
RZ
7303 /*
7304 * Suppress more specific routes that match the route
7305 * map results.
7306 *
7307 * MED matching:
7308 * Don't suppress routes if MED matching is enabled and
7309 * it mismatched otherwise we might end up with no
7310 * routes for this path.
7311 */
7312 if (aggregate->suppress_map_name
7313 && AGGREGATE_MED_VALID(aggregate)
7314 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7315 if (aggr_suppress_path(aggregate, pi))
7316 match++;
d62a17ae 7317 }
c2ff8b3e
DS
7318
7319 aggregate->count++;
7320
f273fef1
DS
7321 /*
7322 * If at least one route among routes that are
7323 * aggregated has ORIGIN with the value INCOMPLETE,
7324 * then the aggregated route MUST have the ORIGIN
7325 * attribute with the value INCOMPLETE. Otherwise, if
7326 * at least one route among routes that are aggregated
7327 * has ORIGIN with the value EGP, then the aggregated
7328 * route MUST have the ORIGIN attribute with the value
7329 * EGP.
7330 */
fc968841
NT
7331 switch (pi->attr->origin) {
7332 case BGP_ORIGIN_INCOMPLETE:
7333 aggregate->incomplete_origin_count++;
7334 break;
7335 case BGP_ORIGIN_EGP:
7336 aggregate->egp_origin_count++;
7337 break;
7338 default:
7339 /*Do nothing.
7340 */
7341 break;
7342 }
c2ff8b3e
DS
7343
7344 if (!aggregate->as_set)
7345 continue;
7346
f273fef1
DS
7347 /*
7348 * as-set aggregate route generate origin, as path,
7349 * and community aggregation.
7350 */
fc968841
NT
7351 /* Compute aggregate route's as-path.
7352 */
ef51a7d8 7353 bgp_compute_aggregate_aspath_hash(aggregate,
7354 pi->attr->aspath);
c2ff8b3e 7355
fc968841
NT
7356 /* Compute aggregate route's community.
7357 */
7358 if (pi->attr->community)
21fec674 7359 bgp_compute_aggregate_community_hash(
fc968841
NT
7360 aggregate,
7361 pi->attr->community);
dd18c5a9 7362
fc968841
NT
7363 /* Compute aggregate route's extended community.
7364 */
7365 if (pi->attr->ecommunity)
4edd83f9 7366 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7367 aggregate,
7368 pi->attr->ecommunity);
7369
7370 /* Compute aggregate route's large community.
7371 */
7372 if (pi->attr->lcommunity)
f1eb1f05 7373 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7374 aggregate,
7375 pi->attr->lcommunity);
d62a17ae 7376 }
c2ff8b3e 7377 if (match)
9bcb3eef 7378 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7379 }
21fec674 7380 if (aggregate->as_set) {
ef51a7d8 7381 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7382 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7383 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7384 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7385 }
7386
f1eb1f05 7387
9bcb3eef 7388 bgp_dest_unlock_node(top);
718e3744 7389
718e3744 7390
fc968841
NT
7391 if (aggregate->incomplete_origin_count > 0)
7392 origin = BGP_ORIGIN_INCOMPLETE;
7393 else if (aggregate->egp_origin_count > 0)
7394 origin = BGP_ORIGIN_EGP;
d62a17ae 7395
229757f1
DA
7396 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7397 origin = aggregate->origin;
7398
fc968841
NT
7399 if (aggregate->as_set) {
7400 if (aggregate->aspath)
7401 /* Retrieve aggregate route's as-path.
7402 */
7403 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7404
fc968841
NT
7405 if (aggregate->community)
7406 /* Retrieve aggregate route's community.
7407 */
7408 community = community_dup(aggregate->community);
3da2cc32 7409
fc968841
NT
7410 if (aggregate->ecommunity)
7411 /* Retrieve aggregate route's ecommunity.
7412 */
7413 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7414
fc968841
NT
7415 if (aggregate->lcommunity)
7416 /* Retrieve aggregate route's lcommunity.
7417 */
7418 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7419 }
718e3744 7420
c701010e 7421 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7422 ecommunity, lcommunity, atomic_aggregate,
7423 aggregate);
718e3744 7424}
7425
5f040085
DS
7426void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7427 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7428{
7429 struct bgp_table *table;
9bcb3eef
DS
7430 struct bgp_dest *top;
7431 struct bgp_dest *dest;
40381db7 7432 struct bgp_path_info *pi;
3b7db173
DS
7433 unsigned long match;
7434
7435 table = bgp->rib[afi][safi];
7436
7437 /* If routes exists below this node, generate aggregate routes. */
7438 top = bgp_node_get(table, p);
9bcb3eef
DS
7439 for (dest = bgp_node_get(table, p); dest;
7440 dest = bgp_route_next_until(dest, top)) {
7441 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7442
9bcb3eef 7443 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7444 continue;
7445 match = 0;
7446
9bcb3eef 7447 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7448 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7449 continue;
7450
40381db7 7451 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7452 continue;
7453
6aabb15d
RZ
7454 if (aggregate->summary_only && pi->extra
7455 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7456 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7457 match++;
3b7db173 7458 }
3b7db173 7459
365ab2e7
RZ
7460 if (aggregate->suppress_map_name
7461 && AGGREGATE_MED_VALID(aggregate)
7462 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7463 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7464 match++;
3b7db173 7465 }
365ab2e7 7466
3b7db173 7467 aggregate->count--;
fc968841
NT
7468
7469 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7470 aggregate->incomplete_origin_count--;
7471 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7472 aggregate->egp_origin_count--;
7473
7474 if (aggregate->as_set) {
7475 /* Remove as-path from aggregate.
7476 */
ef51a7d8 7477 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7478 aggregate,
7479 pi->attr->aspath);
7480
7481 if (pi->attr->community)
7482 /* Remove community from aggregate.
7483 */
21fec674 7484 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7485 aggregate,
7486 pi->attr->community);
7487
7488 if (pi->attr->ecommunity)
7489 /* Remove ecommunity from aggregate.
7490 */
4edd83f9 7491 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7492 aggregate,
7493 pi->attr->ecommunity);
7494
7495 if (pi->attr->lcommunity)
7496 /* Remove lcommunity from aggregate.
7497 */
f1eb1f05 7498 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7499 aggregate,
7500 pi->attr->lcommunity);
7501 }
3b7db173
DS
7502 }
7503
7504 /* If this node was suppressed, process the change. */
7505 if (match)
9bcb3eef 7506 bgp_process(bgp, dest, afi, safi);
3b7db173 7507 }
f1eb1f05 7508 if (aggregate->as_set) {
ef51a7d8 7509 aspath_free(aggregate->aspath);
7510 aggregate->aspath = NULL;
21fec674 7511 if (aggregate->community)
7512 community_free(&aggregate->community);
4edd83f9 7513 if (aggregate->ecommunity)
7514 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7515 if (aggregate->lcommunity)
7516 lcommunity_free(&aggregate->lcommunity);
7517 }
7518
9bcb3eef 7519 bgp_dest_unlock_node(top);
3b7db173 7520}
718e3744 7521
5f040085
DS
7522static void bgp_add_route_to_aggregate(struct bgp *bgp,
7523 const struct prefix *aggr_p,
fc968841
NT
7524 struct bgp_path_info *pinew, afi_t afi,
7525 safi_t safi,
7526 struct bgp_aggregate *aggregate)
7527{
7528 uint8_t origin;
7529 struct aspath *aspath = NULL;
7530 uint8_t atomic_aggregate = 0;
7531 struct community *community = NULL;
7532 struct ecommunity *ecommunity = NULL;
7533 struct lcommunity *lcommunity = NULL;
7534
a4559740 7535 /* If the bgp instance is being deleted or self peer is deleted
7536 * then do not create aggregate route
7537 */
7538 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7539 || (bgp->peer_self == NULL))
7540 return;
7541
fc968841
NT
7542 /* ORIGIN attribute: If at least one route among routes that are
7543 * aggregated has ORIGIN with the value INCOMPLETE, then the
7544 * aggregated route must have the ORIGIN attribute with the value
7545 * INCOMPLETE. Otherwise, if at least one route among routes that
7546 * are aggregated has ORIGIN with the value EGP, then the aggregated
7547 * route must have the origin attribute with the value EGP. In all
7548 * other case the value of the ORIGIN attribute of the aggregated
7549 * route is INTERNAL.
7550 */
7551 origin = BGP_ORIGIN_IGP;
7552
7553 aggregate->count++;
7554
6aabb15d
RZ
7555 /*
7556 * This must be called before `summary` check to avoid
7557 * "suppressing" twice.
7558 */
7559 if (aggregate->match_med)
7560 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7561 pinew, true);
7562
7563 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7564 aggr_suppress_path(aggregate, pinew);
fc968841 7565
365ab2e7
RZ
7566 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7567 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7568 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7569
7570 switch (pinew->attr->origin) {
7571 case BGP_ORIGIN_INCOMPLETE:
7572 aggregate->incomplete_origin_count++;
7573 break;
7574 case BGP_ORIGIN_EGP:
7575 aggregate->egp_origin_count++;
7576 break;
7577 default:
7578 /* Do nothing.
7579 */
7580 break;
7581 }
7582
7583 if (aggregate->incomplete_origin_count > 0)
7584 origin = BGP_ORIGIN_INCOMPLETE;
7585 else if (aggregate->egp_origin_count > 0)
7586 origin = BGP_ORIGIN_EGP;
7587
229757f1
DA
7588 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7589 origin = aggregate->origin;
7590
fc968841
NT
7591 if (aggregate->as_set) {
7592 /* Compute aggregate route's as-path.
7593 */
7594 bgp_compute_aggregate_aspath(aggregate,
7595 pinew->attr->aspath);
7596
7597 /* Compute aggregate route's community.
7598 */
7599 if (pinew->attr->community)
7600 bgp_compute_aggregate_community(
7601 aggregate,
7602 pinew->attr->community);
7603
7604 /* Compute aggregate route's extended community.
7605 */
7606 if (pinew->attr->ecommunity)
7607 bgp_compute_aggregate_ecommunity(
7608 aggregate,
7609 pinew->attr->ecommunity);
7610
7611 /* Compute aggregate route's large community.
7612 */
7613 if (pinew->attr->lcommunity)
7614 bgp_compute_aggregate_lcommunity(
7615 aggregate,
7616 pinew->attr->lcommunity);
7617
7618 /* Retrieve aggregate route's as-path.
7619 */
7620 if (aggregate->aspath)
7621 aspath = aspath_dup(aggregate->aspath);
7622
7623 /* Retrieve aggregate route's community.
7624 */
7625 if (aggregate->community)
7626 community = community_dup(aggregate->community);
7627
7628 /* Retrieve aggregate route's ecommunity.
7629 */
7630 if (aggregate->ecommunity)
7631 ecommunity = ecommunity_dup(aggregate->ecommunity);
7632
7633 /* Retrieve aggregate route's lcommunity.
7634 */
7635 if (aggregate->lcommunity)
7636 lcommunity = lcommunity_dup(aggregate->lcommunity);
7637 }
7638
7639 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7640 aspath, community, ecommunity,
7641 lcommunity, atomic_aggregate, aggregate);
7642}
7643
7644static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7645 safi_t safi,
7646 struct bgp_path_info *pi,
7647 struct bgp_aggregate *aggregate,
5f040085 7648 const struct prefix *aggr_p)
fc968841
NT
7649{
7650 uint8_t origin;
7651 struct aspath *aspath = NULL;
7652 uint8_t atomic_aggregate = 0;
7653 struct community *community = NULL;
7654 struct ecommunity *ecommunity = NULL;
7655 struct lcommunity *lcommunity = NULL;
7656 unsigned long match = 0;
7657
a4559740 7658 /* If the bgp instance is being deleted or self peer is deleted
7659 * then do not create aggregate route
7660 */
7661 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7662 || (bgp->peer_self == NULL))
7663 return;
7664
fc968841
NT
7665 if (BGP_PATH_HOLDDOWN(pi))
7666 return;
7667
7668 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7669 return;
7670
4056a5f6
RZ
7671 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7672 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7673 match++;
fc968841 7674
365ab2e7 7675 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7676 && aggr_suppress_map_test(bgp, aggregate, pi))
7677 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7678 match++;
fc968841 7679
6aabb15d 7680 /*
365ab2e7 7681 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7682 * "unsuppressing" twice.
7683 */
7684 if (aggregate->match_med)
7685 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7686 true);
7687
fc968841
NT
7688 if (aggregate->count > 0)
7689 aggregate->count--;
7690
7691 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7692 aggregate->incomplete_origin_count--;
7693 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7694 aggregate->egp_origin_count--;
7695
7696 if (aggregate->as_set) {
7697 /* Remove as-path from aggregate.
7698 */
7699 bgp_remove_aspath_from_aggregate(aggregate,
7700 pi->attr->aspath);
7701
7702 if (pi->attr->community)
7703 /* Remove community from aggregate.
7704 */
7705 bgp_remove_community_from_aggregate(
7706 aggregate,
7707 pi->attr->community);
7708
7709 if (pi->attr->ecommunity)
7710 /* Remove ecommunity from aggregate.
7711 */
7712 bgp_remove_ecommunity_from_aggregate(
7713 aggregate,
7714 pi->attr->ecommunity);
7715
7716 if (pi->attr->lcommunity)
7717 /* Remove lcommunity from aggregate.
7718 */
7719 bgp_remove_lcommunity_from_aggregate(
7720 aggregate,
7721 pi->attr->lcommunity);
7722 }
7723
7724 /* If this node was suppressed, process the change. */
7725 if (match)
7726 bgp_process(bgp, pi->net, afi, safi);
7727
7728 origin = BGP_ORIGIN_IGP;
7729 if (aggregate->incomplete_origin_count > 0)
7730 origin = BGP_ORIGIN_INCOMPLETE;
7731 else if (aggregate->egp_origin_count > 0)
7732 origin = BGP_ORIGIN_EGP;
7733
229757f1
DA
7734 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7735 origin = aggregate->origin;
7736
fc968841
NT
7737 if (aggregate->as_set) {
7738 /* Retrieve aggregate route's as-path.
7739 */
7740 if (aggregate->aspath)
7741 aspath = aspath_dup(aggregate->aspath);
7742
7743 /* Retrieve aggregate route's community.
7744 */
7745 if (aggregate->community)
7746 community = community_dup(aggregate->community);
7747
7748 /* Retrieve aggregate route's ecommunity.
7749 */
7750 if (aggregate->ecommunity)
7751 ecommunity = ecommunity_dup(aggregate->ecommunity);
7752
7753 /* Retrieve aggregate route's lcommunity.
7754 */
7755 if (aggregate->lcommunity)
7756 lcommunity = lcommunity_dup(aggregate->lcommunity);
7757 }
7758
7759 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7760 aspath, community, ecommunity,
7761 lcommunity, atomic_aggregate, aggregate);
7762}
7763
5a1ae2c2 7764void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7765 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7766{
9bcb3eef
DS
7767 struct bgp_dest *child;
7768 struct bgp_dest *dest;
d62a17ae 7769 struct bgp_aggregate *aggregate;
7770 struct bgp_table *table;
718e3744 7771
d62a17ae 7772 table = bgp->aggregate[afi][safi];
f018db83 7773
d62a17ae 7774 /* No aggregates configured. */
7775 if (bgp_table_top_nolock(table) == NULL)
7776 return;
f018db83 7777
d62a17ae 7778 if (p->prefixlen == 0)
7779 return;
718e3744 7780
40381db7 7781 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7782 return;
718e3744 7783
a77e2f4b
S
7784 /* If suppress fib is enabled and route not installed
7785 * in FIB, do not update the aggregate route
7786 */
7787 if (!bgp_check_advertise(bgp, pi->net))
7788 return;
7789
d62a17ae 7790 child = bgp_node_get(table, p);
718e3744 7791
d62a17ae 7792 /* Aggregate address configuration check. */
9bcb3eef
DS
7793 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7794 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7795
9bcb3eef
DS
7796 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7797 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7798 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7799 aggregate);
d62a17ae 7800 }
b1e62edd 7801 }
9bcb3eef 7802 bgp_dest_unlock_node(child);
718e3744 7803}
7804
5a1ae2c2 7805void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7806 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7807{
9bcb3eef
DS
7808 struct bgp_dest *child;
7809 struct bgp_dest *dest;
d62a17ae 7810 struct bgp_aggregate *aggregate;
7811 struct bgp_table *table;
718e3744 7812
d62a17ae 7813 table = bgp->aggregate[afi][safi];
718e3744 7814
d62a17ae 7815 /* No aggregates configured. */
7816 if (bgp_table_top_nolock(table) == NULL)
7817 return;
718e3744 7818
d62a17ae 7819 if (p->prefixlen == 0)
7820 return;
718e3744 7821
d62a17ae 7822 child = bgp_node_get(table, p);
718e3744 7823
d62a17ae 7824 /* Aggregate address configuration check. */
9bcb3eef
DS
7825 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7826 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7827
9bcb3eef
DS
7828 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7829 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7830 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7831 aggregate, dest_p);
d62a17ae 7832 }
b1e62edd 7833 }
9bcb3eef 7834 bgp_dest_unlock_node(child);
d62a17ae 7835}
718e3744 7836
718e3744 7837/* Aggregate route attribute. */
7838#define AGGREGATE_SUMMARY_ONLY 1
7839#define AGGREGATE_AS_SET 1
fb29348a 7840#define AGGREGATE_AS_UNSET 0
718e3744 7841
229757f1
DA
7842static const char *bgp_origin2str(uint8_t origin)
7843{
7844 switch (origin) {
7845 case BGP_ORIGIN_IGP:
7846 return "igp";
7847 case BGP_ORIGIN_EGP:
7848 return "egp";
7849 case BGP_ORIGIN_INCOMPLETE:
7850 return "incomplete";
7851 }
7852 return "n/a";
7853}
7854
fdeb5a81 7855static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7856{
7857 switch (v_state) {
fdeb5a81
DS
7858 case RPKI_NOT_BEING_USED:
7859 return "not used";
7860 case RPKI_VALID:
b5b99af8 7861 return "valid";
fdeb5a81 7862 case RPKI_NOTFOUND:
b5b99af8 7863 return "not found";
fdeb5a81 7864 case RPKI_INVALID:
b5b99af8 7865 return "invalid";
b5b99af8 7866 }
fdeb5a81
DS
7867
7868 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7869 return "ERROR";
7870}
7871
585f1adc
IR
7872static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7873 afi_t afi, safi_t safi)
718e3744 7874{
585f1adc
IR
7875 VTY_DECLVAR_CONTEXT(bgp, bgp);
7876 int ret;
7877 struct prefix p;
9bcb3eef 7878 struct bgp_dest *dest;
d62a17ae 7879 struct bgp_aggregate *aggregate;
718e3744 7880
585f1adc
IR
7881 /* Convert string to prefix structure. */
7882 ret = str2prefix(prefix_str, &p);
7883 if (!ret) {
7884 vty_out(vty, "Malformed prefix\n");
7885 return CMD_WARNING_CONFIG_FAILED;
7886 }
7887 apply_mask(&p);
a4559740 7888
d62a17ae 7889 /* Old configuration check. */
585f1adc 7890 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 7891 if (!dest) {
585f1adc
IR
7892 vty_out(vty,
7893 "%% There is no aggregate-address configuration.\n");
7894 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 7895 }
f6269b4f 7896
9bcb3eef 7897 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
7898 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
7899 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
7900 NULL, NULL, 0, aggregate);
d62a17ae 7901
7902 /* Unlock aggregate address configuration. */
9bcb3eef 7903 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7904
7905 if (aggregate->community)
7906 community_free(&aggregate->community);
7907
7908 if (aggregate->community_hash) {
7909 /* Delete all communities in the hash.
7910 */
7911 hash_clean(aggregate->community_hash,
7912 bgp_aggr_community_remove);
7913 /* Free up the community_hash.
7914 */
7915 hash_free(aggregate->community_hash);
7916 }
7917
7918 if (aggregate->ecommunity)
7919 ecommunity_free(&aggregate->ecommunity);
7920
7921 if (aggregate->ecommunity_hash) {
7922 /* Delete all ecommunities in the hash.
7923 */
7924 hash_clean(aggregate->ecommunity_hash,
7925 bgp_aggr_ecommunity_remove);
7926 /* Free up the ecommunity_hash.
7927 */
7928 hash_free(aggregate->ecommunity_hash);
7929 }
7930
7931 if (aggregate->lcommunity)
7932 lcommunity_free(&aggregate->lcommunity);
7933
7934 if (aggregate->lcommunity_hash) {
7935 /* Delete all lcommunities in the hash.
7936 */
7937 hash_clean(aggregate->lcommunity_hash,
7938 bgp_aggr_lcommunity_remove);
7939 /* Free up the lcommunity_hash.
7940 */
7941 hash_free(aggregate->lcommunity_hash);
7942 }
7943
7944 if (aggregate->aspath)
7945 aspath_free(aggregate->aspath);
7946
7947 if (aggregate->aspath_hash) {
7948 /* Delete all as-paths in the hash.
7949 */
7950 hash_clean(aggregate->aspath_hash,
7951 bgp_aggr_aspath_remove);
7952 /* Free up the aspath_hash.
7953 */
7954 hash_free(aggregate->aspath_hash);
7955 }
7956
d62a17ae 7957 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7958 bgp_dest_unlock_node(dest);
7959 bgp_dest_unlock_node(dest);
d62a17ae 7960
585f1adc 7961 return CMD_SUCCESS;
d62a17ae 7962}
7963
585f1adc
IR
7964static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
7965 safi_t safi, const char *rmap,
7966 uint8_t summary_only, uint8_t as_set,
7967 uint8_t origin, bool match_med,
7968 const char *suppress_map)
d62a17ae 7969{
585f1adc 7970 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 7971 int ret;
585f1adc 7972 struct prefix p;
9bcb3eef 7973 struct bgp_dest *dest;
d62a17ae 7974 struct bgp_aggregate *aggregate;
fb29348a 7975 uint8_t as_set_new = as_set;
d62a17ae 7976
365ab2e7 7977 if (suppress_map && summary_only) {
585f1adc 7978 vty_out(vty,
365ab2e7 7979 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 7980 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
7981 }
7982
585f1adc
IR
7983 /* Convert string to prefix structure. */
7984 ret = str2prefix(prefix_str, &p);
7985 if (!ret) {
7986 vty_out(vty, "Malformed prefix\n");
7987 return CMD_WARNING_CONFIG_FAILED;
7988 }
7989 apply_mask(&p);
d62a17ae 7990
585f1adc
IR
7991 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
7992 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
7993 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7994 prefix_str);
7995 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
7996 }
7997
d62a17ae 7998 /* Old configuration check. */
585f1adc 7999 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8000 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8001
20894f50 8002 if (aggregate) {
585f1adc 8003 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8004 /* try to remove the old entry */
585f1adc 8005 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8006 if (ret) {
585f1adc 8007 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8008 bgp_dest_unlock_node(dest);
585f1adc 8009 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8010 }
8011 }
718e3744 8012
d62a17ae 8013 /* Make aggregate address structure. */
8014 aggregate = bgp_aggregate_new();
8015 aggregate->summary_only = summary_only;
6aabb15d 8016 aggregate->match_med = match_med;
fb29348a
DA
8017
8018 /* Network operators MUST NOT locally generate any new
8019 * announcements containing AS_SET or AS_CONFED_SET. If they have
8020 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8021 * SHOULD withdraw those routes and re-announce routes for the
8022 * aggregate or component prefixes (i.e., the more-specific routes
8023 * subsumed by the previously aggregated route) without AS_SET
8024 * or AS_CONFED_SET in the updates.
8025 */
7f972cd8 8026 if (bgp->reject_as_sets) {
fb29348a
DA
8027 if (as_set == AGGREGATE_AS_SET) {
8028 as_set_new = AGGREGATE_AS_UNSET;
8029 zlog_warn(
63efca0e 8030 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8031 __func__);
585f1adc 8032 vty_out(vty,
fb29348a
DA
8033 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8034 }
8035 }
8036
8037 aggregate->as_set = as_set_new;
d62a17ae 8038 aggregate->safi = safi;
229757f1
DA
8039 /* Override ORIGIN attribute if defined.
8040 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8041 * to IGP which is not what rfc4271 says.
8042 * This enables the same behavior, optionally.
8043 */
8044 aggregate->origin = origin;
20894f50
DA
8045
8046 if (rmap) {
8047 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8048 route_map_counter_decrement(aggregate->rmap.map);
8049 aggregate->rmap.name =
8050 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8051 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8052 route_map_counter_increment(aggregate->rmap.map);
8053 }
365ab2e7
RZ
8054
8055 if (suppress_map) {
8056 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8057 route_map_counter_decrement(aggregate->suppress_map);
8058
8059 aggregate->suppress_map_name =
8060 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8061 aggregate->suppress_map =
8062 route_map_lookup_by_name(aggregate->suppress_map_name);
8063 route_map_counter_increment(aggregate->suppress_map);
8064 }
8065
9bcb3eef 8066 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8067
d62a17ae 8068 /* Aggregate address insert into BGP routing table. */
585f1adc 8069 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8070
585f1adc 8071 return CMD_SUCCESS;
718e3744 8072}
8073
585f1adc
IR
8074DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8075 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8076 "as-set$as_set_s"
8077 "|summary-only$summary_only"
8078 "|route-map WORD$rmap_name"
8079 "|origin <egp|igp|incomplete>$origin_s"
8080 "|matching-MED-only$match_med"
8081 "|suppress-map WORD$suppress_map"
8082 "}]",
8083 NO_STR
8084 "Configure BGP aggregate entries\n"
8085 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
8086 "Generate AS set path information\n"
8087 "Filter more specific routes from updates\n"
8088 "Apply route map to aggregate network\n"
8089 "Route map name\n"
8090 "BGP origin code\n"
8091 "Remote EGP\n"
8092 "Local IGP\n"
8093 "Unknown heritage\n"
8094 "Only aggregate routes with matching MED\n"
8095 "Suppress the selected more specific routes\n"
8096 "Route map with the route selectors\n")
8097{
8098 const char *prefix_s = NULL;
554b3b10 8099 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8100 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8101 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8102 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8103
554b3b10 8104 if (addr_str) {
7533cad7
QY
8105 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8106 sizeof(prefix_buf))
554b3b10
RZ
8107 == 0) {
8108 vty_out(vty, "%% Inconsistent address and mask\n");
8109 return CMD_WARNING_CONFIG_FAILED;
8110 }
585f1adc
IR
8111 prefix_s = prefix_buf;
8112 } else
8113 prefix_s = prefix_str;
37a87b8f 8114
585f1adc
IR
8115 if (origin_s) {
8116 if (strcmp(origin_s, "egp") == 0)
8117 origin = BGP_ORIGIN_EGP;
8118 else if (strcmp(origin_s, "igp") == 0)
8119 origin = BGP_ORIGIN_IGP;
8120 else if (strcmp(origin_s, "incomplete") == 0)
8121 origin = BGP_ORIGIN_INCOMPLETE;
8122 }
90e21f35 8123
585f1adc
IR
8124 if (as_set_s)
8125 as_set = AGGREGATE_AS_SET;
554b3b10 8126
585f1adc 8127 /* Handle configuration removal, otherwise installation. */
554b3b10 8128 if (no)
585f1adc
IR
8129 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8130
8131 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8132 summary_only != NULL, as_set, origin,
8133 match_med != NULL, suppress_map);
8134}
8135
8136DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8137 "[no] aggregate-address X:X::X:X/M$prefix [{"
8138 "as-set$as_set_s"
8139 "|summary-only$summary_only"
8140 "|route-map WORD$rmap_name"
8141 "|origin <egp|igp|incomplete>$origin_s"
8142 "|matching-MED-only$match_med"
8143 "|suppress-map WORD$suppress_map"
8144 "}]",
8145 NO_STR
8146 "Configure BGP aggregate entries\n"
8147 "Aggregate prefix\n"
8148 "Generate AS set path information\n"
8149 "Filter more specific routes from updates\n"
8150 "Apply route map to aggregate network\n"
8151 "Route map name\n"
8152 "BGP origin code\n"
8153 "Remote EGP\n"
8154 "Local IGP\n"
8155 "Unknown heritage\n"
8156 "Only aggregate routes with matching MED\n"
8157 "Suppress the selected more specific routes\n"
8158 "Route map with the route selectors\n")
8159{
8160 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8161 int as_set = AGGREGATE_AS_UNSET;
8162
8163 if (origin_s) {
8164 if (strcmp(origin_s, "egp") == 0)
8165 origin = BGP_ORIGIN_EGP;
8166 else if (strcmp(origin_s, "igp") == 0)
8167 origin = BGP_ORIGIN_IGP;
8168 else if (strcmp(origin_s, "incomplete") == 0)
8169 origin = BGP_ORIGIN_INCOMPLETE;
8170 }
8171
8172 if (as_set_s)
8173 as_set = AGGREGATE_AS_SET;
8174
8175 /* Handle configuration removal, otherwise installation. */
554b3b10 8176 if (no)
585f1adc
IR
8177 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8178 SAFI_UNICAST);
554b3b10 8179
585f1adc
IR
8180 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8181 rmap_name, summary_only != NULL, as_set,
8182 origin, match_med != NULL, suppress_map);
718e3744 8183}
8184
718e3744 8185/* Redistribute route treatment. */
d62a17ae 8186void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8187 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8188 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8189 enum blackhole_type bhtype, uint32_t metric,
8190 uint8_t type, unsigned short instance,
8191 route_tag_t tag)
d62a17ae 8192{
4b7e6066 8193 struct bgp_path_info *new;
40381db7
DS
8194 struct bgp_path_info *bpi;
8195 struct bgp_path_info rmap_path;
9bcb3eef 8196 struct bgp_dest *bn;
d62a17ae 8197 struct attr attr;
8198 struct attr *new_attr;
8199 afi_t afi;
b68885f9 8200 route_map_result_t ret;
d62a17ae 8201 struct bgp_redist *red;
8202
8203 /* Make default attribute. */
8204 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8205 /*
8206 * This must not be NULL to satisfy Coverity SA
8207 */
8208 assert(attr.aspath);
9de1f7ff 8209
a4d82a8a 8210 switch (nhtype) {
9de1f7ff
DS
8211 case NEXTHOP_TYPE_IFINDEX:
8212 break;
8213 case NEXTHOP_TYPE_IPV4:
8214 case NEXTHOP_TYPE_IPV4_IFINDEX:
8215 attr.nexthop = nexthop->ipv4;
8216 break;
8217 case NEXTHOP_TYPE_IPV6:
8218 case NEXTHOP_TYPE_IPV6_IFINDEX:
8219 attr.mp_nexthop_global = nexthop->ipv6;
8220 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8221 break;
8222 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8223 switch (p->family) {
8224 case AF_INET:
9de1f7ff 8225 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8226 break;
8227 case AF_INET6:
9de1f7ff
DS
8228 memset(&attr.mp_nexthop_global, 0,
8229 sizeof(attr.mp_nexthop_global));
74489921 8230 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8231 break;
74489921 8232 }
0789eb69 8233 attr.bh_type = bhtype;
9de1f7ff 8234 break;
d62a17ae 8235 }
0789eb69 8236 attr.nh_type = nhtype;
74489921 8237 attr.nh_ifindex = ifindex;
f04a80a5 8238
d62a17ae 8239 attr.med = metric;
957f74c3 8240 attr.distance = distance;
d62a17ae 8241 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8242 attr.tag = tag;
718e3744 8243
d62a17ae 8244 afi = family2afi(p->family);
6aeb9e78 8245
d62a17ae 8246 red = bgp_redist_lookup(bgp, afi, type, instance);
8247 if (red) {
8248 struct attr attr_new;
718e3744 8249
d62a17ae 8250 /* Copy attribute for modification. */
6f4f49b2 8251 attr_new = attr;
718e3744 8252
d62a17ae 8253 if (red->redist_metric_flag)
8254 attr_new.med = red->redist_metric;
718e3744 8255
d62a17ae 8256 /* Apply route-map. */
8257 if (red->rmap.name) {
40381db7
DS
8258 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8259 rmap_path.peer = bgp->peer_self;
8260 rmap_path.attr = &attr_new;
718e3744 8261
d62a17ae 8262 SET_FLAG(bgp->peer_self->rmap_type,
8263 PEER_RMAP_TYPE_REDISTRIBUTE);
8264
1782514f 8265 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8266
8267 bgp->peer_self->rmap_type = 0;
8268
8269 if (ret == RMAP_DENYMATCH) {
8270 /* Free uninterned attribute. */
8271 bgp_attr_flush(&attr_new);
8272
8273 /* Unintern original. */
8274 aspath_unintern(&attr.aspath);
8275 bgp_redistribute_delete(bgp, p, type, instance);
8276 return;
8277 }
8278 }
8279
637e5ba4 8280 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8281 bgp_attr_add_gshut_community(&attr_new);
8282
d62a17ae 8283 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8284 SAFI_UNICAST, p, NULL);
8285
8286 new_attr = bgp_attr_intern(&attr_new);
8287
9bcb3eef 8288 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8289 if (bpi->peer == bgp->peer_self
8290 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8291 break;
8292
40381db7 8293 if (bpi) {
d62a17ae 8294 /* Ensure the (source route) type is updated. */
40381db7
DS
8295 bpi->type = type;
8296 if (attrhash_cmp(bpi->attr, new_attr)
8297 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8298 bgp_attr_unintern(&new_attr);
8299 aspath_unintern(&attr.aspath);
9bcb3eef 8300 bgp_dest_unlock_node(bn);
d62a17ae 8301 return;
8302 } else {
8303 /* The attribute is changed. */
40381db7 8304 bgp_path_info_set_flag(bn, bpi,
18ee8310 8305 BGP_PATH_ATTR_CHANGED);
d62a17ae 8306
8307 /* Rewrite BGP route information. */
40381db7
DS
8308 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8309 bgp_path_info_restore(bn, bpi);
d62a17ae 8310 else
40381db7
DS
8311 bgp_aggregate_decrement(
8312 bgp, p, bpi, afi, SAFI_UNICAST);
8313 bgp_attr_unintern(&bpi->attr);
8314 bpi->attr = new_attr;
8315 bpi->uptime = bgp_clock();
d62a17ae 8316
8317 /* Process change. */
40381db7 8318 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8319 SAFI_UNICAST);
8320 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8321 bgp_dest_unlock_node(bn);
d62a17ae 8322 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8323
8324 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8325 || (bgp->inst_type
8326 == BGP_INSTANCE_TYPE_DEFAULT)) {
8327
8328 vpn_leak_from_vrf_update(
40381db7 8329 bgp_get_default(), bgp, bpi);
ddb5b488 8330 }
d62a17ae 8331 return;
8332 }
8333 }
8334
8335 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8336 bgp->peer_self, new_attr, bn);
1defdda8 8337 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8338
8339 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8340 bgp_path_info_add(bn, new);
9bcb3eef 8341 bgp_dest_unlock_node(bn);
be785e35 8342 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8343 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8344
8345 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8346 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8347
8348 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8349 }
d62a17ae 8350 }
8351
8352 /* Unintern original. */
8353 aspath_unintern(&attr.aspath);
718e3744 8354}
8355
d7c0a89a
QY
8356void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8357 unsigned short instance)
718e3744 8358{
d62a17ae 8359 afi_t afi;
9bcb3eef 8360 struct bgp_dest *dest;
40381db7 8361 struct bgp_path_info *pi;
d62a17ae 8362 struct bgp_redist *red;
718e3744 8363
d62a17ae 8364 afi = family2afi(p->family);
718e3744 8365
d62a17ae 8366 red = bgp_redist_lookup(bgp, afi, type, instance);
8367 if (red) {
9bcb3eef
DS
8368 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8369 SAFI_UNICAST, p, NULL);
d62a17ae 8370
9bcb3eef 8371 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8372 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8373 break;
8374
40381db7 8375 if (pi) {
ddb5b488
PZ
8376 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8377 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8378
8379 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8380 bgp, pi);
ddb5b488 8381 }
40381db7 8382 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8383 bgp_path_info_delete(dest, pi);
8384 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8385 }
9bcb3eef 8386 bgp_dest_unlock_node(dest);
d62a17ae 8387 }
8388}
8389
8390/* Withdraw specified route type's route. */
8391void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8392 unsigned short instance)
d62a17ae 8393{
9bcb3eef 8394 struct bgp_dest *dest;
40381db7 8395 struct bgp_path_info *pi;
d62a17ae 8396 struct bgp_table *table;
8397
8398 table = bgp->rib[afi][SAFI_UNICAST];
8399
9bcb3eef
DS
8400 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8401 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8402 if (pi->peer == bgp->peer_self && pi->type == type
8403 && pi->instance == instance)
d62a17ae 8404 break;
8405
40381db7 8406 if (pi) {
ddb5b488
PZ
8407 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8408 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8409
8410 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8411 bgp, pi);
ddb5b488 8412 }
9bcb3eef 8413 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8414 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8415 bgp_path_info_delete(dest, pi);
8416 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8417 }
718e3744 8418 }
718e3744 8419}
6b0655a2 8420
718e3744 8421/* Static function to display route. */
7d3cae70
DA
8422static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8423 struct vty *vty, json_object *json, bool wide)
718e3744 8424{
be054588 8425 int len = 0;
d62a17ae 8426 char buf[BUFSIZ];
718e3744 8427
d62a17ae 8428 if (p->family == AF_INET) {
c6462ff4 8429 if (!json) {
8228a9a7 8430 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8431 } else {
8432 json_object_string_add(json, "prefix",
8433 inet_ntop(p->family,
8434 &p->u.prefix, buf,
8435 BUFSIZ));
8436 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8437 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8438 json_object_int_add(json, "version", dest->version);
c6462ff4 8439 }
d62a17ae 8440 } else if (p->family == AF_ETHERNET) {
8228a9a7 8441 len = vty_out(vty, "%pFX", p);
b03b8898 8442 } else if (p->family == AF_EVPN) {
57f7feb6 8443 if (!json)
2dbe669b 8444 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8445 else
60466a63 8446 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8447 } else if (p->family == AF_FLOWSPEC) {
8448 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8449 json ?
8450 NLRI_STRING_FORMAT_JSON_SIMPLE :
8451 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8452 } else {
c6462ff4 8453 if (!json)
8228a9a7 8454 len = vty_out(vty, "%pFX", p);
50e05855
AD
8455 else {
8456 json_object_string_add(json, "prefix",
8457 inet_ntop(p->family,
8458 &p->u.prefix, buf,
8459 BUFSIZ));
8460 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8461 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8462 json_object_int_add(json, "version", dest->version);
37d4e0df 8463 }
9c92b5f7 8464 }
d62a17ae 8465
9c92b5f7 8466 if (!json) {
ae248832 8467 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8468 if (len < 1)
8469 vty_out(vty, "\n%*s", 20, " ");
8470 else
8471 vty_out(vty, "%*s", len, " ");
8472 }
718e3744 8473}
8474
d62a17ae 8475enum bgp_display_type {
8476 normal_list,
718e3744 8477};
8478
1d7260a1 8479const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8480{
8481 switch (reason) {
8482 case bgp_path_selection_none:
8483 return "Nothing to Select";
8484 case bgp_path_selection_first:
8485 return "First path received";
8486 case bgp_path_selection_evpn_sticky_mac:
8487 return "EVPN Sticky Mac";
8488 case bgp_path_selection_evpn_seq:
8489 return "EVPN sequence number";
8490 case bgp_path_selection_evpn_lower_ip:
8491 return "EVPN lower IP";
8492 case bgp_path_selection_evpn_local_path:
8493 return "EVPN local ES path";
8494 case bgp_path_selection_evpn_non_proxy:
8495 return "EVPN non proxy";
8496 case bgp_path_selection_weight:
8497 return "Weight";
8498 case bgp_path_selection_local_pref:
8499 return "Local Pref";
8500 case bgp_path_selection_local_route:
8501 return "Local Route";
8502 case bgp_path_selection_confed_as_path:
8503 return "Confederation based AS Path";
8504 case bgp_path_selection_as_path:
8505 return "AS Path";
8506 case bgp_path_selection_origin:
8507 return "Origin";
8508 case bgp_path_selection_med:
8509 return "MED";
8510 case bgp_path_selection_peer:
8511 return "Peer Type";
8512 case bgp_path_selection_confed:
8513 return "Confed Peer Type";
8514 case bgp_path_selection_igp_metric:
8515 return "IGP Metric";
8516 case bgp_path_selection_older:
8517 return "Older Path";
8518 case bgp_path_selection_router_id:
8519 return "Router ID";
8520 case bgp_path_selection_cluster_length:
bcab253c 8521 return "Cluster length";
bbb46eb5
DA
8522 case bgp_path_selection_stale:
8523 return "Path Staleness";
8524 case bgp_path_selection_local_configured:
8525 return "Locally configured route";
8526 case bgp_path_selection_neighbor_ip:
8527 return "Neighbor IP";
8528 case bgp_path_selection_default:
8529 return "Nothing left to compare";
8530 }
8531 return "Invalid (internal error)";
8532}
8533
18ee8310 8534/* Print the short form route status for a bgp_path_info */
4b7e6066 8535static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8536 struct bgp_path_info *path,
82c298be 8537 const struct prefix *p,
d62a17ae 8538 json_object *json_path)
718e3744 8539{
82c298be
DA
8540 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8541
d62a17ae 8542 if (json_path) {
b05a1c8b 8543
d62a17ae 8544 /* Route status display. */
9b6d8fcf 8545 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8546 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8547
9b6d8fcf 8548 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8549 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8550
4056a5f6 8551 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8552 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8553
9b6d8fcf
DS
8554 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8555 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8556 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8557
d62a17ae 8558 /* Selected */
9b6d8fcf 8559 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8560 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8561
9b6d8fcf 8562 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8563 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8564
bbb46eb5 8565 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8566 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8567 json_object_string_add(json_path, "selectionReason",
8568 bgp_path_selection_reason2str(
8569 path->net->reason));
8570 }
b05a1c8b 8571
9b6d8fcf 8572 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8573 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8574
d62a17ae 8575 /* Internal route. */
9b6d8fcf
DS
8576 if ((path->peer->as)
8577 && (path->peer->as == path->peer->local_as))
d62a17ae 8578 json_object_string_add(json_path, "pathFrom",
8579 "internal");
8580 else
8581 json_object_string_add(json_path, "pathFrom",
8582 "external");
b05a1c8b 8583
d62a17ae 8584 return;
8585 }
b05a1c8b 8586
82c298be
DA
8587 /* RPKI validation state */
8588 rpki_state =
8589 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8590
8591 if (rpki_state == RPKI_VALID)
8592 vty_out(vty, "V");
8593 else if (rpki_state == RPKI_INVALID)
8594 vty_out(vty, "I");
8595 else if (rpki_state == RPKI_NOTFOUND)
8596 vty_out(vty, "N");
8597
d62a17ae 8598 /* Route status display. */
9b6d8fcf 8599 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8600 vty_out(vty, "R");
9b6d8fcf 8601 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8602 vty_out(vty, "S");
4056a5f6 8603 else if (bgp_path_suppressed(path))
d62a17ae 8604 vty_out(vty, "s");
9b6d8fcf
DS
8605 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8606 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8607 vty_out(vty, "*");
8608 else
8609 vty_out(vty, " ");
8610
8611 /* Selected */
9b6d8fcf 8612 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8613 vty_out(vty, "h");
9b6d8fcf 8614 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8615 vty_out(vty, "d");
9b6d8fcf 8616 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8617 vty_out(vty, ">");
9b6d8fcf 8618 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8619 vty_out(vty, "=");
8620 else
8621 vty_out(vty, " ");
718e3744 8622
d62a17ae 8623 /* Internal route. */
9b6d8fcf
DS
8624 if (path->peer && (path->peer->as)
8625 && (path->peer->as == path->peer->local_as))
d62a17ae 8626 vty_out(vty, "i");
8627 else
8628 vty_out(vty, " ");
b40d939b 8629}
8630
2ba93fd6
DA
8631static char *bgp_nexthop_hostname(struct peer *peer,
8632 struct bgp_nexthop_cache *bnc)
25b5da8d 8633{
892fedb6 8634 if (peer->hostname
aef999a2 8635 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8636 return peer->hostname;
8637 return NULL;
8638}
8639
b40d939b 8640/* called from terminal list command */
bd494ec5 8641void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8642 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8643 json_object *json_paths, bool wide)
d62a17ae 8644{
aef999a2 8645 int len;
515c2602 8646 struct attr *attr = path->attr;
d62a17ae 8647 json_object *json_path = NULL;
8648 json_object *json_nexthops = NULL;
8649 json_object *json_nexthop_global = NULL;
8650 json_object *json_nexthop_ll = NULL;
6f214dd3 8651 json_object *json_ext_community = NULL;
9df8b37c 8652 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8653 bool nexthop_self =
9b6d8fcf 8654 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8655 bool nexthop_othervrf = false;
43089216 8656 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8657 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8658 char *nexthop_hostname =
8659 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8660 char esi_buf[ESI_STR_LEN];
d62a17ae 8661
8662 if (json_paths)
8663 json_path = json_object_new_object();
8664
8665 /* short status lead text */
82c298be 8666 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8667
8668 if (!json_paths) {
8669 /* print prefix and mask */
8670 if (!display)
7d3cae70 8671 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8672 else
ae248832 8673 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8674 } else {
7d3cae70 8675 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8676 }
47fc97cc 8677
9df8b37c
PZ
8678 /*
8679 * If vrf id of nexthop is different from that of prefix,
8680 * set up printable string to append
8681 */
9b6d8fcf 8682 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8683 const char *self = "";
8684
8685 if (nexthop_self)
8686 self = "<";
8687
8688 nexthop_othervrf = true;
9b6d8fcf 8689 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8690
9b6d8fcf 8691 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8692 snprintf(vrf_id_str, sizeof(vrf_id_str),
8693 "@%s%s", VRFID_NONE_STR, self);
8694 else
8695 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8696 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8697
9b6d8fcf
DS
8698 if (path->extra->bgp_orig->inst_type
8699 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8700
9b6d8fcf 8701 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8702 } else {
8703 const char *self = "";
8704
8705 if (nexthop_self)
8706 self = "<";
8707
8708 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8709 }
8710
445c2480
DS
8711 /*
8712 * For ENCAP and EVPN routes, nexthop address family is not
8713 * neccessarily the same as the prefix address family.
8714 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8715 * EVPN routes are also exchanged with a MP nexthop. Currently,
8716 * this
8717 * is only IPv4, the value will be present in either
8718 * attr->nexthop or
8719 * attr->mp_nexthop_global_in
8720 */
8721 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8722 char buf[BUFSIZ];
8723 char nexthop[128];
8724 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8725
8726 switch (af) {
8727 case AF_INET:
772270f3
QY
8728 snprintf(nexthop, sizeof(nexthop), "%s",
8729 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8730 BUFSIZ));
445c2480
DS
8731 break;
8732 case AF_INET6:
772270f3
QY
8733 snprintf(nexthop, sizeof(nexthop), "%s",
8734 inet_ntop(af, &attr->mp_nexthop_global, buf,
8735 BUFSIZ));
445c2480
DS
8736 break;
8737 default:
772270f3 8738 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8739 break;
d62a17ae 8740 }
d62a17ae 8741
445c2480
DS
8742 if (json_paths) {
8743 json_nexthop_global = json_object_new_object();
8744
515c2602
DA
8745 json_object_string_add(json_nexthop_global, "ip",
8746 nexthop);
8747
939a97f4 8748 if (path->peer->hostname)
515c2602
DA
8749 json_object_string_add(json_nexthop_global,
8750 "hostname",
939a97f4 8751 path->peer->hostname);
515c2602
DA
8752
8753 json_object_string_add(json_nexthop_global, "afi",
8754 (af == AF_INET) ? "ipv4"
8755 : "ipv6");
445c2480
DS
8756 json_object_boolean_true_add(json_nexthop_global,
8757 "used");
aef999a2
DA
8758 } else {
8759 if (nexthop_hostname)
8760 len = vty_out(vty, "%s(%s)%s", nexthop,
8761 nexthop_hostname, vrf_id_str);
8762 else
8763 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8764
ae248832 8765 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8766 if (len < 1)
8767 vty_out(vty, "\n%*s", 36, " ");
8768 else
8769 vty_out(vty, "%*s", len, " ");
8770 }
445c2480
DS
8771 } else if (safi == SAFI_EVPN) {
8772 if (json_paths) {
8773 json_nexthop_global = json_object_new_object();
8774
c949c771
DA
8775 json_object_string_addf(json_nexthop_global, "ip",
8776 "%pI4", &attr->nexthop);
515c2602 8777
939a97f4 8778 if (path->peer->hostname)
515c2602
DA
8779 json_object_string_add(json_nexthop_global,
8780 "hostname",
939a97f4 8781 path->peer->hostname);
515c2602 8782
a4d82a8a
PZ
8783 json_object_string_add(json_nexthop_global, "afi",
8784 "ipv4");
445c2480
DS
8785 json_object_boolean_true_add(json_nexthop_global,
8786 "used");
aef999a2
DA
8787 } else {
8788 if (nexthop_hostname)
8789 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8790 nexthop_hostname, vrf_id_str);
8791 else
8792 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8793 vrf_id_str);
8794
ae248832 8795 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8796 if (len < 1)
8797 vty_out(vty, "\n%*s", 36, " ");
8798 else
8799 vty_out(vty, "%*s", len, " ");
8800 }
d33fc23b 8801 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8802 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8803 if (json_paths) {
8804 json_nexthop_global = json_object_new_object();
515c2602 8805
026b914a
PG
8806 json_object_string_add(json_nexthop_global,
8807 "afi", "ipv4");
c949c771
DA
8808 json_object_string_addf(json_nexthop_global,
8809 "ip", "%pI4",
8810 &attr->nexthop);
515c2602 8811
939a97f4 8812 if (path->peer->hostname)
515c2602
DA
8813 json_object_string_add(
8814 json_nexthop_global, "hostname",
939a97f4 8815 path->peer->hostname);
515c2602 8816
50e05855
AD
8817 json_object_boolean_true_add(
8818 json_nexthop_global,
026b914a
PG
8819 "used");
8820 } else {
aef999a2
DA
8821 if (nexthop_hostname)
8822 len = vty_out(vty, "%pI4(%s)%s",
8823 &attr->nexthop,
8824 nexthop_hostname,
8825 vrf_id_str);
8826 else
8827 len = vty_out(vty, "%pI4%s",
8828 &attr->nexthop,
8829 vrf_id_str);
8830
ae248832 8831 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8832 if (len < 1)
8833 vty_out(vty, "\n%*s", 36, " ");
8834 else
8835 vty_out(vty, "%*s", len, " ");
026b914a
PG
8836 }
8837 }
d33fc23b 8838 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8839 if (json_paths) {
8840 json_nexthop_global = json_object_new_object();
d62a17ae 8841
c949c771
DA
8842 json_object_string_addf(json_nexthop_global, "ip",
8843 "%pI4", &attr->nexthop);
515c2602 8844
939a97f4 8845 if (path->peer->hostname)
515c2602
DA
8846 json_object_string_add(json_nexthop_global,
8847 "hostname",
939a97f4 8848 path->peer->hostname);
445c2480 8849
a4d82a8a
PZ
8850 json_object_string_add(json_nexthop_global, "afi",
8851 "ipv4");
445c2480
DS
8852 json_object_boolean_true_add(json_nexthop_global,
8853 "used");
8854 } else {
aef999a2
DA
8855 if (nexthop_hostname)
8856 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8857 nexthop_hostname, vrf_id_str);
8858 else
8859 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8860 vrf_id_str);
9df8b37c 8861
ae248832 8862 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8863 if (len < 1)
8864 vty_out(vty, "\n%*s", 36, " ");
8865 else
8866 vty_out(vty, "%*s", len, " ");
d62a17ae 8867 }
445c2480 8868 }
b05a1c8b 8869
445c2480 8870 /* IPv6 Next Hop */
a4d82a8a 8871 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8872 if (json_paths) {
8873 json_nexthop_global = json_object_new_object();
c949c771
DA
8874 json_object_string_addf(json_nexthop_global, "ip",
8875 "%pI6",
8876 &attr->mp_nexthop_global);
515c2602 8877
939a97f4 8878 if (path->peer->hostname)
515c2602
DA
8879 json_object_string_add(json_nexthop_global,
8880 "hostname",
939a97f4 8881 path->peer->hostname);
515c2602 8882
a4d82a8a
PZ
8883 json_object_string_add(json_nexthop_global, "afi",
8884 "ipv6");
8885 json_object_string_add(json_nexthop_global, "scope",
8886 "global");
445c2480
DS
8887
8888 /* We display both LL & GL if both have been
8889 * received */
0606039c
DA
8890 if ((attr->mp_nexthop_len
8891 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8892 || (path->peer->conf_if)) {
a4d82a8a 8893 json_nexthop_ll = json_object_new_object();
c949c771
DA
8894 json_object_string_addf(
8895 json_nexthop_ll, "ip", "%pI6",
8896 &attr->mp_nexthop_local);
515c2602 8897
939a97f4 8898 if (path->peer->hostname)
515c2602
DA
8899 json_object_string_add(
8900 json_nexthop_ll, "hostname",
939a97f4 8901 path->peer->hostname);
515c2602 8902
a4d82a8a
PZ
8903 json_object_string_add(json_nexthop_ll, "afi",
8904 "ipv6");
8905 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8906 "link-local");
d62a17ae 8907
a4d82a8a
PZ
8908 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8909 &attr->mp_nexthop_local)
445c2480
DS
8910 != 0)
8911 && !attr->mp_nexthop_prefer_global)
d62a17ae 8912 json_object_boolean_true_add(
a4d82a8a 8913 json_nexthop_ll, "used");
445c2480
DS
8914 else
8915 json_object_boolean_true_add(
a4d82a8a 8916 json_nexthop_global, "used");
445c2480
DS
8917 } else
8918 json_object_boolean_true_add(
8919 json_nexthop_global, "used");
8920 } else {
8921 /* Display LL if LL/Global both in table unless
8922 * prefer-global is set */
0606039c
DA
8923 if (((attr->mp_nexthop_len
8924 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8925 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8926 || (path->peer->conf_if)) {
8927 if (path->peer->conf_if) {
a4d82a8a 8928 len = vty_out(vty, "%s",
9b6d8fcf 8929 path->peer->conf_if);
ae248832
MK
8930 /* len of IPv6 addr + max len of def
8931 * ifname */
8932 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8933
8934 if (len < 1)
a4d82a8a 8935 vty_out(vty, "\n%*s", 36, " ");
445c2480 8936 else
a4d82a8a 8937 vty_out(vty, "%*s", len, " ");
d62a17ae 8938 } else {
aef999a2
DA
8939 if (nexthop_hostname)
8940 len = vty_out(
8941 vty, "%pI6(%s)%s",
8942 &attr->mp_nexthop_local,
8943 nexthop_hostname,
8944 vrf_id_str);
8945 else
8946 len = vty_out(
8947 vty, "%pI6%s",
8948 &attr->mp_nexthop_local,
8949 vrf_id_str);
8950
ae248832 8951 len = wide ? (41 - len) : (16 - len);
d62a17ae 8952
8953 if (len < 1)
a4d82a8a 8954 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8955 else
a4d82a8a 8956 vty_out(vty, "%*s", len, " ");
d62a17ae 8957 }
445c2480 8958 } else {
aef999a2
DA
8959 if (nexthop_hostname)
8960 len = vty_out(vty, "%pI6(%s)%s",
8961 &attr->mp_nexthop_global,
8962 nexthop_hostname,
8963 vrf_id_str);
8964 else
8965 len = vty_out(vty, "%pI6%s",
8966 &attr->mp_nexthop_global,
8967 vrf_id_str);
8968
ae248832 8969 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8970
8971 if (len < 1)
8972 vty_out(vty, "\n%*s", 36, " ");
8973 else
8974 vty_out(vty, "%*s", len, " ");
d62a17ae 8975 }
8976 }
445c2480 8977 }
718e3744 8978
445c2480
DS
8979 /* MED/Metric */
8980 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8981 if (json_paths)
50e05855 8982 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8983 else if (wide)
8984 vty_out(vty, "%7u", attr->med);
0fbac0b4 8985 else
445c2480 8986 vty_out(vty, "%10u", attr->med);
ae248832
MK
8987 else if (!json_paths) {
8988 if (wide)
8989 vty_out(vty, "%*s", 7, " ");
8990 else
8991 vty_out(vty, "%*s", 10, " ");
8992 }
d62a17ae 8993
445c2480
DS
8994 /* Local Pref */
8995 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8996 if (json_paths)
50e05855 8997 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8998 attr->local_pref);
8999 else
445c2480
DS
9000 vty_out(vty, "%7u", attr->local_pref);
9001 else if (!json_paths)
9002 vty_out(vty, " ");
d62a17ae 9003
445c2480
DS
9004 if (json_paths)
9005 json_object_int_add(json_path, "weight", attr->weight);
9006 else
9007 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9008
445c2480
DS
9009 if (json_paths) {
9010 char buf[BUFSIZ];
a4d82a8a
PZ
9011 json_object_string_add(
9012 json_path, "peerId",
9b6d8fcf 9013 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 9014 }
b05a1c8b 9015
445c2480
DS
9016 /* Print aspath */
9017 if (attr->aspath) {
0fbac0b4 9018 if (json_paths)
50e05855 9019 json_object_string_add(json_path, "path",
0fbac0b4
DA
9020 attr->aspath->str);
9021 else
445c2480 9022 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9023 }
f1aa5d8a 9024
445c2480
DS
9025 /* Print origin */
9026 if (json_paths)
a4d82a8a
PZ
9027 json_object_string_add(json_path, "origin",
9028 bgp_origin_long_str[attr->origin]);
445c2480
DS
9029 else
9030 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9031
9df8b37c 9032 if (json_paths) {
d071f237 9033 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9034 json_object_string_add(json_path, "esi",
9035 esi_to_str(&attr->esi,
9036 esi_buf, sizeof(esi_buf)));
9037 }
6f214dd3
CS
9038 if (safi == SAFI_EVPN &&
9039 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9040 json_ext_community = json_object_new_object();
9041 json_object_string_add(json_ext_community,
9042 "string",
9043 attr->ecommunity->str);
9044 json_object_object_add(json_path,
9045 "extendedCommunity",
9046 json_ext_community);
9047 }
9048
9df8b37c
PZ
9049 if (nexthop_self)
9050 json_object_boolean_true_add(json_path,
9051 "announceNexthopSelf");
9052 if (nexthop_othervrf) {
9053 json_object_string_add(json_path, "nhVrfName",
9054 nexthop_vrfname);
9055
9056 json_object_int_add(json_path, "nhVrfId",
9057 ((nexthop_vrfid == VRF_UNKNOWN)
9058 ? -1
9059 : (int)nexthop_vrfid));
9060 }
9061 }
9062
d62a17ae 9063 if (json_paths) {
9064 if (json_nexthop_global || json_nexthop_ll) {
9065 json_nexthops = json_object_new_array();
f1aa5d8a 9066
d62a17ae 9067 if (json_nexthop_global)
9068 json_object_array_add(json_nexthops,
9069 json_nexthop_global);
f1aa5d8a 9070
d62a17ae 9071 if (json_nexthop_ll)
9072 json_object_array_add(json_nexthops,
9073 json_nexthop_ll);
f1aa5d8a 9074
d62a17ae 9075 json_object_object_add(json_path, "nexthops",
9076 json_nexthops);
9077 }
9078
9079 json_object_array_add(json_paths, json_path);
9080 } else {
9081 vty_out(vty, "\n");
6f214dd3 9082
b5e140c8 9083 if (safi == SAFI_EVPN) {
d071f237 9084 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9085 /* XXX - add these params to the json out */
b5e140c8 9086 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9087 vty_out(vty, "ESI:%s",
9088 esi_to_str(&attr->esi, esi_buf,
9089 sizeof(esi_buf)));
60605cbc 9090
229587fb 9091 vty_out(vty, "\n");
b5e140c8
AK
9092 }
9093 if (attr->flag &
9094 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9095 vty_out(vty, "%*s", 20, " ");
9096 vty_out(vty, "%s\n", attr->ecommunity->str);
9097 }
6f214dd3
CS
9098 }
9099
49e5a4a0 9100#ifdef ENABLE_BGP_VNC
d62a17ae 9101 /* prints an additional line, indented, with VNC info, if
9102 * present */
9103 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9104 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9105#endif
d62a17ae 9106 }
9107}
718e3744 9108
9109/* called from terminal list command */
7d3cae70
DA
9110void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9111 const struct prefix *p, struct attr *attr, safi_t safi,
9112 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9113{
9114 json_object *json_status = NULL;
9115 json_object *json_net = NULL;
aef999a2 9116 int len;
d62a17ae 9117 char buff[BUFSIZ];
dc387b0f 9118
d62a17ae 9119 /* Route status display. */
9120 if (use_json) {
9121 json_status = json_object_new_object();
9122 json_net = json_object_new_object();
9123 } else {
9124 vty_out(vty, "*");
9125 vty_out(vty, ">");
9126 vty_out(vty, " ");
9127 }
718e3744 9128
d62a17ae 9129 /* print prefix and mask */
50e05855 9130 if (use_json) {
dc387b0f
LK
9131 if (safi == SAFI_EVPN)
9132 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9133 else if (p->family == AF_INET || p->family == AF_INET6) {
9134 json_object_string_add(
9135 json_net, "addrPrefix",
9136 inet_ntop(p->family, &p->u.prefix, buff,
9137 BUFSIZ));
9138 json_object_int_add(json_net, "prefixLen",
9139 p->prefixlen);
67d7e256 9140 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9141 }
50e05855 9142 } else
7d3cae70 9143 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9144
9145 /* Print attribute */
9146 if (attr) {
9147 if (use_json) {
9148 if (p->family == AF_INET
9149 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9150 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9151 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9152 json_object_string_addf(
9153 json_net, "nextHop", "%pI4",
9154 &attr->mp_nexthop_global_in);
d62a17ae 9155 else
c949c771
DA
9156 json_object_string_addf(
9157 json_net, "nextHop", "%pI4",
9158 &attr->nexthop);
d62a17ae 9159 } else if (p->family == AF_INET6
9160 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9161 json_object_string_addf(
9162 json_net, "nextHopGlobal", "%pI6",
9163 &attr->mp_nexthop_global);
23d0a753
DA
9164 } else if (p->family == AF_EVPN
9165 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9166 json_object_string_addf(
9167 json_net, "nextHop", "%pI4",
9168 &attr->mp_nexthop_global_in);
23d0a753 9169 }
d62a17ae 9170
9171 if (attr->flag
9172 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9173 json_object_int_add(json_net, "metric",
9174 attr->med);
9175
0fbac0b4 9176 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9177 json_object_int_add(json_net, "locPrf",
0fbac0b4 9178 attr->local_pref);
d62a17ae 9179
9180 json_object_int_add(json_net, "weight", attr->weight);
9181
9182 /* Print aspath */
0fbac0b4 9183 if (attr->aspath)
50e05855 9184 json_object_string_add(json_net, "path",
0fbac0b4 9185 attr->aspath->str);
d62a17ae 9186
9187 /* Print origin */
9188 json_object_string_add(json_net, "bgpOriginCode",
9189 bgp_origin_str[attr->origin]);
9190 } else {
9191 if (p->family == AF_INET
9192 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9193 || safi == SAFI_EVPN
9194 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9195 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9196 || safi == SAFI_EVPN)
23d0a753
DA
9197 vty_out(vty, "%-16pI4",
9198 &attr->mp_nexthop_global_in);
ae248832 9199 else if (wide)
23d0a753 9200 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9201 else
23d0a753 9202 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9203 } else if (p->family == AF_INET6
9204 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9205 char buf[BUFSIZ];
9206
9207 len = vty_out(
9208 vty, "%s",
9209 inet_ntop(AF_INET6,
9210 &attr->mp_nexthop_global, buf,
9211 BUFSIZ));
ae248832 9212 len = wide ? (41 - len) : (16 - len);
d62a17ae 9213 if (len < 1)
9214 vty_out(vty, "\n%*s", 36, " ");
9215 else
9216 vty_out(vty, "%*s", len, " ");
9217 }
9218 if (attr->flag
9219 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9220 if (wide)
9221 vty_out(vty, "%7u", attr->med);
9222 else
9223 vty_out(vty, "%10u", attr->med);
9224 else if (wide)
9225 vty_out(vty, " ");
d62a17ae 9226 else
9227 vty_out(vty, " ");
718e3744 9228
d62a17ae 9229 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9230 vty_out(vty, "%7u", attr->local_pref);
9231 else
9232 vty_out(vty, " ");
9233
9234 vty_out(vty, "%7u ", attr->weight);
9235
9236 /* Print aspath */
9237 if (attr->aspath)
9238 aspath_print_vty(vty, "%s", attr->aspath, " ");
9239
9240 /* Print origin */
9241 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9242 }
9243 }
9244 if (use_json) {
9245 json_object_boolean_true_add(json_status, "*");
9246 json_object_boolean_true_add(json_status, ">");
9247 json_object_object_add(json_net, "appliedStatusSymbols",
9248 json_status);
1608ff77 9249
dc387b0f
LK
9250 prefix2str(p, buff, PREFIX_STRLEN);
9251 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9252 } else
9253 vty_out(vty, "\n");
9254}
9255
bd494ec5 9256void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9257 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9258 json_object *json)
9259{
9260 json_object *json_out = NULL;
9261 struct attr *attr;
9262 mpls_label_t label = MPLS_INVALID_LABEL;
9263
9b6d8fcf 9264 if (!path->extra)
d62a17ae 9265 return;
9266
9267 if (json)
9268 json_out = json_object_new_object();
9269
9270 /* short status lead text */
82c298be 9271 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9272
9273 /* print prefix and mask */
9274 if (json == NULL) {
9275 if (!display)
7d3cae70 9276 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9277 else
9278 vty_out(vty, "%*s", 17, " ");
9279 }
9280
9281 /* Print attribute */
9b6d8fcf 9282 attr = path->attr;
05864da7
DS
9283 if (((p->family == AF_INET)
9284 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9285 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9286 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9287 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9288 || safi == SAFI_EVPN) {
9289 if (json)
c949c771
DA
9290 json_object_string_addf(
9291 json_out, "mpNexthopGlobalIn", "%pI4",
9292 &attr->mp_nexthop_global_in);
05864da7 9293 else
23d0a753
DA
9294 vty_out(vty, "%-16pI4",
9295 &attr->mp_nexthop_global_in);
05864da7
DS
9296 } else {
9297 if (json)
c949c771
DA
9298 json_object_string_addf(json_out, "nexthop",
9299 "%pI4", &attr->nexthop);
05864da7 9300 else
23d0a753 9301 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9302 }
9303 } else if (((p->family == AF_INET6)
9304 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9305 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9306 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9307 char buf_a[512];
9308
9309 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9310 if (json)
c949c771
DA
9311 json_object_string_addf(
9312 json_out, "mpNexthopGlobalIn", "%pI6",
9313 &attr->mp_nexthop_global);
05864da7
DS
9314 else
9315 vty_out(vty, "%s",
9316 inet_ntop(AF_INET6,
9317 &attr->mp_nexthop_global,
9318 buf_a, sizeof(buf_a)));
9319 } else if (attr->mp_nexthop_len
9320 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9321 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9322 &attr->mp_nexthop_global,
9323 &attr->mp_nexthop_local);
9324 if (json)
9325 json_object_string_add(json_out,
9326 "mpNexthopGlobalLocal",
9327 buf_a);
9328 else
9329 vty_out(vty, "%s", buf_a);
d62a17ae 9330 }
9331 }
9332
9b6d8fcf 9333 label = decode_label(&path->extra->label[0]);
d62a17ae 9334
9335 if (bgp_is_valid_label(&label)) {
9336 if (json) {
9337 json_object_int_add(json_out, "notag", label);
9338 json_object_array_add(json, json_out);
9339 } else {
9340 vty_out(vty, "notag/%d", label);
9341 vty_out(vty, "\n");
9342 }
700ddfed
PG
9343 } else if (!json)
9344 vty_out(vty, "\n");
d62a17ae 9345}
718e3744 9346
bd494ec5 9347void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9348 struct bgp_path_info *path, int display,
d62a17ae 9349 json_object *json_paths)
718e3744 9350{
d62a17ae 9351 struct attr *attr;
14f51eba 9352 char buf[BUFSIZ] = {0};
d62a17ae 9353 json_object *json_path = NULL;
14f51eba
LK
9354 json_object *json_nexthop = NULL;
9355 json_object *json_overlay = NULL;
856ca177 9356
9b6d8fcf 9357 if (!path->extra)
d62a17ae 9358 return;
718e3744 9359
14f51eba
LK
9360 if (json_paths) {
9361 json_path = json_object_new_object();
9362 json_overlay = json_object_new_object();
9363 json_nexthop = json_object_new_object();
9364 }
9365
d62a17ae 9366 /* short status lead text */
82c298be 9367 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9368
d62a17ae 9369 /* print prefix and mask */
9370 if (!display)
7d3cae70 9371 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9372 else
9373 vty_out(vty, "%*s", 17, " ");
9374
9375 /* Print attribute */
9b6d8fcf 9376 attr = path->attr;
05864da7
DS
9377 char buf1[BUFSIZ];
9378 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9379
05864da7
DS
9380 switch (af) {
9381 case AF_INET:
9382 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9383 if (!json_path) {
9384 vty_out(vty, "%-16s", buf);
9385 } else {
9386 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9387
05864da7 9388 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9389
05864da7
DS
9390 json_object_object_add(json_path, "nexthop",
9391 json_nexthop);
9392 }
9393 break;
9394 case AF_INET6:
9395 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9396 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9397 if (!json_path) {
9398 vty_out(vty, "%s(%s)", buf, buf1);
9399 } else {
9400 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9401
05864da7
DS
9402 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9403 buf1);
14f51eba 9404
05864da7 9405 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9406
05864da7
DS
9407 json_object_object_add(json_path, "nexthop",
9408 json_nexthop);
9409 }
9410 break;
9411 default:
9412 if (!json_path) {
9413 vty_out(vty, "?");
9414 } else {
9415 json_object_string_add(json_nexthop, "Error",
9416 "Unsupported address-family");
d62a17ae 9417 }
05864da7 9418 }
988258b4 9419
6c924775
DS
9420 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9421
9422 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9423 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9424 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9425 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9426
05864da7
DS
9427 if (!json_path)
9428 vty_out(vty, "/%s", buf);
9429 else
9430 json_object_string_add(json_overlay, "gw", buf);
9431
9432 if (attr->ecommunity) {
9433 char *mac = NULL;
9434 struct ecommunity_val *routermac = ecommunity_lookup(
9435 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9436 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9437
9438 if (routermac)
9439 mac = ecom_mac2str((char *)routermac->val);
9440 if (mac) {
9441 if (!json_path) {
c4efd0f4 9442 vty_out(vty, "/%s", mac);
05864da7
DS
9443 } else {
9444 json_object_string_add(json_overlay, "rmac",
9445 mac);
988258b4 9446 }
05864da7 9447 XFREE(MTYPE_TMP, mac);
988258b4 9448 }
05864da7 9449 }
718e3744 9450
05864da7
DS
9451 if (!json_path) {
9452 vty_out(vty, "\n");
9453 } else {
9454 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9455
05864da7 9456 json_object_array_add(json_paths, json_path);
14f51eba 9457 }
d62a17ae 9458}
718e3744 9459
d62a17ae 9460/* dampening route */
5f040085
DS
9461static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9462 struct bgp_path_info *path, int display,
9463 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9464 json_object *json_paths)
d62a17ae 9465{
e5be8c1d 9466 struct attr *attr = path->attr;
d62a17ae 9467 int len;
9468 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9469 json_object *json_path = NULL;
9470
9471 if (use_json)
9472 json_path = json_object_new_object();
d62a17ae 9473
9474 /* short status lead text */
e5be8c1d 9475 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9476
9477 /* print prefix and mask */
9478 if (!use_json) {
9479 if (!display)
7d3cae70 9480 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9481 else
9482 vty_out(vty, "%*s", 17, " ");
d62a17ae 9483
e5be8c1d
DA
9484 len = vty_out(vty, "%s", path->peer->host);
9485 len = 17 - len;
9486
9487 if (len < 1)
d62a17ae 9488 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9489 else
9490 vty_out(vty, "%*s", len, " ");
d62a17ae 9491
9b6d8fcf
DS
9492 vty_out(vty, "%s ",
9493 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9494 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9495 use_json, NULL));
d62a17ae 9496
e5be8c1d 9497 if (attr->aspath)
05864da7 9498 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9499
05864da7
DS
9500 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9501
d62a17ae 9502 vty_out(vty, "\n");
e5be8c1d
DA
9503 } else {
9504 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9505 safi, use_json, json_path);
9506
9507 if (attr->aspath)
9508 json_object_string_add(json_path, "asPath",
9509 attr->aspath->str);
9510
9511 json_object_string_add(json_path, "origin",
9512 bgp_origin_str[attr->origin]);
9513 json_object_string_add(json_path, "peerHost", path->peer->host);
9514
9515 json_object_array_add(json_paths, json_path);
9516 }
d62a17ae 9517}
718e3744 9518
d62a17ae 9519/* flap route */
5f040085
DS
9520static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9521 struct bgp_path_info *path, int display,
9522 afi_t afi, safi_t safi, bool use_json,
31258046 9523 json_object *json_paths)
784d3a42 9524{
31258046 9525 struct attr *attr = path->attr;
d62a17ae 9526 struct bgp_damp_info *bdi;
9527 char timebuf[BGP_UPTIME_LEN];
9528 int len;
31258046 9529 json_object *json_path = NULL;
784d3a42 9530
9b6d8fcf 9531 if (!path->extra)
d62a17ae 9532 return;
784d3a42 9533
31258046
DA
9534 if (use_json)
9535 json_path = json_object_new_object();
9536
9b6d8fcf 9537 bdi = path->extra->damp_info;
784d3a42 9538
d62a17ae 9539 /* short status lead text */
31258046 9540 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9541
d62a17ae 9542 if (!use_json) {
9543 if (!display)
7d3cae70 9544 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9545 else
9546 vty_out(vty, "%*s", 17, " ");
784d3a42 9547
31258046
DA
9548 len = vty_out(vty, "%s", path->peer->host);
9549 len = 16 - len;
9550 if (len < 1)
d62a17ae 9551 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9552 else
9553 vty_out(vty, "%*s", len, " ");
784d3a42 9554
31258046
DA
9555 len = vty_out(vty, "%d", bdi->flap);
9556 len = 5 - len;
9557 if (len < 1)
d62a17ae 9558 vty_out(vty, " ");
d62a17ae 9559 else
9560 vty_out(vty, "%*s", len, " ");
d62a17ae 9561
996c9314
LB
9562 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9563 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9564
31258046
DA
9565 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9566 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9567 vty_out(vty, "%s ",
9b6d8fcf 9568 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9569 BGP_UPTIME_LEN, afi,
31258046
DA
9570 safi, use_json, NULL));
9571 else
d62a17ae 9572 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9573
31258046 9574 if (attr->aspath)
05864da7 9575 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9576
05864da7
DS
9577 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9578
d62a17ae 9579 vty_out(vty, "\n");
31258046
DA
9580 } else {
9581 json_object_string_add(json_path, "peerHost", path->peer->host);
9582 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9583
9584 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9585 json_path);
9586
9587 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9588 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9589 bgp_damp_reuse_time_vty(vty, path, timebuf,
9590 BGP_UPTIME_LEN, afi, safi,
9591 use_json, json_path);
9592
9593 if (attr->aspath)
9594 json_object_string_add(json_path, "asPath",
9595 attr->aspath->str);
9596
9597 json_object_string_add(json_path, "origin",
9598 bgp_origin_str[attr->origin]);
9599
9600 json_object_array_add(json_paths, json_path);
9601 }
d62a17ae 9602}
9603
9604static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9605 int *first, const char *header,
9606 json_object *json_adv_to)
9607{
9608 char buf1[INET6_ADDRSTRLEN];
9609 json_object *json_peer = NULL;
9610
9611 if (json_adv_to) {
9612 /* 'advertised-to' is a dictionary of peers we have advertised
9613 * this
9614 * prefix too. The key is the peer's IP or swpX, the value is
9615 * the
9616 * hostname if we know it and "" if not.
9617 */
9618 json_peer = json_object_new_object();
9619
9620 if (peer->hostname)
9621 json_object_string_add(json_peer, "hostname",
9622 peer->hostname);
9623
9624 if (peer->conf_if)
9625 json_object_object_add(json_adv_to, peer->conf_if,
9626 json_peer);
9627 else
9628 json_object_object_add(
9629 json_adv_to,
9630 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9631 json_peer);
9632 } else {
9633 if (*first) {
9634 vty_out(vty, "%s", header);
9635 *first = 0;
9636 }
9637
9638 if (peer->hostname
892fedb6 9639 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9640 if (peer->conf_if)
9641 vty_out(vty, " %s(%s)", peer->hostname,
9642 peer->conf_if);
9643 else
9644 vty_out(vty, " %s(%s)", peer->hostname,
9645 sockunion2str(&peer->su, buf1,
9646 SU_ADDRSTRLEN));
9647 } else {
9648 if (peer->conf_if)
9649 vty_out(vty, " %s", peer->conf_if);
9650 else
9651 vty_out(vty, " %s",
9652 sockunion2str(&peer->su, buf1,
9653 SU_ADDRSTRLEN));
9654 }
9655 }
784d3a42
PG
9656}
9657
dcc68b5e
MS
9658static void route_vty_out_tx_ids(struct vty *vty,
9659 struct bgp_addpath_info_data *d)
9660{
9661 int i;
9662
9663 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9664 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9665 d->addpath_tx_id[i],
9666 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9667 }
9668}
9669
5e4d4c8a 9670static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9671 struct bgp_path_info *pi,
9672 struct attr *attr,
9673 json_object *json_path)
5e4d4c8a
AK
9674{
9675 char esi_buf[ESI_STR_LEN];
9676 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9677 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9678 ATTR_ES_PEER_ROUTER);
9679 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9680 ATTR_ES_PEER_ACTIVE);
9681 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9682 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9683 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9684 if (json_path) {
9685 json_object *json_es_info = NULL;
9686
9687 json_object_string_add(
9688 json_path, "esi",
9689 esi_buf);
9690 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9691 json_es_info = json_object_new_object();
9692 if (es_local)
9693 json_object_boolean_true_add(
9694 json_es_info, "localEs");
9695 if (peer_active)
9696 json_object_boolean_true_add(
9697 json_es_info, "peerActive");
9698 if (peer_proxy)
9699 json_object_boolean_true_add(
9700 json_es_info, "peerProxy");
9701 if (peer_router)
9702 json_object_boolean_true_add(
9703 json_es_info, "peerRouter");
9704 if (attr->mm_sync_seqnum)
9705 json_object_int_add(
9706 json_es_info, "peerSeq",
9707 attr->mm_sync_seqnum);
9708 json_object_object_add(
9709 json_path, "es_info",
9710 json_es_info);
9711 }
9712 } else {
9713 if (bgp_evpn_attr_is_sync(attr))
9714 vty_out(vty,
9715 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9716 esi_buf,
9717 es_local ? "local-es":"",
9718 peer_proxy ? "proxy " : "",
9719 peer_active ? "active ":"",
9720 peer_router ? "router ":"",
9721 attr->mm_sync_seqnum);
9722 else
9723 vty_out(vty, " ESI %s %s\n",
9724 esi_buf,
9725 es_local ? "local-es":"");
9726 }
9727}
9728
4933eaaf
DS
9729void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9730 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9731 enum rpki_states rpki_curr_state,
9732 json_object *json_paths)
d62a17ae 9733{
9734 char buf[INET6_ADDRSTRLEN];
9735 char buf1[BUFSIZ];
515c2602 9736 struct attr *attr = path->attr;
d62a17ae 9737 int sockunion_vty_out(struct vty *, union sockunion *);
9738 time_t tbuf;
9739 json_object *json_bestpath = NULL;
9740 json_object *json_cluster_list = NULL;
9741 json_object *json_cluster_list_list = NULL;
9742 json_object *json_ext_community = NULL;
9743 json_object *json_last_update = NULL;
7fd077aa 9744 json_object *json_pmsi = NULL;
d62a17ae 9745 json_object *json_nexthop_global = NULL;
9746 json_object *json_nexthop_ll = NULL;
9747 json_object *json_nexthops = NULL;
9748 json_object *json_path = NULL;
9749 json_object *json_peer = NULL;
9750 json_object *json_string = NULL;
9751 json_object *json_adv_to = NULL;
9752 int first = 0;
9753 struct listnode *node, *nnode;
9754 struct peer *peer;
9755 int addpath_capable;
9756 int has_adj;
9757 unsigned int first_as;
1defdda8 9758 bool nexthop_self =
9b6d8fcf 9759 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9760 int i;
2ba93fd6
DA
9761 char *nexthop_hostname =
9762 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9763
9764 if (json_paths) {
9765 json_path = json_object_new_object();
9766 json_peer = json_object_new_object();
9767 json_nexthop_global = json_object_new_object();
9768 }
9769
8304dabf
AD
9770 if (safi == SAFI_EVPN) {
9771 if (!json_paths)
9772 vty_out(vty, " Route %pRN", bn);
9773 }
9774
44c69747 9775 if (path->extra) {
b57ba6d2 9776 char tag_buf[30];
d62a17ae 9777
d62a17ae 9778 tag_buf[0] = '\0';
9b6d8fcf
DS
9779 if (path->extra && path->extra->num_labels) {
9780 bgp_evpn_label2str(path->extra->label,
9781 path->extra->num_labels, tag_buf,
a4d82a8a 9782 sizeof(tag_buf));
d62a17ae 9783 }
d7325ee7 9784 if (safi == SAFI_EVPN) {
44c69747 9785 if (!json_paths) {
44c69747
LK
9786 if (tag_buf[0] != '\0')
9787 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9788 } else {
9789 if (tag_buf[0])
9790 json_object_string_add(json_path, "VNI",
9791 tag_buf);
9792 }
d7325ee7
DD
9793 }
9794
44c69747 9795 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9796 struct bgp_path_info *parent_ri;
9bcb3eef 9797 struct bgp_dest *dest, *pdest;
d62a17ae 9798
9b6d8fcf 9799 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9800 dest = parent_ri->net;
9801 if (dest && dest->pdest) {
9802 pdest = dest->pdest;
9803 prefix_rd2str(
9804 (struct prefix_rd *)bgp_dest_get_prefix(
9805 pdest),
9806 buf1, sizeof(buf1));
d7325ee7 9807 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9808 vty_out(vty,
58bff4d1 9809 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9810 buf1,
9811 (struct prefix_evpn *)
9812 bgp_dest_get_prefix(
9813 dest),
9814 tag_buf);
58bff4d1
AK
9815 if (attr->es_flags & ATTR_ES_L3_NHG)
9816 vty_out(vty, ", L3NHG %s",
9817 (attr->es_flags
9818 & ATTR_ES_L3_NHG_ACTIVE)
9819 ? "active"
9820 : "inactive");
9821 vty_out(vty, "\n");
9822
d7325ee7 9823 } else
2dbe669b
DA
9824 vty_out(vty,
9825 " Imported from %s:%pFX\n",
9826 buf1,
9827 (struct prefix_evpn *)
9828 bgp_dest_get_prefix(
9829 dest));
d62a17ae 9830 }
9831 }
9832 }
d62a17ae 9833
8304dabf
AD
9834 if (safi == SAFI_EVPN
9835 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9836 char gwip_buf[INET6_ADDRSTRLEN];
9837
9838 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
9839 inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
9840 gwip_buf, sizeof(gwip_buf));
9841 else
9842 inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
9843 gwip_buf, sizeof(gwip_buf));
9844
9845 if (json_paths)
9846 json_object_string_add(json_path, "gatewayIP",
9847 gwip_buf);
9848 else
9849 vty_out(vty, " Gateway IP %s", gwip_buf);
9850 }
9851
9852 if (safi == SAFI_EVPN)
9853 vty_out(vty, "\n");
9854
05864da7
DS
9855 /* Line1 display AS-path, Aggregator */
9856 if (attr->aspath) {
9857 if (json_paths) {
9858 if (!attr->aspath->json)
9859 aspath_str_update(attr->aspath, true);
9860 json_object_lock(attr->aspath->json);
9861 json_object_object_add(json_path, "aspath",
9862 attr->aspath->json);
9863 } else {
9864 if (attr->aspath->segments)
9865 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9866 else
05864da7 9867 vty_out(vty, " Local");
d62a17ae 9868 }
05864da7 9869 }
d62a17ae 9870
05864da7
DS
9871 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9872 if (json_paths)
9873 json_object_boolean_true_add(json_path, "removed");
9874 else
9875 vty_out(vty, ", (removed)");
9876 }
d62a17ae 9877
05864da7
DS
9878 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9879 if (json_paths)
9880 json_object_boolean_true_add(json_path, "stale");
9881 else
9882 vty_out(vty, ", (stale)");
9883 }
d62a17ae 9884
05864da7
DS
9885 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9886 if (json_paths) {
9887 json_object_int_add(json_path, "aggregatorAs",
9888 attr->aggregator_as);
c949c771
DA
9889 json_object_string_addf(json_path, "aggregatorId",
9890 "%pI4", &attr->aggregator_addr);
05864da7 9891 } else {
88d495a9
DA
9892 vty_out(vty, ", (aggregated by %u %pI4)",
9893 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9894 }
05864da7 9895 }
d62a17ae 9896
05864da7
DS
9897 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9898 PEER_FLAG_REFLECTOR_CLIENT)) {
9899 if (json_paths)
9900 json_object_boolean_true_add(json_path,
9901 "rxedFromRrClient");
9902 else
9903 vty_out(vty, ", (Received from a RR-client)");
9904 }
d62a17ae 9905
05864da7
DS
9906 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9907 PEER_FLAG_RSERVER_CLIENT)) {
9908 if (json_paths)
9909 json_object_boolean_true_add(json_path,
9910 "rxedFromRsClient");
9911 else
9912 vty_out(vty, ", (Received from a RS-client)");
9913 }
d62a17ae 9914
05864da7
DS
9915 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9916 if (json_paths)
9917 json_object_boolean_true_add(json_path,
9918 "dampeningHistoryEntry");
9919 else
9920 vty_out(vty, ", (history entry)");
9921 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9922 if (json_paths)
9923 json_object_boolean_true_add(json_path,
9924 "dampeningSuppressed");
9925 else
9926 vty_out(vty, ", (suppressed due to dampening)");
9927 }
d62a17ae 9928
05864da7
DS
9929 if (!json_paths)
9930 vty_out(vty, "\n");
d62a17ae 9931
05864da7
DS
9932 /* Line2 display Next-hop, Neighbor, Router-id */
9933 /* Display the nexthop */
9bcb3eef 9934 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9935
9936 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9937 || bn_p->family == AF_EVPN)
05864da7
DS
9938 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9939 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9940 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9941 || safi == SAFI_EVPN) {
515c2602 9942 if (json_paths) {
c949c771
DA
9943 json_object_string_addf(
9944 json_nexthop_global, "ip", "%pI4",
9945 &attr->mp_nexthop_global_in);
515c2602 9946
939a97f4 9947 if (path->peer->hostname)
515c2602
DA
9948 json_object_string_add(
9949 json_nexthop_global, "hostname",
939a97f4 9950 path->peer->hostname);
aef999a2
DA
9951 } else {
9952 if (nexthop_hostname)
9953 vty_out(vty, " %pI4(%s)",
9954 &attr->mp_nexthop_global_in,
9955 nexthop_hostname);
9956 else
9957 vty_out(vty, " %pI4",
9958 &attr->mp_nexthop_global_in);
9959 }
d62a17ae 9960 } else {
515c2602 9961 if (json_paths) {
c949c771
DA
9962 json_object_string_addf(json_nexthop_global,
9963 "ip", "%pI4",
9964 &attr->nexthop);
515c2602 9965
939a97f4 9966 if (path->peer->hostname)
515c2602
DA
9967 json_object_string_add(
9968 json_nexthop_global, "hostname",
939a97f4 9969 path->peer->hostname);
aef999a2
DA
9970 } else {
9971 if (nexthop_hostname)
9972 vty_out(vty, " %pI4(%s)",
9973 &attr->nexthop,
9974 nexthop_hostname);
9975 else
9976 vty_out(vty, " %pI4",
9977 &attr->nexthop);
9978 }
d62a17ae 9979 }
9980
05864da7
DS
9981 if (json_paths)
9982 json_object_string_add(json_nexthop_global, "afi",
9983 "ipv4");
9984 } else {
9985 if (json_paths) {
c949c771
DA
9986 json_object_string_addf(json_nexthop_global, "ip",
9987 "%pI6",
9988 &attr->mp_nexthop_global);
515c2602 9989
939a97f4 9990 if (path->peer->hostname)
515c2602
DA
9991 json_object_string_add(json_nexthop_global,
9992 "hostname",
939a97f4 9993 path->peer->hostname);
515c2602 9994
05864da7
DS
9995 json_object_string_add(json_nexthop_global, "afi",
9996 "ipv6");
9997 json_object_string_add(json_nexthop_global, "scope",
9998 "global");
9999 } else {
aef999a2
DA
10000 if (nexthop_hostname)
10001 vty_out(vty, " %pI6(%s)",
10002 &attr->mp_nexthop_global,
10003 nexthop_hostname);
10004 else
10005 vty_out(vty, " %pI6",
10006 &attr->mp_nexthop_global);
d62a17ae 10007 }
05864da7 10008 }
d62a17ae 10009
05864da7
DS
10010 /* Display the IGP cost or 'inaccessible' */
10011 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10012 if (json_paths)
10013 json_object_boolean_false_add(json_nexthop_global,
10014 "accessible");
10015 else
10016 vty_out(vty, " (inaccessible)");
10017 } else {
10018 if (path->extra && path->extra->igpmetric) {
d62a17ae 10019 if (json_paths)
05864da7
DS
10020 json_object_int_add(json_nexthop_global,
10021 "metric",
10022 path->extra->igpmetric);
d62a17ae 10023 else
05864da7
DS
10024 vty_out(vty, " (metric %u)",
10025 path->extra->igpmetric);
d62a17ae 10026 }
10027
05864da7 10028 /* IGP cost is 0, display this only for json */
d62a17ae 10029 else {
d62a17ae 10030 if (json_paths)
05864da7
DS
10031 json_object_int_add(json_nexthop_global,
10032 "metric", 0);
d62a17ae 10033 }
d62a17ae 10034
05864da7
DS
10035 if (json_paths)
10036 json_object_boolean_true_add(json_nexthop_global,
10037 "accessible");
10038 }
d62a17ae 10039
05864da7
DS
10040 /* Display peer "from" output */
10041 /* This path was originated locally */
10042 if (path->peer == bgp->peer_self) {
d62a17ae 10043
05864da7 10044 if (safi == SAFI_EVPN
b54892e0 10045 || (bn_p->family == AF_INET
05864da7 10046 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10047 if (json_paths)
05864da7
DS
10048 json_object_string_add(json_peer, "peerId",
10049 "0.0.0.0");
d62a17ae 10050 else
05864da7
DS
10051 vty_out(vty, " from 0.0.0.0 ");
10052 } else {
d62a17ae 10053 if (json_paths)
05864da7
DS
10054 json_object_string_add(json_peer, "peerId",
10055 "::");
d62a17ae 10056 else
05864da7 10057 vty_out(vty, " from :: ");
d62a17ae 10058 }
d62a17ae 10059
4e9a9863 10060 if (json_paths)
c949c771
DA
10061 json_object_string_addf(json_peer, "routerId", "%pI4",
10062 &bgp->router_id);
4e9a9863 10063 else
23d0a753 10064 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10065 }
d62a17ae 10066
05864da7
DS
10067 /* We RXed this path from one of our peers */
10068 else {
10069
10070 if (json_paths) {
10071 json_object_string_add(json_peer, "peerId",
10072 sockunion2str(&path->peer->su,
10073 buf,
10074 SU_ADDRSTRLEN));
c949c771
DA
10075 json_object_string_addf(json_peer, "routerId", "%pI4",
10076 &path->peer->remote_id);
05864da7
DS
10077
10078 if (path->peer->hostname)
10079 json_object_string_add(json_peer, "hostname",
10080 path->peer->hostname);
10081
10082 if (path->peer->domainname)
10083 json_object_string_add(json_peer, "domainname",
10084 path->peer->domainname);
10085
10086 if (path->peer->conf_if)
10087 json_object_string_add(json_peer, "interface",
10088 path->peer->conf_if);
10089 } else {
10090 if (path->peer->conf_if) {
10091 if (path->peer->hostname
892fedb6
DA
10092 && CHECK_FLAG(path->peer->bgp->flags,
10093 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10094 vty_out(vty, " from %s(%s)",
10095 path->peer->hostname,
10096 path->peer->conf_if);
d62a17ae 10097 else
05864da7 10098 vty_out(vty, " from %s",
9b6d8fcf 10099 path->peer->conf_if);
d62a17ae 10100 } else {
05864da7 10101 if (path->peer->hostname
892fedb6
DA
10102 && CHECK_FLAG(path->peer->bgp->flags,
10103 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10104 vty_out(vty, " from %s(%s)",
10105 path->peer->hostname,
10106 path->peer->host);
d62a17ae 10107 else
05864da7
DS
10108 vty_out(vty, " from %s",
10109 sockunion2str(&path->peer->su,
10110 buf,
10111 SU_ADDRSTRLEN));
d62a17ae 10112 }
d62a17ae 10113
05864da7 10114 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10115 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10116 else
10117 vty_out(vty, " (%s)",
10118 inet_ntop(AF_INET,
10119 &path->peer->remote_id, buf1,
10120 sizeof(buf1)));
d62a17ae 10121 }
05864da7 10122 }
9df8b37c 10123
05864da7
DS
10124 /*
10125 * Note when vrfid of nexthop is different from that of prefix
10126 */
10127 if (path->extra && path->extra->bgp_orig) {
10128 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10129
05864da7
DS
10130 if (json_paths) {
10131 const char *vn;
9df8b37c 10132
05864da7
DS
10133 if (path->extra->bgp_orig->inst_type
10134 == BGP_INSTANCE_TYPE_DEFAULT)
10135 vn = VRF_DEFAULT_NAME;
10136 else
10137 vn = path->extra->bgp_orig->name;
9df8b37c 10138
05864da7 10139 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10140
05864da7
DS
10141 if (nexthop_vrfid == VRF_UNKNOWN) {
10142 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10143 } else {
05864da7
DS
10144 json_object_int_add(json_path, "nhVrfId",
10145 (int)nexthop_vrfid);
9df8b37c 10146 }
05864da7
DS
10147 } else {
10148 if (nexthop_vrfid == VRF_UNKNOWN)
10149 vty_out(vty, " vrf ?");
137147c6
DS
10150 else {
10151 struct vrf *vrf;
10152
10153 vrf = vrf_lookup_by_id(nexthop_vrfid);
10154 vty_out(vty, " vrf %s(%u)",
10155 VRF_LOGNAME(vrf), nexthop_vrfid);
10156 }
9df8b37c 10157 }
05864da7 10158 }
9df8b37c 10159
05864da7
DS
10160 if (nexthop_self) {
10161 if (json_paths) {
10162 json_object_boolean_true_add(json_path,
10163 "announceNexthopSelf");
10164 } else {
10165 vty_out(vty, " announce-nh-self");
9df8b37c 10166 }
05864da7 10167 }
9df8b37c 10168
05864da7
DS
10169 if (!json_paths)
10170 vty_out(vty, "\n");
d62a17ae 10171
05864da7
DS
10172 /* display the link-local nexthop */
10173 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10174 if (json_paths) {
10175 json_nexthop_ll = json_object_new_object();
c949c771
DA
10176 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10177 &attr->mp_nexthop_local);
515c2602 10178
939a97f4 10179 if (path->peer->hostname)
515c2602
DA
10180 json_object_string_add(json_nexthop_ll,
10181 "hostname",
939a97f4 10182 path->peer->hostname);
515c2602 10183
05864da7
DS
10184 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10185 json_object_string_add(json_nexthop_ll, "scope",
10186 "link-local");
d62a17ae 10187
05864da7
DS
10188 json_object_boolean_true_add(json_nexthop_ll,
10189 "accessible");
d62a17ae 10190
05864da7 10191 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10192 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10193 "used");
10194 else
10195 json_object_boolean_true_add(
10196 json_nexthop_global, "used");
10197 } else {
10198 vty_out(vty, " (%s) %s\n",
10199 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10200 buf, INET6_ADDRSTRLEN),
10201 attr->mp_nexthop_prefer_global
10202 ? "(prefer-global)"
10203 : "(used)");
d62a17ae 10204 }
05864da7
DS
10205 }
10206 /* If we do not have a link-local nexthop then we must flag the
10207 global as "used" */
10208 else {
10209 if (json_paths)
10210 json_object_boolean_true_add(json_nexthop_global,
10211 "used");
10212 }
d62a17ae 10213
b5e140c8 10214 if (safi == SAFI_EVPN &&
5e4d4c8a 10215 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10216 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10217 }
10218
05864da7
DS
10219 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10220 * Int/Ext/Local, Atomic, best */
10221 if (json_paths)
10222 json_object_string_add(json_path, "origin",
10223 bgp_origin_long_str[attr->origin]);
10224 else
10225 vty_out(vty, " Origin %s",
10226 bgp_origin_long_str[attr->origin]);
9df8b37c 10227
05864da7 10228 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10229 if (json_paths)
05864da7 10230 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10231 else
05864da7
DS
10232 vty_out(vty, ", metric %u", attr->med);
10233 }
9df8b37c 10234
05864da7
DS
10235 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10236 if (json_paths)
0fbac0b4 10237 json_object_int_add(json_path, "locPrf",
05864da7
DS
10238 attr->local_pref);
10239 else
10240 vty_out(vty, ", localpref %u", attr->local_pref);
10241 }
9df8b37c 10242
05864da7
DS
10243 if (attr->weight != 0) {
10244 if (json_paths)
10245 json_object_int_add(json_path, "weight", attr->weight);
10246 else
10247 vty_out(vty, ", weight %u", attr->weight);
10248 }
9df8b37c 10249
05864da7
DS
10250 if (attr->tag != 0) {
10251 if (json_paths)
10252 json_object_int_add(json_path, "tag", attr->tag);
10253 else
10254 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10255 }
9df8b37c 10256
05864da7
DS
10257 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10258 if (json_paths)
10259 json_object_boolean_false_add(json_path, "valid");
10260 else
10261 vty_out(vty, ", invalid");
10262 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10263 if (json_paths)
10264 json_object_boolean_true_add(json_path, "valid");
10265 else
10266 vty_out(vty, ", valid");
10267 }
9df8b37c 10268
7d3cae70
DA
10269 if (json_paths)
10270 json_object_int_add(json_path, "version", bn->version);
10271
05864da7
DS
10272 if (path->peer != bgp->peer_self) {
10273 if (path->peer->as == path->peer->local_as) {
10274 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10275 if (json_paths)
10276 json_object_string_add(
10277 json_peer, "type",
10278 "confed-internal");
d62a17ae 10279 else
05864da7 10280 vty_out(vty, ", confed-internal");
d62a17ae 10281 } else {
05864da7
DS
10282 if (json_paths)
10283 json_object_string_add(
10284 json_peer, "type", "internal");
10285 else
10286 vty_out(vty, ", internal");
9df8b37c 10287 }
05864da7
DS
10288 } else {
10289 if (bgp_confederation_peers_check(bgp,
10290 path->peer->as)) {
10291 if (json_paths)
10292 json_object_string_add(
10293 json_peer, "type",
10294 "confed-external");
d62a17ae 10295 else
05864da7 10296 vty_out(vty, ", confed-external");
d62a17ae 10297 } else {
05864da7
DS
10298 if (json_paths)
10299 json_object_string_add(
10300 json_peer, "type", "external");
10301 else
10302 vty_out(vty, ", external");
d62a17ae 10303 }
10304 }
05864da7
DS
10305 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10306 if (json_paths) {
10307 json_object_boolean_true_add(json_path, "aggregated");
10308 json_object_boolean_true_add(json_path, "local");
10309 } else {
10310 vty_out(vty, ", aggregated, local");
10311 }
10312 } else if (path->type != ZEBRA_ROUTE_BGP) {
10313 if (json_paths)
10314 json_object_boolean_true_add(json_path, "sourced");
10315 else
10316 vty_out(vty, ", sourced");
10317 } else {
10318 if (json_paths) {
10319 json_object_boolean_true_add(json_path, "sourced");
10320 json_object_boolean_true_add(json_path, "local");
10321 } else {
10322 vty_out(vty, ", sourced, local");
d62a17ae 10323 }
05864da7 10324 }
718e3744 10325
05864da7 10326 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10327 if (json_paths)
05864da7
DS
10328 json_object_boolean_true_add(json_path,
10329 "atomicAggregate");
d62a17ae 10330 else
05864da7
DS
10331 vty_out(vty, ", atomic-aggregate");
10332 }
d62a17ae 10333
05864da7
DS
10334 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10335 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10336 && bgp_path_info_mpath_count(path))) {
10337 if (json_paths)
10338 json_object_boolean_true_add(json_path, "multipath");
10339 else
10340 vty_out(vty, ", multipath");
10341 }
50e05855 10342
05864da7
DS
10343 // Mark the bestpath(s)
10344 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10345 first_as = aspath_get_first_as(attr->aspath);
718e3744 10346
05864da7
DS
10347 if (json_paths) {
10348 if (!json_bestpath)
10349 json_bestpath = json_object_new_object();
10350 json_object_int_add(json_bestpath, "bestpathFromAs",
10351 first_as);
10352 } else {
10353 if (first_as)
10354 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10355 else
05864da7 10356 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10357 }
05864da7 10358 }
718e3744 10359
05864da7
DS
10360 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10361 if (json_paths) {
10362 if (!json_bestpath)
10363 json_bestpath = json_object_new_object();
10364 json_object_boolean_true_add(json_bestpath, "overall");
10365 json_object_string_add(
10366 json_bestpath, "selectionReason",
10367 bgp_path_selection_reason2str(bn->reason));
10368 } else {
10369 vty_out(vty, ", best");
10370 vty_out(vty, " (%s)",
10371 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10372 }
05864da7 10373 }
718e3744 10374
4027d19b 10375 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10376 if (json_paths)
10377 json_object_string_add(
10378 json_path, "rpkiValidationState",
4027d19b 10379 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10380 else
1d327209 10381 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10382 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10383 }
10384
05864da7
DS
10385 if (json_bestpath)
10386 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10387
05864da7
DS
10388 if (!json_paths)
10389 vty_out(vty, "\n");
10390
10391 /* Line 4 display Community */
29e72930 10392 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10393 if (json_paths) {
10394 if (!attr->community->json)
10395 community_str(attr->community, true);
10396 json_object_lock(attr->community->json);
10397 json_object_object_add(json_path, "community",
10398 attr->community->json);
10399 } else {
10400 vty_out(vty, " Community: %s\n",
10401 attr->community->str);
d62a17ae 10402 }
05864da7 10403 }
718e3744 10404
05864da7
DS
10405 /* Line 5 display Extended-community */
10406 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10407 if (json_paths) {
10408 json_ext_community = json_object_new_object();
10409 json_object_string_add(json_ext_community, "string",
10410 attr->ecommunity->str);
10411 json_object_object_add(json_path, "extendedCommunity",
10412 json_ext_community);
d62a17ae 10413 } else {
05864da7
DS
10414 vty_out(vty, " Extended Community: %s\n",
10415 attr->ecommunity->str);
d62a17ae 10416 }
05864da7 10417 }
718e3744 10418
05864da7
DS
10419 /* Line 6 display Large community */
10420 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10421 if (json_paths) {
10422 if (!attr->lcommunity->json)
10423 lcommunity_str(attr->lcommunity, true);
10424 json_object_lock(attr->lcommunity->json);
10425 json_object_object_add(json_path, "largeCommunity",
10426 attr->lcommunity->json);
10427 } else {
10428 vty_out(vty, " Large Community: %s\n",
10429 attr->lcommunity->str);
d62a17ae 10430 }
05864da7 10431 }
718e3744 10432
05864da7
DS
10433 /* Line 7 display Originator, Cluster-id */
10434 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10435 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10436 char buf[BUFSIZ] = {0};
10437
05864da7 10438 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10439 if (json_paths)
c949c771
DA
10440 json_object_string_addf(json_path,
10441 "originatorId", "%pI4",
10442 &attr->originator_id);
d62a17ae 10443 else
23d0a753
DA
10444 vty_out(vty, " Originator: %pI4",
10445 &attr->originator_id);
d62a17ae 10446 }
856ca177 10447
05864da7 10448 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10449 struct cluster_list *cluster =
10450 bgp_attr_get_cluster(attr);
05864da7 10451 int i;
d62a17ae 10452
10453 if (json_paths) {
05864da7
DS
10454 json_cluster_list = json_object_new_object();
10455 json_cluster_list_list =
10456 json_object_new_array();
10457
779fee93 10458 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10459 json_string = json_object_new_string(
779fee93
DS
10460 inet_ntop(AF_INET,
10461 &cluster->list[i],
10462 buf, sizeof(buf)));
05864da7
DS
10463 json_object_array_add(
10464 json_cluster_list_list,
10465 json_string);
10466 }
718e3744 10467
05864da7
DS
10468 /*
10469 * struct cluster_list does not have
10470 * "str" variable like aspath and community
10471 * do. Add this someday if someone asks
10472 * for it.
10473 * json_object_string_add(json_cluster_list,
779fee93 10474 * "string", cluster->str);
05864da7
DS
10475 */
10476 json_object_object_add(json_cluster_list,
10477 "list",
10478 json_cluster_list_list);
10479 json_object_object_add(json_path, "clusterList",
10480 json_cluster_list);
0dc8ee70 10481 } else {
05864da7
DS
10482 vty_out(vty, ", Cluster list: ");
10483
779fee93 10484 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10485 vty_out(vty, "%pI4 ",
779fee93 10486 &cluster->list[i]);
05864da7 10487 }
0dc8ee70 10488 }
d62a17ae 10489 }
718e3744 10490
d62a17ae 10491 if (!json_paths)
10492 vty_out(vty, "\n");
05864da7 10493 }
d62a17ae 10494
05864da7 10495 if (path->extra && path->extra->damp_info)
b4f7f45b 10496 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10497
05864da7
DS
10498 /* Remote Label */
10499 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10500 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10501 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10502
05864da7
DS
10503 if (json_paths)
10504 json_object_int_add(json_path, "remoteLabel", label);
10505 else
10506 vty_out(vty, " Remote label: %d\n", label);
10507 }
d62a17ae 10508
e496b420
HS
10509 /* Remote SID */
10510 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10511 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10512 if (json_paths)
10513 json_object_string_add(json_path, "remoteSid", buf);
10514 else
10515 vty_out(vty, " Remote SID: %s\n", buf);
10516 }
10517
05864da7
DS
10518 /* Label Index */
10519 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10520 if (json_paths)
10521 json_object_int_add(json_path, "labelIndex",
10522 attr->label_index);
10523 else
10524 vty_out(vty, " Label Index: %d\n",
10525 attr->label_index);
10526 }
d62a17ae 10527
05864da7
DS
10528 /* Line 8 display Addpath IDs */
10529 if (path->addpath_rx_id
10530 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10531 if (json_paths) {
10532 json_object_int_add(json_path, "addpathRxId",
10533 path->addpath_rx_id);
d62a17ae 10534
05864da7
DS
10535 /* Keep backwards compatibility with the old API
10536 * by putting TX All's ID in the old field
10537 */
10538 json_object_int_add(
10539 json_path, "addpathTxId",
10540 path->tx_addpath
10541 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10542
05864da7
DS
10543 /* ... but create a specific field for each
10544 * strategy
10545 */
10546 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10547 json_object_int_add(
10548 json_path,
10549 bgp_addpath_names(i)->id_json_name,
10550 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10551 }
05864da7
DS
10552 } else {
10553 vty_out(vty, " AddPath ID: RX %u, ",
10554 path->addpath_rx_id);
d62a17ae 10555
05864da7 10556 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10557 }
05864da7 10558 }
520d5d76 10559
05864da7
DS
10560 /* If we used addpath to TX a non-bestpath we need to display
10561 * "Advertised to" on a path-by-path basis
10562 */
10563 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10564 first = 1;
dcc68b5e 10565
05864da7
DS
10566 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10567 addpath_capable =
10568 bgp_addpath_encode_tx(peer, afi, safi);
10569 has_adj = bgp_adj_out_lookup(
10570 peer, path->net,
10571 bgp_addpath_id_for_peer(peer, afi, safi,
10572 &path->tx_addpath));
10573
10574 if ((addpath_capable && has_adj)
10575 || (!addpath_capable && has_adj
10576 && CHECK_FLAG(path->flags,
10577 BGP_PATH_SELECTED))) {
10578 if (json_path && !json_adv_to)
10579 json_adv_to = json_object_new_object();
dcc68b5e 10580
05864da7
DS
10581 route_vty_out_advertised_to(
10582 vty, peer, &first,
10583 " Advertised to:", json_adv_to);
d62a17ae 10584 }
10585 }
718e3744 10586
05864da7
DS
10587 if (json_path) {
10588 if (json_adv_to) {
10589 json_object_object_add(
10590 json_path, "advertisedTo", json_adv_to);
d62a17ae 10591 }
05864da7
DS
10592 } else {
10593 if (!first) {
10594 vty_out(vty, "\n");
d62a17ae 10595 }
10596 }
05864da7 10597 }
b05a1c8b 10598
05864da7
DS
10599 /* Line 9 display Uptime */
10600 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10601 if (json_paths) {
10602 json_last_update = json_object_new_object();
10603 json_object_int_add(json_last_update, "epoch", tbuf);
10604 json_object_string_add(json_last_update, "string",
10605 ctime(&tbuf));
10606 json_object_object_add(json_path, "lastUpdate",
10607 json_last_update);
10608 } else
10609 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10610
05864da7
DS
10611 /* Line 10 display PMSI tunnel attribute, if present */
10612 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10613 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10614 bgp_attr_get_pmsi_tnl_type(attr),
10615 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10616
05864da7
DS
10617 if (json_paths) {
10618 json_pmsi = json_object_new_object();
10619 json_object_string_add(json_pmsi, "tunnelType", str);
10620 json_object_int_add(json_pmsi, "label",
10621 label2vni(&attr->label));
10622 json_object_object_add(json_path, "pmsi", json_pmsi);
10623 } else
10624 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10625 str, label2vni(&attr->label));
d62a17ae 10626 }
f1aa5d8a 10627
92269aa2
DS
10628 /* Output some debug about internal state of the dest flags */
10629 if (json_paths) {
10630 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10631 json_object_boolean_true_add(json_path, "processScheduled");
10632 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10633 json_object_boolean_true_add(json_path, "userCleared");
10634 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10635 json_object_boolean_true_add(json_path, "labelChanged");
10636 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10637 json_object_boolean_true_add(json_path, "registeredForLabel");
10638 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10639 json_object_boolean_true_add(json_path, "selectDefered");
10640 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10641 json_object_boolean_true_add(json_path, "fibInstalled");
10642 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10643 json_object_boolean_true_add(json_path, "fibPending");
10644 }
10645
d62a17ae 10646 /* We've constructed the json object for this path, add it to the json
10647 * array of paths
10648 */
10649 if (json_paths) {
10650 if (json_nexthop_global || json_nexthop_ll) {
10651 json_nexthops = json_object_new_array();
f1aa5d8a 10652
d62a17ae 10653 if (json_nexthop_global)
10654 json_object_array_add(json_nexthops,
10655 json_nexthop_global);
f1aa5d8a 10656
d62a17ae 10657 if (json_nexthop_ll)
10658 json_object_array_add(json_nexthops,
10659 json_nexthop_ll);
f1aa5d8a 10660
d62a17ae 10661 json_object_object_add(json_path, "nexthops",
10662 json_nexthops);
10663 }
10664
10665 json_object_object_add(json_path, "peer", json_peer);
10666 json_object_array_add(json_paths, json_path);
05864da7 10667 }
b366b518
BB
10668}
10669
96ade3ed 10670#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10671#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10672#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10673
a4d82a8a 10674static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10675 afi_t afi, safi_t safi, enum bgp_show_type type,
10676 bool use_json);
7f323236
DW
10677static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10678 const char *comstr, int exact, afi_t afi,
96c81f66 10679 safi_t safi, uint16_t show_flags);
d62a17ae 10680
1ae44dfc 10681static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10682 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10683 void *output_arg, const char *rd, int is_last,
96f3485c 10684 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10685 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10686 enum rpki_states rpki_target_state)
d62a17ae 10687{
40381db7 10688 struct bgp_path_info *pi;
9bcb3eef 10689 struct bgp_dest *dest;
2aad8c42
MS
10690 bool header = true;
10691 bool json_detail_header = false;
d62a17ae 10692 int display;
1ae44dfc
LB
10693 unsigned long output_count = 0;
10694 unsigned long total_count = 0;
d62a17ae 10695 struct prefix *p;
d62a17ae 10696 json_object *json_paths = NULL;
10697 int first = 1;
96f3485c
MK
10698 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10699 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10700 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10701
1ae44dfc 10702 if (output_cum && *output_cum != 0)
2aad8c42 10703 header = false;
1ae44dfc 10704
9386b588 10705 if (use_json && !*json_header_depth) {
96f3485c
MK
10706 if (all)
10707 *json_header_depth = 1;
10708 else {
10709 vty_out(vty, "{\n");
10710 *json_header_depth = 2;
10711 }
10712
d62a17ae 10713 vty_out(vty,
23d0a753
DA
10714 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10715 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10716 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10717 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10718 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10719 ? VRF_DEFAULT_NAME
10720 : bgp->name,
10721 table->version, &bgp->router_id,
01eced22 10722 bgp->default_local_pref, bgp->as);
9386b588 10723 if (rd) {
445c2480 10724 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10725 ++*json_header_depth;
10726 }
d62a17ae 10727 }
718e3744 10728
445c2480
DS
10729 if (use_json && rd) {
10730 vty_out(vty, " \"%s\" : { ", rd);
10731 }
10732
2aad8c42
MS
10733 /* Check for 'json detail', where we need header output once per dest */
10734 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10735 type != bgp_show_type_dampend_paths &&
10736 type != bgp_show_type_damp_neighbor &&
10737 type != bgp_show_type_flap_statistics &&
10738 type != bgp_show_type_flap_neighbor)
10739 json_detail_header = true;
10740
d62a17ae 10741 /* Start processing of routes. */
9bcb3eef
DS
10742 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10743 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10744 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10745 bool json_detail = json_detail_header;
b54892e0 10746
9bcb3eef 10747 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10748 if (pi == NULL)
98ce9a06 10749 continue;
d62a17ae 10750
98ce9a06 10751 display = 0;
98ce9a06
DS
10752 if (use_json)
10753 json_paths = json_object_new_array();
10754 else
10755 json_paths = NULL;
d62a17ae 10756
6f94b685 10757 for (; pi; pi = pi->next) {
98ce9a06 10758 total_count++;
1e2ce4f1 10759
7d3cae70
DA
10760 if (type == bgp_show_type_prefix_version) {
10761 uint32_t version =
10762 strtoul(output_arg, NULL, 10);
10763 if (dest->version < version)
10764 continue;
10765 }
10766
a70a28a5
DA
10767 if (type == bgp_show_type_community_alias) {
10768 char *alias = output_arg;
10769 char **communities;
10770 int num;
10771 bool found = false;
10772
10773 if (pi->attr->community) {
10774 frrstr_split(pi->attr->community->str,
10775 " ", &communities, &num);
10776 for (int i = 0; i < num; i++) {
10777 const char *com2alias =
10778 bgp_community2alias(
10779 communities[i]);
cd9cc0e6
IR
10780 if (!found
10781 && strcmp(alias, com2alias)
10782 == 0)
a70a28a5 10783 found = true;
cd9cc0e6
IR
10784 XFREE(MTYPE_TMP,
10785 communities[i]);
a70a28a5 10786 }
cd9cc0e6 10787 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10788 }
10789
10790 if (!found && pi->attr->lcommunity) {
10791 frrstr_split(pi->attr->lcommunity->str,
10792 " ", &communities, &num);
10793 for (int i = 0; i < num; i++) {
10794 const char *com2alias =
10795 bgp_community2alias(
10796 communities[i]);
cd9cc0e6
IR
10797 if (!found
10798 && strcmp(alias, com2alias)
10799 == 0)
a70a28a5 10800 found = true;
cd9cc0e6
IR
10801 XFREE(MTYPE_TMP,
10802 communities[i]);
a70a28a5 10803 }
cd9cc0e6 10804 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10805 }
10806
10807 if (!found)
10808 continue;
10809 }
10810
1e2ce4f1
DS
10811 if (type == bgp_show_type_rpki) {
10812 if (dest_p->family == AF_INET
10813 || dest_p->family == AF_INET6)
4027d19b 10814 rpki_curr_state = hook_call(
1e2ce4f1
DS
10815 bgp_rpki_prefix_status,
10816 pi->peer, pi->attr, dest_p);
4027d19b
DS
10817 if (rpki_target_state != RPKI_NOT_BEING_USED
10818 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10819 continue;
10820 }
10821
98ce9a06
DS
10822 if (type == bgp_show_type_flap_statistics
10823 || type == bgp_show_type_flap_neighbor
10824 || type == bgp_show_type_dampend_paths
10825 || type == bgp_show_type_damp_neighbor) {
40381db7 10826 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10827 continue;
10828 }
10829 if (type == bgp_show_type_regexp) {
10830 regex_t *regex = output_arg;
d62a17ae 10831
40381db7 10832 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10833 == REG_NOMATCH)
10834 continue;
10835 }
10836 if (type == bgp_show_type_prefix_list) {
10837 struct prefix_list *plist = output_arg;
d62a17ae 10838
9bcb3eef 10839 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10840 != PREFIX_PERMIT)
10841 continue;
10842 }
10843 if (type == bgp_show_type_filter_list) {
10844 struct as_list *as_list = output_arg;
d62a17ae 10845
40381db7 10846 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10847 != AS_FILTER_PERMIT)
10848 continue;
10849 }
10850 if (type == bgp_show_type_route_map) {
10851 struct route_map *rmap = output_arg;
9b6d8fcf 10852 struct bgp_path_info path;
98ce9a06 10853 struct attr dummy_attr;
b68885f9 10854 route_map_result_t ret;
d62a17ae 10855
6f4f49b2 10856 dummy_attr = *pi->attr;
d62a17ae 10857
40381db7 10858 path.peer = pi->peer;
9b6d8fcf 10859 path.attr = &dummy_attr;
d62a17ae 10860
1782514f 10861 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 10862 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
10863 if (ret == RMAP_DENYMATCH)
10864 continue;
10865 }
10866 if (type == bgp_show_type_neighbor
10867 || type == bgp_show_type_flap_neighbor
10868 || type == bgp_show_type_damp_neighbor) {
10869 union sockunion *su = output_arg;
10870
40381db7
DS
10871 if (pi->peer == NULL
10872 || pi->peer->su_remote == NULL
10873 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10874 continue;
10875 }
10876 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10877 uint32_t destination;
d62a17ae 10878
9bcb3eef 10879 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10880 if (IN_CLASSC(destination)
9bcb3eef 10881 && dest_p->prefixlen == 24)
98ce9a06
DS
10882 continue;
10883 if (IN_CLASSB(destination)
9bcb3eef 10884 && dest_p->prefixlen == 16)
98ce9a06
DS
10885 continue;
10886 if (IN_CLASSA(destination)
9bcb3eef 10887 && dest_p->prefixlen == 8)
98ce9a06
DS
10888 continue;
10889 }
10890 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10891 p = output_arg;
9bcb3eef 10892 if (!prefix_match(p, dest_p))
98ce9a06
DS
10893 continue;
10894 }
10895 if (type == bgp_show_type_community_all) {
40381db7 10896 if (!pi->attr->community)
98ce9a06
DS
10897 continue;
10898 }
10899 if (type == bgp_show_type_community) {
10900 struct community *com = output_arg;
d62a17ae 10901
40381db7
DS
10902 if (!pi->attr->community
10903 || !community_match(pi->attr->community,
98ce9a06
DS
10904 com))
10905 continue;
10906 }
10907 if (type == bgp_show_type_community_exact) {
10908 struct community *com = output_arg;
d62a17ae 10909
40381db7
DS
10910 if (!pi->attr->community
10911 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10912 continue;
10913 }
10914 if (type == bgp_show_type_community_list) {
10915 struct community_list *list = output_arg;
d62a17ae 10916
40381db7 10917 if (!community_list_match(pi->attr->community,
a4d82a8a 10918 list))
98ce9a06
DS
10919 continue;
10920 }
a4d82a8a 10921 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10922 struct community_list *list = output_arg;
d62a17ae 10923
98ce9a06 10924 if (!community_list_exact_match(
40381db7 10925 pi->attr->community, list))
98ce9a06
DS
10926 continue;
10927 }
10928 if (type == bgp_show_type_lcommunity) {
10929 struct lcommunity *lcom = output_arg;
d62a17ae 10930
40381db7
DS
10931 if (!pi->attr->lcommunity
10932 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10933 lcom))
10934 continue;
10935 }
36a206db 10936
10937 if (type == bgp_show_type_lcommunity_exact) {
10938 struct lcommunity *lcom = output_arg;
10939
10940 if (!pi->attr->lcommunity
10941 || !lcommunity_cmp(pi->attr->lcommunity,
10942 lcom))
10943 continue;
10944 }
98ce9a06
DS
10945 if (type == bgp_show_type_lcommunity_list) {
10946 struct community_list *list = output_arg;
d62a17ae 10947
40381db7 10948 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10949 list))
98ce9a06
DS
10950 continue;
10951 }
36a206db 10952 if (type
10953 == bgp_show_type_lcommunity_list_exact) {
10954 struct community_list *list = output_arg;
10955
10956 if (!lcommunity_list_exact_match(
10957 pi->attr->lcommunity, list))
10958 continue;
10959 }
98ce9a06 10960 if (type == bgp_show_type_lcommunity_all) {
40381db7 10961 if (!pi->attr->lcommunity)
98ce9a06
DS
10962 continue;
10963 }
10964 if (type == bgp_show_type_dampend_paths
10965 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10966 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10967 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10968 continue;
10969 }
10970
10971 if (!use_json && header) {
23d0a753
DA
10972 vty_out(vty,
10973 "BGP table version is %" PRIu64
10974 ", local router ID is %pI4, vrf id ",
10975 table->version, &bgp->router_id);
9df8b37c
PZ
10976 if (bgp->vrf_id == VRF_UNKNOWN)
10977 vty_out(vty, "%s", VRFID_NONE_STR);
10978 else
10979 vty_out(vty, "%u", bgp->vrf_id);
10980 vty_out(vty, "\n");
01eced22
AD
10981 vty_out(vty, "Default local pref %u, ",
10982 bgp->default_local_pref);
10983 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10984 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10985 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10986 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 10987 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 10988 if (type == bgp_show_type_dampend_paths
10989 || type == bgp_show_type_damp_neighbor)
98ce9a06 10990 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10991 else if (type == bgp_show_type_flap_statistics
10992 || type == bgp_show_type_flap_neighbor)
98ce9a06 10993 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10994 else
ae248832
MK
10995 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10996 : BGP_SHOW_HEADER));
2aad8c42
MS
10997 header = false;
10998
10999 } else if (json_detail && json_paths != NULL) {
11000 const struct prefix_rd *prd;
11001 json_object *jtemp;
11002
11003 /* Use common detail header, for most types;
11004 * need a json 'object'.
11005 */
11006
11007 jtemp = json_object_new_object();
11008 prd = bgp_rd_from_dest(dest, safi);
11009
11010 route_vty_out_detail_header(
11011 vty, bgp, dest, prd, table->afi,
11012 safi, jtemp);
11013
11014 json_object_array_add(json_paths, jtemp);
11015
11016 json_detail = false;
d62a17ae 11017 }
2aad8c42 11018
98ce9a06
DS
11019 if (rd != NULL && !display && !output_count) {
11020 if (!use_json)
11021 vty_out(vty,
11022 "Route Distinguisher: %s\n",
11023 rd);
d62a17ae 11024 }
98ce9a06
DS
11025 if (type == bgp_show_type_dampend_paths
11026 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11027 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11028 AFI_IP, safi, use_json,
11029 json_paths);
98ce9a06
DS
11030 else if (type == bgp_show_type_flap_statistics
11031 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11032 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11033 AFI_IP, safi, use_json,
11034 json_paths);
f280c93b
DA
11035 else {
11036 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11037 route_vty_out_detail(
11038 vty, bgp, dest, pi,
11039 family2afi(dest_p->family),
11040 safi, RPKI_NOT_BEING_USED,
11041 json_paths);
11042 else
11043 route_vty_out(vty, dest_p, pi, display,
11044 safi, json_paths, wide);
11045 }
98ce9a06 11046 display++;
d62a17ae 11047 }
11048
98ce9a06
DS
11049 if (display) {
11050 output_count++;
11051 if (!use_json)
11052 continue;
11053
625d2931 11054 /* encode prefix */
9bcb3eef 11055 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11056 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11057
1840384b 11058
b54892e0
DS
11059 bgp_fs_nlri_get_string(
11060 (unsigned char *)
9bcb3eef
DS
11061 dest_p->u.prefix_flowspec.ptr,
11062 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11063 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11064 family2afi(dest_p->u
11065 .prefix_flowspec.family));
625d2931 11066 if (first)
b54892e0 11067 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11068 dest_p->u.prefix_flowspec
b54892e0 11069 .prefixlen);
625d2931 11070 else
b54892e0 11071 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11072 dest_p->u.prefix_flowspec
b54892e0 11073 .prefixlen);
625d2931 11074 } else {
625d2931 11075 if (first)
1b78780b 11076 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11077 else
1b78780b 11078 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11079 }
98ce9a06 11080 vty_out(vty, "%s",
f4ec52f7
DA
11081 json_object_to_json_string_ext(
11082 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 11083 json_object_free(json_paths);
449feb8e 11084 json_paths = NULL;
98ce9a06 11085 first = 0;
1f83ed02
DS
11086 } else
11087 json_object_free(json_paths);
98ce9a06
DS
11088 }
11089
1ae44dfc
LB
11090 if (output_cum) {
11091 output_count += *output_cum;
11092 *output_cum = output_count;
11093 }
11094 if (total_cum) {
11095 total_count += *total_cum;
11096 *total_cum = total_count;
11097 }
d62a17ae 11098 if (use_json) {
9386b588 11099 if (rd) {
a4d82a8a 11100 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11101 }
11102 if (is_last) {
a4d82a8a
PZ
11103 unsigned long i;
11104 for (i = 0; i < *json_header_depth; ++i)
11105 vty_out(vty, " } ");
96f3485c
MK
11106 if (!all)
11107 vty_out(vty, "\n");
9386b588 11108 }
d62a17ae 11109 } else {
1ae44dfc
LB
11110 if (is_last) {
11111 /* No route is displayed */
11112 if (output_count == 0) {
11113 if (type == bgp_show_type_normal)
11114 vty_out(vty,
11115 "No BGP prefixes displayed, %ld exist\n",
11116 total_count);
11117 } else
d62a17ae 11118 vty_out(vty,
1ae44dfc
LB
11119 "\nDisplayed %ld routes and %ld total paths\n",
11120 output_count, total_count);
11121 }
d62a17ae 11122 }
718e3744 11123
d62a17ae 11124 return CMD_SUCCESS;
718e3744 11125}
11126
1ae44dfc
LB
11127int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11128 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11129 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11130{
9bcb3eef 11131 struct bgp_dest *dest, *next;
1ae44dfc
LB
11132 unsigned long output_cum = 0;
11133 unsigned long total_cum = 0;
9386b588 11134 unsigned long json_header_depth = 0;
67009e22 11135 struct bgp_table *itable;
0136788c 11136 bool show_msg;
96c81f66 11137 uint16_t show_flags = 0;
0136788c
LB
11138
11139 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11140
96f3485c
MK
11141 if (use_json)
11142 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11143
9bcb3eef
DS
11144 for (dest = bgp_table_top(table); dest; dest = next) {
11145 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11146
9bcb3eef
DS
11147 next = bgp_route_next(dest);
11148 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11149 continue;
67009e22 11150
9bcb3eef 11151 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11152 if (itable != NULL) {
1ae44dfc 11153 struct prefix_rd prd;
06b9f471 11154 char rd[RD_ADDRSTRLEN];
1ae44dfc 11155
9bcb3eef 11156 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11157 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11158 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11159 rd, next == NULL, &output_cum,
11160 &total_cum, &json_header_depth,
1e2ce4f1 11161 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11162 if (next == NULL)
11163 show_msg = false;
1ae44dfc
LB
11164 }
11165 }
0136788c
LB
11166 if (show_msg) {
11167 if (output_cum == 0)
11168 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11169 total_cum);
11170 else
11171 vty_out(vty,
11172 "\nDisplayed %ld routes and %ld total paths\n",
11173 output_cum, total_cum);
11174 }
1ae44dfc
LB
11175 return CMD_SUCCESS;
11176}
2aad8c42 11177
d62a17ae 11178static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11179 enum bgp_show_type type, void *output_arg,
96c81f66 11180 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11181{
d62a17ae 11182 struct bgp_table *table;
9386b588 11183 unsigned long json_header_depth = 0;
96f3485c 11184 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11185
d62a17ae 11186 if (bgp == NULL) {
11187 bgp = bgp_get_default();
11188 }
fee0f4c6 11189
d62a17ae 11190 if (bgp == NULL) {
11191 if (!use_json)
11192 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11193 else
11194 vty_out(vty, "{}\n");
d62a17ae 11195 return CMD_WARNING;
11196 }
4dd6177e 11197
cd8c2a27
MS
11198 /* Labeled-unicast routes live in the unicast table. */
11199 if (safi == SAFI_LABELED_UNICAST)
11200 safi = SAFI_UNICAST;
11201
1ae44dfc 11202 table = bgp->rib[afi][safi];
d62a17ae 11203 /* use MPLS and ENCAP specific shows until they are merged */
11204 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11205 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11206 output_arg, use_json);
d62a17ae 11207 }
dba3c1d3
PG
11208
11209 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11210 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11211 output_arg, use_json,
11212 1, NULL, NULL);
11213 }
fee0f4c6 11214
96f3485c 11215 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11216 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11217 rpki_target_state);
fee0f4c6 11218}
11219
d62a17ae 11220static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11221 safi_t safi, uint16_t show_flags)
f186de26 11222{
d62a17ae 11223 struct listnode *node, *nnode;
11224 struct bgp *bgp;
11225 int is_first = 1;
9f049418 11226 bool route_output = false;
96f3485c 11227 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11228
d62a17ae 11229 if (use_json)
11230 vty_out(vty, "{\n");
9f689658 11231
d62a17ae 11232 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11233 route_output = true;
d62a17ae 11234 if (use_json) {
11235 if (!is_first)
11236 vty_out(vty, ",\n");
11237 else
11238 is_first = 0;
11239
11240 vty_out(vty, "\"%s\":",
11241 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11242 ? VRF_DEFAULT_NAME
d62a17ae 11243 : bgp->name);
11244 } else {
11245 vty_out(vty, "\nInstance %s:\n",
11246 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11247 ? VRF_DEFAULT_NAME
d62a17ae 11248 : bgp->name);
11249 }
11250 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11251 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11252 }
9f689658 11253
d62a17ae 11254 if (use_json)
11255 vty_out(vty, "}\n");
9f049418
DS
11256 else if (!route_output)
11257 vty_out(vty, "%% BGP instance not found\n");
f186de26 11258}
11259
718e3744 11260/* Header of detailed BGP route information */
d62a17ae 11261void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11262 struct bgp_dest *dest,
11263 const struct prefix_rd *prd,
d62a17ae 11264 afi_t afi, safi_t safi, json_object *json)
11265{
40381db7 11266 struct bgp_path_info *pi;
b54892e0 11267 const struct prefix *p;
d62a17ae 11268 struct peer *peer;
11269 struct listnode *node, *nnode;
06b9f471 11270 char buf1[RD_ADDRSTRLEN];
d62a17ae 11271 int count = 0;
11272 int best = 0;
11273 int suppress = 0;
c5f1e1b2
C
11274 int accept_own = 0;
11275 int route_filter_translated_v4 = 0;
11276 int route_filter_v4 = 0;
11277 int route_filter_translated_v6 = 0;
11278 int route_filter_v6 = 0;
11279 int llgr_stale = 0;
11280 int no_llgr = 0;
11281 int accept_own_nexthop = 0;
11282 int blackhole = 0;
d62a17ae 11283 int no_export = 0;
11284 int no_advertise = 0;
11285 int local_as = 0;
c5f1e1b2 11286 int no_peer = 0;
d62a17ae 11287 int first = 1;
11288 int has_valid_label = 0;
11289 mpls_label_t label = 0;
11290 json_object *json_adv_to = NULL;
9bedbb1e 11291
9bcb3eef
DS
11292 p = bgp_dest_get_prefix(dest);
11293 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11294
11295 if (has_valid_label)
9bcb3eef 11296 label = label_pton(&dest->local_label);
d62a17ae 11297
44c69747 11298 if (safi == SAFI_EVPN) {
d62a17ae 11299
44c69747 11300 if (!json) {
2dbe669b 11301 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11302 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11303 : "",
2dbe669b 11304 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11305 } else {
11306 json_object_string_add(json, "rd",
11307 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11308 "");
11309 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11310 }
11311 } else {
11312 if (!json) {
9119ef3a
DA
11313 vty_out(vty,
11314 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11315 "\n",
d62a17ae 11316 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11317 ? prefix_rd2str(prd, buf1,
11318 sizeof(buf1))
11319 : ""),
9119ef3a
DA
11320 safi == SAFI_MPLS_VPN ? ":" : "", p,
11321 dest->version);
cd1964ff 11322
9119ef3a 11323 } else {
67d7e256 11324 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11325 json_object_int_add(json, "version", dest->version);
11326
11327 }
44c69747
LK
11328 }
11329
11330 if (has_valid_label) {
11331 if (json)
11332 json_object_int_add(json, "localLabel", label);
11333 else
d62a17ae 11334 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11335 }
11336
11337 if (!json)
d62a17ae 11338 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11339 vty_out(vty, "not allocated\n");
718e3744 11340
9bcb3eef 11341 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11342 count++;
40381db7 11343 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11344 best = count;
4056a5f6 11345 if (bgp_path_suppressed(pi))
d62a17ae 11346 suppress = 1;
cee9c031 11347
40381db7 11348 if (pi->attr->community == NULL)
cee9c031
QY
11349 continue;
11350
11351 no_advertise += community_include(
40381db7
DS
11352 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11353 no_export += community_include(pi->attr->community,
cee9c031 11354 COMMUNITY_NO_EXPORT);
40381db7 11355 local_as += community_include(pi->attr->community,
cee9c031 11356 COMMUNITY_LOCAL_AS);
40381db7 11357 accept_own += community_include(pi->attr->community,
cee9c031
QY
11358 COMMUNITY_ACCEPT_OWN);
11359 route_filter_translated_v4 += community_include(
40381db7 11360 pi->attr->community,
cee9c031
QY
11361 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11362 route_filter_translated_v6 += community_include(
40381db7 11363 pi->attr->community,
cee9c031
QY
11364 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11365 route_filter_v4 += community_include(
40381db7 11366 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11367 route_filter_v6 += community_include(
40381db7
DS
11368 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11369 llgr_stale += community_include(pi->attr->community,
cee9c031 11370 COMMUNITY_LLGR_STALE);
40381db7 11371 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11372 COMMUNITY_NO_LLGR);
11373 accept_own_nexthop +=
40381db7 11374 community_include(pi->attr->community,
cee9c031 11375 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11376 blackhole += community_include(pi->attr->community,
cee9c031 11377 COMMUNITY_BLACKHOLE);
40381db7 11378 no_peer += community_include(pi->attr->community,
cee9c031 11379 COMMUNITY_NO_PEER);
d62a17ae 11380 }
718e3744 11381 }
718e3744 11382
d62a17ae 11383 if (!json) {
11384 vty_out(vty, "Paths: (%d available", count);
11385 if (best) {
11386 vty_out(vty, ", best #%d", best);
b84060bb
PG
11387 if (safi == SAFI_UNICAST) {
11388 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11389 vty_out(vty, ", table %s",
11390 VRF_DEFAULT_NAME);
11391 else
11392 vty_out(vty, ", vrf %s",
11393 bgp->name);
11394 }
d62a17ae 11395 } else
11396 vty_out(vty, ", no best path");
11397
c5f1e1b2
C
11398 if (accept_own)
11399 vty_out(vty,
11400 ", accept own local route exported and imported in different VRF");
11401 else if (route_filter_translated_v4)
11402 vty_out(vty,
11403 ", mark translated RTs for VPNv4 route filtering");
11404 else if (route_filter_v4)
11405 vty_out(vty,
11406 ", attach RT as-is for VPNv4 route filtering");
11407 else if (route_filter_translated_v6)
11408 vty_out(vty,
11409 ", mark translated RTs for VPNv6 route filtering");
11410 else if (route_filter_v6)
11411 vty_out(vty,
11412 ", attach RT as-is for VPNv6 route filtering");
11413 else if (llgr_stale)
11414 vty_out(vty,
11415 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11416 else if (no_llgr)
11417 vty_out(vty,
11418 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11419 else if (accept_own_nexthop)
11420 vty_out(vty,
11421 ", accept local nexthop");
11422 else if (blackhole)
11423 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11424 else if (no_export)
11425 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11426 else if (no_advertise)
11427 vty_out(vty, ", not advertised to any peer");
d62a17ae 11428 else if (local_as)
11429 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11430 else if (no_peer)
11431 vty_out(vty,
11432 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11433
11434 if (suppress)
11435 vty_out(vty,
11436 ", Advertisements suppressed by an aggregate.");
11437 vty_out(vty, ")\n");
11438 }
718e3744 11439
d62a17ae 11440 /* If we are not using addpath then we can display Advertised to and
11441 * that will
11442 * show what peers we advertised the bestpath to. If we are using
11443 * addpath
11444 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11445 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11446 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11447 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11448 if (json && !json_adv_to)
11449 json_adv_to = json_object_new_object();
11450
11451 route_vty_out_advertised_to(
11452 vty, peer, &first,
11453 " Advertised to non peer-group peers:\n ",
11454 json_adv_to);
11455 }
11456 }
11457
11458 if (json) {
11459 if (json_adv_to) {
11460 json_object_object_add(json, "advertisedTo",
11461 json_adv_to);
11462 }
11463 } else {
11464 if (first)
11465 vty_out(vty, " Not advertised to any peer");
11466 vty_out(vty, "\n");
11467 }
11468 }
718e3744 11469}
11470
edfee30d 11471static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11472 struct bgp_dest *bgp_node, struct vty *vty,
11473 struct bgp *bgp, afi_t afi, safi_t safi,
11474 json_object *json, enum bgp_path_type pathtype,
4027d19b 11475 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11476{
11477 struct bgp_path_info *pi;
11478 int header = 1;
11479 char rdbuf[RD_ADDRSTRLEN];
11480 json_object *json_header = NULL;
11481 json_object *json_paths = NULL;
4933eaaf 11482 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11483
9bcb3eef 11484 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11485 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11486
11487 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11488 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11489 pi->peer, pi->attr, p);
4933eaaf 11490
4027d19b
DS
11491 if (rpki_target_state != RPKI_NOT_BEING_USED
11492 && rpki_curr_state != rpki_target_state)
4933eaaf 11493 continue;
44c69747
LK
11494
11495 if (json && !json_paths) {
11496 /* Instantiate json_paths only if path is valid */
11497 json_paths = json_object_new_array();
11498 if (pfx_rd) {
11499 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11500 json_header = json_object_new_object();
11501 } else
11502 json_header = json;
11503 }
11504
11505 if (header) {
11506 route_vty_out_detail_header(
11507 vty, bgp, bgp_node, pfx_rd,
11508 AFI_IP, safi, json_header);
11509 header = 0;
11510 }
11511 (*display)++;
11512
11513 if (pathtype == BGP_PATH_SHOW_ALL
11514 || (pathtype == BGP_PATH_SHOW_BESTPATH
11515 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11516 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11517 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11518 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11519 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11520 safi, rpki_curr_state, json_paths);
44c69747
LK
11521 }
11522
11523 if (json && json_paths) {
11524 json_object_object_add(json_header, "paths", json_paths);
11525
11526 if (pfx_rd)
11527 json_object_object_add(json, rdbuf, json_header);
11528 }
11529}
11530
2aad8c42
MS
11531/*
11532 * Return rd based on safi
11533 */
11534static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11535 safi_t safi)
11536{
11537 switch (safi) {
11538 case SAFI_MPLS_VPN:
11539 case SAFI_ENCAP:
11540 case SAFI_EVPN:
11541 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11542 default:
11543 return NULL;
11544
11545 }
11546}
11547
718e3744 11548/* Display specified route of BGP table. */
d62a17ae 11549static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11550 struct bgp_table *rib, const char *ip_str,
11551 afi_t afi, safi_t safi,
4027d19b 11552 enum rpki_states rpki_target_state,
d62a17ae 11553 struct prefix_rd *prd, int prefix_check,
9f049418 11554 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11555{
11556 int ret;
d62a17ae 11557 int display = 0;
11558 struct prefix match;
9bcb3eef
DS
11559 struct bgp_dest *dest;
11560 struct bgp_dest *rm;
d62a17ae 11561 struct bgp_table *table;
11562 json_object *json = NULL;
11563 json_object *json_paths = NULL;
11564
11565 /* Check IP address argument. */
11566 ret = str2prefix(ip_str, &match);
11567 if (!ret) {
11568 vty_out(vty, "address is malformed\n");
11569 return CMD_WARNING;
11570 }
718e3744 11571
d62a17ae 11572 match.family = afi2family(afi);
b05a1c8b 11573
44c69747 11574 if (use_json)
d62a17ae 11575 json = json_object_new_object();
718e3744 11576
44c69747 11577 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11578 for (dest = bgp_table_top(rib); dest;
11579 dest = bgp_route_next(dest)) {
11580 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11581
9bcb3eef 11582 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11583 continue;
9bcb3eef 11584 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11585 if (!table)
ea47320b 11586 continue;
d62a17ae 11587
4953391b
DA
11588 rm = bgp_node_match(table, &match);
11589 if (rm == NULL)
ea47320b 11590 continue;
d62a17ae 11591
9bcb3eef 11592 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11593 if (prefix_check
b54892e0 11594 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11595 bgp_dest_unlock_node(rm);
ea47320b
DL
11596 continue;
11597 }
d62a17ae 11598
9bcb3eef 11599 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11600 bgp, afi, safi, json, pathtype,
4027d19b 11601 &display, rpki_target_state);
44c69747 11602
9bcb3eef 11603 bgp_dest_unlock_node(rm);
44c69747
LK
11604 }
11605 } else if (safi == SAFI_EVPN) {
9bcb3eef 11606 struct bgp_dest *longest_pfx;
cded3b72 11607 bool is_exact_pfxlen_match = false;
44c69747 11608
9bcb3eef
DS
11609 for (dest = bgp_table_top(rib); dest;
11610 dest = bgp_route_next(dest)) {
11611 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11612
9bcb3eef 11613 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11614 continue;
9bcb3eef 11615 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11616 if (!table)
11617 continue;
11618
11619 longest_pfx = NULL;
cded3b72 11620 is_exact_pfxlen_match = false;
44c69747
LK
11621 /*
11622 * Search through all the prefixes for a match. The
11623 * pfx's are enumerated in ascending order of pfxlens.
11624 * So, the last pfx match is the longest match. Set
11625 * is_exact_pfxlen_match when we get exact pfxlen match
11626 */
11627 for (rm = bgp_table_top(table); rm;
11628 rm = bgp_route_next(rm)) {
b54892e0 11629 const struct prefix *rm_p =
9bcb3eef 11630 bgp_dest_get_prefix(rm);
44c69747
LK
11631 /*
11632 * Get prefixlen of the ip-prefix within type5
11633 * evpn route
11634 */
b54892e0
DS
11635 if (evpn_type5_prefix_match(rm_p, &match)
11636 && rm->info) {
44c69747
LK
11637 longest_pfx = rm;
11638 int type5_pfxlen =
b54892e0
DS
11639 bgp_evpn_get_type5_prefixlen(
11640 rm_p);
44c69747 11641 if (type5_pfxlen == match.prefixlen) {
cded3b72 11642 is_exact_pfxlen_match = true;
9bcb3eef 11643 bgp_dest_unlock_node(rm);
44c69747
LK
11644 break;
11645 }
d62a17ae 11646 }
11647 }
ea47320b 11648
44c69747
LK
11649 if (!longest_pfx)
11650 continue;
11651
11652 if (prefix_check && !is_exact_pfxlen_match)
11653 continue;
11654
11655 rm = longest_pfx;
9bcb3eef 11656 bgp_dest_lock_node(rm);
44c69747 11657
9bcb3eef 11658 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11659 bgp, afi, safi, json, pathtype,
4027d19b 11660 &display, rpki_target_state);
44c69747 11661
9bcb3eef 11662 bgp_dest_unlock_node(rm);
d62a17ae 11663 }
98a9dbc7 11664 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11665 if (use_json)
11666 json_paths = json_object_new_array();
11667
63a0b7a9
PG
11668 display = bgp_flowspec_display_match_per_ip(afi, rib,
11669 &match, prefix_check,
11670 vty,
11671 use_json,
11672 json_paths);
d5f20468
SP
11673 if (use_json) {
11674 if (display)
11675 json_object_object_add(json, "paths",
11676 json_paths);
11677 else
11678 json_object_free(json_paths);
11679 }
d62a17ae 11680 } else {
4953391b
DA
11681 dest = bgp_node_match(rib, &match);
11682 if (dest != NULL) {
9bcb3eef 11683 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11684 if (!prefix_check
9bcb3eef
DS
11685 || dest_p->prefixlen == match.prefixlen) {
11686 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11687 safi, json, pathtype,
4027d19b 11688 &display, rpki_target_state);
d62a17ae 11689 }
11690
9bcb3eef 11691 bgp_dest_unlock_node(dest);
d62a17ae 11692 }
11693 }
e5eee9af 11694
d62a17ae 11695 if (use_json) {
75eeda93 11696 vty_json(vty, json);
d62a17ae 11697 } else {
11698 if (!display) {
11699 vty_out(vty, "%% Network not in table\n");
11700 return CMD_WARNING;
11701 }
11702 }
b05a1c8b 11703
d62a17ae 11704 return CMD_SUCCESS;
718e3744 11705}
11706
fee0f4c6 11707/* Display specified route of Main RIB */
d62a17ae 11708static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11709 afi_t afi, safi_t safi, struct prefix_rd *prd,
11710 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11711 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11712{
9b86009a 11713 if (!bgp) {
d62a17ae 11714 bgp = bgp_get_default();
9b86009a
RW
11715 if (!bgp) {
11716 if (!use_json)
11717 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11718 else
11719 vty_out(vty, "{}\n");
9b86009a
RW
11720 return CMD_WARNING;
11721 }
11722 }
d62a17ae 11723
11724 /* labeled-unicast routes live in the unicast table */
11725 if (safi == SAFI_LABELED_UNICAST)
11726 safi = SAFI_UNICAST;
11727
11728 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11729 afi, safi, rpki_target_state, prd,
8aa22bbb 11730 prefix_check, pathtype, use_json);
d62a17ae 11731}
11732
11733static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11734 struct cmd_token **argv, bool exact, afi_t afi,
11735 safi_t safi, bool uj)
d62a17ae 11736{
11737 struct lcommunity *lcom;
11738 struct buffer *b;
11739 int i;
11740 char *str;
11741 int first = 0;
96c81f66 11742 uint16_t show_flags = 0;
4f28b2b5 11743 int ret;
96f3485c
MK
11744
11745 if (uj)
11746 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11747
11748 b = buffer_new(1024);
11749 for (i = 0; i < argc; i++) {
11750 if (first)
11751 buffer_putc(b, ' ');
11752 else {
11753 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11754 first = 1;
11755 buffer_putstr(b, argv[i]->arg);
11756 }
11757 }
11758 }
11759 buffer_putc(b, '\0');
57d187bc 11760
d62a17ae 11761 str = buffer_getstr(b);
11762 buffer_free(b);
57d187bc 11763
d62a17ae 11764 lcom = lcommunity_str2com(str);
11765 XFREE(MTYPE_TMP, str);
11766 if (!lcom) {
11767 vty_out(vty, "%% Large-community malformed\n");
11768 return CMD_WARNING;
11769 }
57d187bc 11770
4f28b2b5 11771 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11772 (exact ? bgp_show_type_lcommunity_exact
11773 : bgp_show_type_lcommunity),
11774 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11775
11776 lcommunity_free(&lcom);
11777 return ret;
57d187bc
JS
11778}
11779
d62a17ae 11780static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11781 const char *lcom, bool exact, afi_t afi,
11782 safi_t safi, bool uj)
57d187bc 11783{
d62a17ae 11784 struct community_list *list;
96c81f66 11785 uint16_t show_flags = 0;
96f3485c
MK
11786
11787 if (uj)
11788 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11789
57d187bc 11790
e237b0d2 11791 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11792 LARGE_COMMUNITY_LIST_MASTER);
11793 if (list == NULL) {
11794 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11795 lcom);
11796 return CMD_WARNING;
11797 }
57d187bc 11798
36a206db 11799 return bgp_show(vty, bgp, afi, safi,
11800 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11801 : bgp_show_type_lcommunity_list),
1e2ce4f1 11802 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11803}
11804
52951b63
DS
11805DEFUN (show_ip_bgp_large_community_list,
11806 show_ip_bgp_large_community_list_cmd,
77a3a95e 11807 "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
11808 SHOW_STR
11809 IP_STR
11810 BGP_STR
11811 BGP_INSTANCE_HELP_STR
9bedbb1e 11812 BGP_AFI_HELP_STR
4dd6177e 11813 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11814 "Display routes matching the large-community-list\n"
11815 "large-community-list number\n"
11816 "large-community-list name\n"
36a206db 11817 "Exact match of the large-communities\n"
52951b63
DS
11818 JSON_STR)
11819{
d62a17ae 11820 afi_t afi = AFI_IP6;
11821 safi_t safi = SAFI_UNICAST;
11822 int idx = 0;
36a206db 11823 bool exact_match = 0;
4d678463 11824 struct bgp *bgp = NULL;
9f049418 11825 bool uj = use_json(argc, argv);
d62a17ae 11826
ef3364f0
DA
11827 if (uj)
11828 argc--;
4d678463 11829
ef3364f0
DA
11830 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11831 &bgp, uj);
11832 if (!idx)
11833 return CMD_WARNING;
d62a17ae 11834
11835 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11836
11837 const char *clist_number_or_name = argv[++idx]->arg;
11838
11839 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11840 exact_match = 1;
11841
11842 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11843 exact_match, afi, safi, uj);
52951b63
DS
11844}
11845DEFUN (show_ip_bgp_large_community,
11846 show_ip_bgp_large_community_cmd,
36a206db 11847 "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
11848 SHOW_STR
11849 IP_STR
11850 BGP_STR
11851 BGP_INSTANCE_HELP_STR
9bedbb1e 11852 BGP_AFI_HELP_STR
4dd6177e 11853 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11854 "Display routes matching the large-communities\n"
11855 "List of large-community numbers\n"
36a206db 11856 "Exact match of the large-communities\n"
52951b63
DS
11857 JSON_STR)
11858{
d62a17ae 11859 afi_t afi = AFI_IP6;
11860 safi_t safi = SAFI_UNICAST;
11861 int idx = 0;
36a206db 11862 bool exact_match = 0;
4d678463 11863 struct bgp *bgp = NULL;
9f049418 11864 bool uj = use_json(argc, argv);
96c81f66 11865 uint16_t show_flags = 0;
d62a17ae 11866
96f3485c
MK
11867 if (uj) {
11868 argc--;
11869 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11870 }
4d678463 11871
96f3485c
MK
11872 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11873 &bgp, uj);
11874 if (!idx)
11875 return CMD_WARNING;
d62a17ae 11876
36a206db 11877 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11878 if (argv_find(argv, argc, "exact-match", &idx))
11879 exact_match = 1;
11880 return bgp_show_lcommunity(vty, bgp, argc, argv,
11881 exact_match, afi, safi, uj);
11882 } else
d62a17ae 11883 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11884 bgp_show_type_lcommunity_all, NULL, show_flags,
11885 RPKI_NOT_BEING_USED);
52951b63
DS
11886}
11887
71f1613a
DA
11888static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11889 safi_t safi, struct json_object *json_array);
d62a17ae 11890static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11891 safi_t safi, struct json_object *json);
e01ca200 11892
7b2ff250 11893
9ab0cf58
PG
11894DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11895 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11896 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11897 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11898{
11899 bool uj = use_json(argc, argv);
11900 struct bgp *bgp = NULL;
ec76a1d1
DA
11901 safi_t safi = SAFI_UNICAST;
11902 afi_t afi = AFI_IP6;
4265b261 11903 int idx = 0;
6c9d22e2
PG
11904 struct json_object *json_all = NULL;
11905 struct json_object *json_afi_safi = NULL;
4265b261
PG
11906
11907 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11908 &bgp, false);
71f1613a 11909 if (!idx)
4265b261 11910 return CMD_WARNING;
6c9d22e2 11911
4265b261 11912 if (uj)
6c9d22e2 11913 json_all = json_object_new_object();
4265b261 11914
9ab0cf58
PG
11915 FOREACH_AFI_SAFI (afi, safi) {
11916 /*
11917 * So limit output to those afi/safi pairs that
11918 * actually have something interesting in them
11919 */
11920 if (strmatch(get_afi_safi_str(afi, safi, true),
11921 "Unknown")) {
11922 continue;
11923 }
11924 if (uj) {
11925 json_afi_safi = json_object_new_array();
11926 json_object_object_add(
11927 json_all,
11928 get_afi_safi_str(afi, safi, true),
11929 json_afi_safi);
11930 } else {
11931 json_afi_safi = NULL;
6c9d22e2 11932 }
9ab0cf58
PG
11933
11934 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11935 }
6c9d22e2
PG
11936
11937 if (uj) {
9ab0cf58
PG
11938 vty_out(vty, "%s",
11939 json_object_to_json_string_ext(
11940 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11941 json_object_free(json_all);
4265b261 11942 }
6c9d22e2 11943
4265b261
PG
11944 return CMD_SUCCESS;
11945}
11946
7b2ff250 11947/* BGP route print out function without JSON */
14718643
PG
11948DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11949 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11950 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11951 SHOW_STR
11952 IP_STR
11953 BGP_STR
11954 BGP_INSTANCE_HELP_STR
11955 L2VPN_HELP_STR
11956 EVPN_HELP_STR
11957 "BGP RIB advertisement statistics\n"
11958 JSON_STR)
11959{
ec76a1d1
DA
11960 afi_t afi = AFI_IP6;
11961 safi_t safi = SAFI_UNICAST;
14718643
PG
11962 struct bgp *bgp = NULL;
11963 int idx = 0, ret;
11964 bool uj = use_json(argc, argv);
11965 struct json_object *json_afi_safi = NULL, *json = NULL;
11966
11967 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11968 &bgp, false);
11969 if (!idx)
11970 return CMD_WARNING;
11971
11972 if (uj)
11973 json_afi_safi = json_object_new_array();
11974 else
11975 json_afi_safi = NULL;
11976
11977 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11978
11979 if (uj) {
11980 json = json_object_new_object();
11981 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11982 json_afi_safi);
11983 vty_out(vty, "%s", json_object_to_json_string_ext(
11984 json, JSON_C_TO_STRING_PRETTY));
11985 json_object_free(json);
11986 }
11987 return ret;
11988}
11989
893cccd0 11990/* BGP route print out function without JSON */
9ab0cf58
PG
11991DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11992 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11993 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11994 "]]\
893cccd0 11995 statistics [json]",
9ab0cf58
PG
11996 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11997 BGP_SAFI_WITH_LABEL_HELP_STR
11998 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11999{
ec76a1d1
DA
12000 afi_t afi = AFI_IP6;
12001 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12002 struct bgp *bgp = NULL;
12003 int idx = 0, ret;
12004 bool uj = use_json(argc, argv);
6c9d22e2 12005 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12006
12007 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12008 &bgp, false);
12009 if (!idx)
12010 return CMD_WARNING;
6c9d22e2 12011
893cccd0 12012 if (uj)
6c9d22e2
PG
12013 json_afi_safi = json_object_new_array();
12014 else
12015 json_afi_safi = NULL;
12016
12017 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12018
12019 if (uj) {
12020 json = json_object_new_object();
12021 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12022 json_afi_safi);
9ab0cf58
PG
12023 vty_out(vty, "%s",
12024 json_object_to_json_string_ext(
12025 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
12026 json_object_free(json);
12027 }
12028 return ret;
893cccd0 12029}
7b2ff250 12030
fe0f234d 12031DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12032 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12033 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12034 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12035 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12036 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12037 "Display the entries for all address families\n"
9ab0cf58
PG
12038 "Display detailed information about dampening\n"
12039 "Display detail of configured dampening parameters\n"
fe0f234d 12040 JSON_STR)
718e3744 12041{
d62a17ae 12042 afi_t afi = AFI_IP6;
12043 safi_t safi = SAFI_UNICAST;
d62a17ae 12044 struct bgp *bgp = NULL;
12045 int idx = 0;
96c81f66 12046 uint16_t show_flags = 0;
fe0f234d
RW
12047 bool uj = use_json(argc, argv);
12048
12049 if (uj) {
12050 argc--;
12051 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12052 }
96f3485c
MK
12053
12054 /* [<ipv4|ipv6> [all]] */
12055 if (all) {
12056 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12057 if (argv_find(argv, argc, "ipv4", &idx))
12058 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12059
12060 if (argv_find(argv, argc, "ipv6", &idx))
12061 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12062 }
d62a17ae 12063
12064 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12065 &bgp, false);
d62a17ae 12066 if (!idx)
12067 return CMD_WARNING;
12068
fe0f234d 12069 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12070}
12071
fe0f234d
RW
12072/* BGP route print out function */
12073DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12074 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12075 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12076 "]]\
96f3485c 12077 [all$all]\
cf4898bc
QY
12078 [cidr-only\
12079 |dampening <flap-statistics|dampened-paths>\
12080 |community [AA:NN|local-AS|no-advertise|no-export\
12081 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12082 |accept-own|accept-own-nexthop|route-filter-v6\
12083 |route-filter-v4|route-filter-translated-v6\
12084 |route-filter-translated-v4] [exact-match]\
70799983 12085 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12086 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12087 |prefix-list WORD\
bf1a944a 12088 |route-map WORD\
1e2ce4f1 12089 |rpki <invalid|valid|notfound>\
7d3cae70 12090 |version (1-4294967295)\
b4ad2fae 12091 |alias ALIAS_NAME\
39c3c736
RW
12092 |A.B.C.D/M longer-prefixes\
12093 |X:X::X:X/M longer-prefixes\
f280c93b 12094 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12095 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12096 BGP_SAFI_WITH_LABEL_HELP_STR
12097 "Display the entries for all address families\n"
12098 "Display only routes with non-natural netmasks\n"
12099 "Display detailed information about dampening\n"
12100 "Display flap statistics of routes\n"
12101 "Display paths suppressed due to dampening\n"
12102 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12103 "Do not send outside local AS (well-known community)\n"
12104 "Do not advertise to any peer (well-known community)\n"
12105 "Do not export to next AS (well-known community)\n"
12106 "Graceful shutdown (well-known community)\n"
12107 "Do not export to any peer (well-known community)\n"
12108 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12109 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12110 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12111 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12112 "Should accept VPN route with local nexthop (well-known community)\n"
12113 "RT VPNv6 route filtering (well-known community)\n"
12114 "RT VPNv4 route filtering (well-known community)\n"
12115 "RT translated VPNv6 route filtering (well-known community)\n"
12116 "RT translated VPNv4 route filtering (well-known community)\n"
12117 "Exact match of the communities\n"
70799983
RW
12118 "Community-list number\n"
12119 "Community-list name\n"
12120 "Display routes matching the community-list\n"
12121 "Exact match of the communities\n"
a7129347
RW
12122 "Display routes conforming to the filter-list\n"
12123 "Regular expression access list name\n"
6deaf579
RW
12124 "Display routes conforming to the prefix-list\n"
12125 "Prefix-list name\n"
bf1a944a
RW
12126 "Display routes matching the route-map\n"
12127 "A route-map to match on\n"
a70a28a5
DA
12128 "RPKI route types\n"
12129 "A valid path as determined by rpki\n"
12130 "A invalid path as determined by rpki\n"
12131 "A path that has no rpki data\n"
12132 "Display prefixes with matching version numbers\n"
12133 "Version number and above\n"
12134 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12135 "BGP community alias\n"
12136 "IPv4 prefix\n"
12137 "Display route and more specific routes\n"
12138 "IPv6 prefix\n"
12139 "Display route and more specific routes\n"
12140 JSON_STR
a70a28a5
DA
12141 "Display detailed version of JSON output\n"
12142 "Increase table width for longer prefixes\n")
7b2ff250
DW
12143{
12144 afi_t afi = AFI_IP6;
12145 safi_t safi = SAFI_UNICAST;
12146 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12147 void *output_arg = NULL;
7b2ff250
DW
12148 struct bgp *bgp = NULL;
12149 int idx = 0;
d0086e8e 12150 int exact_match = 0;
96f3485c
MK
12151 char *community = NULL;
12152 bool first = true;
96c81f66 12153 uint16_t show_flags = 0;
4027d19b 12154 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12155
12156 if (uj) {
9f049418 12157 argc--;
96f3485c
MK
12158 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12159 }
12160
f280c93b
DA
12161 if (detail)
12162 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12163
96f3485c
MK
12164 /* [<ipv4|ipv6> [all]] */
12165 if (all) {
12166 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12167
12168 if (argv_find(argv, argc, "ipv4", &idx))
12169 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12170
12171 if (argv_find(argv, argc, "ipv6", &idx))
12172 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12173 }
12174
12175 if (wide)
12176 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12177
12178 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12179 &bgp, uj);
7b2ff250
DW
12180 if (!idx)
12181 return CMD_WARNING;
12182
7b2ff250 12183 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12184 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12185
12186 if (argv_find(argv, argc, "dampening", &idx)) {
12187 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12188 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12189 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12190 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12191 }
12192
12193 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12194 char *maybecomm = NULL;
d0086e8e 12195
79bc257a
RW
12196 if (idx + 1 < argc) {
12197 if (argv[idx + 1]->type == VARIABLE_TKN)
12198 maybecomm = argv[idx + 1]->arg;
12199 else
12200 maybecomm = argv[idx + 1]->text;
12201 }
12202
cf4898bc
QY
12203 if (maybecomm && !strmatch(maybecomm, "json")
12204 && !strmatch(maybecomm, "exact-match"))
12205 community = maybecomm;
d0086e8e 12206
cf4898bc
QY
12207 if (argv_find(argv, argc, "exact-match", &idx))
12208 exact_match = 1;
d0086e8e 12209
96f3485c
MK
12210 if (!community)
12211 sh_type = bgp_show_type_community_all;
12212 }
12213
70799983
RW
12214 if (argv_find(argv, argc, "community-list", &idx)) {
12215 const char *clist_number_or_name = argv[++idx]->arg;
12216 struct community_list *list;
12217
12218 if (argv_find(argv, argc, "exact-match", &idx))
12219 exact_match = 1;
12220
12221 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12222 COMMUNITY_LIST_MASTER);
12223 if (list == NULL) {
12224 vty_out(vty,
12225 "%% %s is not a valid community-list name\n",
12226 clist_number_or_name);
12227 return CMD_WARNING;
12228 }
12229
12230 if (exact_match)
12231 sh_type = bgp_show_type_community_list_exact;
12232 else
12233 sh_type = bgp_show_type_community_list;
12234 output_arg = list;
12235 }
12236
a7129347
RW
12237 if (argv_find(argv, argc, "filter-list", &idx)) {
12238 const char *filter = argv[++idx]->arg;
12239 struct as_list *as_list;
12240
12241 as_list = as_list_lookup(filter);
12242 if (as_list == NULL) {
12243 vty_out(vty,
12244 "%% %s is not a valid AS-path access-list name\n",
12245 filter);
12246 return CMD_WARNING;
12247 }
12248
12249 sh_type = bgp_show_type_filter_list;
12250 output_arg = as_list;
12251 }
12252
6deaf579
RW
12253 if (argv_find(argv, argc, "prefix-list", &idx)) {
12254 const char *prefix_list_str = argv[++idx]->arg;
12255 struct prefix_list *plist;
12256
12257 plist = prefix_list_lookup(afi, prefix_list_str);
12258 if (plist == NULL) {
12259 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12260 prefix_list_str);
12261 return CMD_WARNING;
12262 }
12263
12264 sh_type = bgp_show_type_prefix_list;
12265 output_arg = plist;
12266 }
12267
bf1a944a
RW
12268 if (argv_find(argv, argc, "route-map", &idx)) {
12269 const char *rmap_str = argv[++idx]->arg;
12270 struct route_map *rmap;
12271
12272 rmap = route_map_lookup_by_name(rmap_str);
12273 if (!rmap) {
12274 vty_out(vty, "%% %s is not a valid route-map name\n",
12275 rmap_str);
12276 return CMD_WARNING;
12277 }
12278
12279 sh_type = bgp_show_type_route_map;
12280 output_arg = rmap;
12281 }
12282
1e2ce4f1
DS
12283 if (argv_find(argv, argc, "rpki", &idx)) {
12284 sh_type = bgp_show_type_rpki;
12285 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12286 rpki_target_state = RPKI_VALID;
1e2ce4f1 12287 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12288 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12289 }
12290
7d3cae70
DA
12291 /* Display prefixes with matching version numbers */
12292 if (argv_find(argv, argc, "version", &idx)) {
12293 sh_type = bgp_show_type_prefix_version;
2391833e 12294 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12295 }
12296
a70a28a5
DA
12297 /* Display prefixes with matching BGP community alias */
12298 if (argv_find(argv, argc, "alias", &idx)) {
12299 sh_type = bgp_show_type_community_alias;
2391833e 12300 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12301 }
12302
39c3c736
RW
12303 /* prefix-longer */
12304 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12305 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12306 const char *prefix_str = argv[idx]->arg;
12307 struct prefix p;
12308
12309 if (!str2prefix(prefix_str, &p)) {
12310 vty_out(vty, "%% Malformed Prefix\n");
12311 return CMD_WARNING;
12312 }
12313
12314 sh_type = bgp_show_type_prefix_longer;
12315 output_arg = &p;
a70a28a5
DA
12316 }
12317
96f3485c
MK
12318 if (!all) {
12319 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12320 if (community)
12321 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12322 exact_match, afi, safi,
12323 show_flags);
2391833e 12324 else
a70a28a5 12325 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12326 output_arg, show_flags,
a70a28a5 12327 rpki_target_state);
96f3485c
MK
12328 } else {
12329 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12330 * AFI_IP6 */
12331
12332 if (uj)
12333 vty_out(vty, "{\n");
12334
12335 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12336 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12337 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12338 ? AFI_IP
12339 : AFI_IP6;
12340 FOREACH_SAFI (safi) {
96f3485c
MK
12341 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12342 continue;
12343
12344 if (uj) {
12345 if (first)
12346 first = false;
12347 else
12348 vty_out(vty, ",\n");
12349 vty_out(vty, "\"%s\":{\n",
12350 get_afi_safi_str(afi, safi,
12351 true));
12352 } else
12353 vty_out(vty,
12354 "\nFor address family: %s\n",
12355 get_afi_safi_str(afi, safi,
12356 false));
12357
12358 if (community)
12359 bgp_show_community(vty, bgp, community,
12360 exact_match, afi,
12361 safi, show_flags);
12362 else
12363 bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12364 output_arg, show_flags,
4027d19b 12365 rpki_target_state);
96f3485c
MK
12366 if (uj)
12367 vty_out(vty, "}\n");
12368 }
12369 } else {
12370 /* show <ip> bgp all: for each AFI and SAFI*/
12371 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12372 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12373 continue;
12374
12375 if (uj) {
12376 if (first)
12377 first = false;
12378 else
12379 vty_out(vty, ",\n");
d0086e8e 12380
96f3485c
MK
12381 vty_out(vty, "\"%s\":{\n",
12382 get_afi_safi_str(afi, safi,
12383 true));
12384 } else
12385 vty_out(vty,
12386 "\nFor address family: %s\n",
12387 get_afi_safi_str(afi, safi,
12388 false));
12389
12390 if (community)
12391 bgp_show_community(vty, bgp, community,
12392 exact_match, afi,
12393 safi, show_flags);
12394 else
12395 bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12396 output_arg, show_flags,
4027d19b 12397 rpki_target_state);
96f3485c
MK
12398 if (uj)
12399 vty_out(vty, "}\n");
12400 }
12401 }
12402 if (uj)
12403 vty_out(vty, "}\n");
12404 }
12405 return CMD_SUCCESS;
a636c635 12406}
47fc97cc 12407
718e3744 12408DEFUN (show_ip_bgp_route,
12409 show_ip_bgp_route_cmd,
8aa22bbb 12410 "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 12411 SHOW_STR
12412 IP_STR
12413 BGP_STR
a636c635 12414 BGP_INSTANCE_HELP_STR
4f280b15 12415 BGP_AFI_HELP_STR
4dd6177e 12416 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12417 "Network in the BGP routing table to display\n"
0c7b1b01 12418 "IPv4 prefix\n"
8c3deaae 12419 "Network in the BGP routing table to display\n"
0c7b1b01 12420 "IPv6 prefix\n"
4092b06c 12421 "Display only the bestpath\n"
b05a1c8b 12422 "Display only multipaths\n"
8aa22bbb
DS
12423 "Display only paths that match the specified rpki state\n"
12424 "A valid path as determined by rpki\n"
12425 "A invalid path as determined by rpki\n"
12426 "A path that has no rpki data\n"
9973d184 12427 JSON_STR)
4092b06c 12428{
d62a17ae 12429 int prefix_check = 0;
ae19d7dd 12430
d62a17ae 12431 afi_t afi = AFI_IP6;
12432 safi_t safi = SAFI_UNICAST;
12433 char *prefix = NULL;
12434 struct bgp *bgp = NULL;
12435 enum bgp_path_type path_type;
9f049418 12436 bool uj = use_json(argc, argv);
b05a1c8b 12437
d62a17ae 12438 int idx = 0;
ae19d7dd 12439
d62a17ae 12440 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12441 &bgp, uj);
d62a17ae 12442 if (!idx)
12443 return CMD_WARNING;
c41247f5 12444
d62a17ae 12445 if (!bgp) {
12446 vty_out(vty,
12447 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12448 return CMD_WARNING;
12449 }
a636c635 12450
d62a17ae 12451 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12452 if (argv_find(argv, argc, "A.B.C.D", &idx)
12453 || argv_find(argv, argc, "X:X::X:X", &idx))
12454 prefix_check = 0;
12455 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12456 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12457 prefix_check = 1;
12458
12459 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12460 && afi != AFI_IP6) {
12461 vty_out(vty,
12462 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12463 return CMD_WARNING;
12464 }
12465 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12466 && afi != AFI_IP) {
12467 vty_out(vty,
12468 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12469 return CMD_WARNING;
12470 }
12471
12472 prefix = argv[idx]->arg;
12473
12474 /* [<bestpath|multipath>] */
12475 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12476 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12477 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12478 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12479 else
360660c6 12480 path_type = BGP_PATH_SHOW_ALL;
a636c635 12481
d62a17ae 12482 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12483 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12484}
12485
8c3deaae
QY
12486DEFUN (show_ip_bgp_regexp,
12487 show_ip_bgp_regexp_cmd,
3e5b31b3 12488 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12489 SHOW_STR
12490 IP_STR
12491 BGP_STR
b00b230a 12492 BGP_INSTANCE_HELP_STR
4f280b15 12493 BGP_AFI_HELP_STR
4dd6177e 12494 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12495 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12496 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12497 JSON_STR)
8c3deaae 12498{
d62a17ae 12499 afi_t afi = AFI_IP6;
12500 safi_t safi = SAFI_UNICAST;
12501 struct bgp *bgp = NULL;
3e5b31b3
DA
12502 bool uj = use_json(argc, argv);
12503 char *regstr = NULL;
8c3deaae 12504
d62a17ae 12505 int idx = 0;
12506 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12507 &bgp, false);
d62a17ae 12508 if (!idx)
12509 return CMD_WARNING;
8c3deaae 12510
d62a17ae 12511 // get index of regex
3e5b31b3
DA
12512 if (argv_find(argv, argc, "REGEX", &idx))
12513 regstr = argv[idx]->arg;
8c3deaae 12514
5f71d11c 12515 assert(regstr);
3e5b31b3
DA
12516 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12517 bgp_show_type_regexp, uj);
8c3deaae
QY
12518}
12519
ae248832 12520DEFPY (show_ip_bgp_instance_all,
a636c635 12521 show_ip_bgp_instance_all_cmd,
ae248832 12522 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12523 SHOW_STR
a636c635 12524 IP_STR
4092b06c 12525 BGP_STR
a636c635 12526 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12527 BGP_AFI_HELP_STR
4dd6177e 12528 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12529 JSON_STR
12530 "Increase table width for longer prefixes\n")
4092b06c 12531{
54d05dea 12532 afi_t afi = AFI_IP6;
d62a17ae 12533 safi_t safi = SAFI_UNICAST;
12534 struct bgp *bgp = NULL;
d62a17ae 12535 int idx = 0;
96c81f66 12536 uint16_t show_flags = 0;
ae19d7dd 12537
96f3485c 12538 if (uj) {
d62a17ae 12539 argc--;
96f3485c
MK
12540 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12541 }
12542
12543 if (wide)
12544 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12545
9f049418
DS
12546 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12547 &bgp, uj);
12548 if (!idx)
12549 return CMD_WARNING;
12550
96f3485c 12551 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12552 return CMD_SUCCESS;
e3e29b32
LB
12553}
12554
a4d82a8a 12555static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12556 afi_t afi, safi_t safi, enum bgp_show_type type,
12557 bool use_json)
718e3744 12558{
d62a17ae 12559 regex_t *regex;
12560 int rc;
96c81f66 12561 uint16_t show_flags = 0;
96f3485c
MK
12562
12563 if (use_json)
12564 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12565
c3900853 12566 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12567 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12568 regstr);
12569 return CMD_WARNING_CONFIG_FAILED;
12570 }
12571
d62a17ae 12572 regex = bgp_regcomp(regstr);
12573 if (!regex) {
12574 vty_out(vty, "Can't compile regexp %s\n", regstr);
12575 return CMD_WARNING;
12576 }
a636c635 12577
1e2ce4f1
DS
12578 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12579 RPKI_NOT_BEING_USED);
d62a17ae 12580 bgp_regex_free(regex);
12581 return rc;
e3e29b32
LB
12582}
12583
7f323236
DW
12584static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12585 const char *comstr, int exact, afi_t afi,
96c81f66 12586 safi_t safi, uint16_t show_flags)
d62a17ae 12587{
12588 struct community *com;
d62a17ae 12589 int ret = 0;
12590
7f323236 12591 com = community_str2com(comstr);
d62a17ae 12592 if (!com) {
7f323236 12593 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12594 return CMD_WARNING;
12595 }
12596
12597 ret = bgp_show(vty, bgp, afi, safi,
12598 (exact ? bgp_show_type_community_exact
12599 : bgp_show_type_community),
1e2ce4f1 12600 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12601 community_free(&com);
46c3ce83 12602
d62a17ae 12603 return ret;
718e3744 12604}
12605
d62a17ae 12606enum bgp_stats {
12607 BGP_STATS_MAXBITLEN = 0,
12608 BGP_STATS_RIB,
12609 BGP_STATS_PREFIXES,
12610 BGP_STATS_TOTPLEN,
12611 BGP_STATS_UNAGGREGATEABLE,
12612 BGP_STATS_MAX_AGGREGATEABLE,
12613 BGP_STATS_AGGREGATES,
12614 BGP_STATS_SPACE,
12615 BGP_STATS_ASPATH_COUNT,
12616 BGP_STATS_ASPATH_MAXHOPS,
12617 BGP_STATS_ASPATH_TOTHOPS,
12618 BGP_STATS_ASPATH_MAXSIZE,
12619 BGP_STATS_ASPATH_TOTSIZE,
12620 BGP_STATS_ASN_HIGHEST,
12621 BGP_STATS_MAX,
a636c635 12622};
2815e61f 12623
9ab0cf58 12624#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12625#define TABLE_STATS_IDX_JSON 1
12626
12627static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12628 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12629 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12630 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12631 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12632 "unaggregateablePrefixes"},
12633 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12634 "maximumAggregateablePrefixes"},
12635 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12636 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12637 [BGP_STATS_SPACE] = {"Address space advertised",
12638 "addressSpaceAdvertised"},
9ab0cf58
PG
12639 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12640 "advertisementsWithPaths"},
12641 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12642 "longestAsPath"},
12643 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12644 "largestAsPath"},
12645 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12646 "averageAsPathLengthHops"},
12647 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12648 "averageAsPathSizeBytes"},
12649 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12650 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12651};
2815e61f 12652
d62a17ae 12653struct bgp_table_stats {
12654 struct bgp_table *table;
12655 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12656 double total_space;
ff7924f6
PJ
12657};
12658
9bcb3eef 12659static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12660 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12661{
9bcb3eef 12662 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12663 struct bgp_path_info *pi;
b54892e0 12664 const struct prefix *rn_p;
d62a17ae 12665
9bcb3eef 12666 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12667 return;
d62a17ae 12668
9bcb3eef 12669 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12670 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12671 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12672
9c14ec72 12673 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12674 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12675 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12676
9bcb3eef 12677 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12678 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12679 /* announced address space */
12680 if (space)
b54892e0 12681 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12682 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12683 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12684
9c14ec72 12685
9bcb3eef 12686 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12687 ts->counts[BGP_STATS_RIB]++;
12688
05864da7
DS
12689 if (CHECK_FLAG(pi->attr->flag,
12690 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12691 ts->counts[BGP_STATS_AGGREGATES]++;
12692
12693 /* as-path stats */
05864da7 12694 if (pi->attr->aspath) {
9c14ec72
RW
12695 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12696 unsigned int size = aspath_size(pi->attr->aspath);
12697 as_t highest = aspath_highest(pi->attr->aspath);
12698
12699 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12700
12701 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12702 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12703
12704 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12705 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12706
12707 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12708 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12709 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12710 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12711 }
12712 }
12713}
12714
12715static int bgp_table_stats_walker(struct thread *t)
12716{
9bcb3eef
DS
12717 struct bgp_dest *dest, *ndest;
12718 struct bgp_dest *top;
9c14ec72
RW
12719 struct bgp_table_stats *ts = THREAD_ARG(t);
12720 unsigned int space = 0;
12721
12722 if (!(top = bgp_table_top(ts->table)))
12723 return 0;
12724
12725 switch (ts->table->afi) {
12726 case AFI_IP:
12727 space = IPV4_MAX_BITLEN;
12728 break;
12729 case AFI_IP6:
12730 space = IPV6_MAX_BITLEN;
12731 break;
3ba7b4af
TA
12732 case AFI_L2VPN:
12733 space = EVPN_ROUTE_PREFIXLEN;
12734 break;
9c14ec72
RW
12735 default:
12736 return 0;
12737 }
12738
12739 ts->counts[BGP_STATS_MAXBITLEN] = space;
12740
9bcb3eef 12741 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12742 if (ts->table->safi == SAFI_MPLS_VPN
12743 || ts->table->safi == SAFI_ENCAP
12744 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12745 struct bgp_table *table;
12746
9bcb3eef 12747 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12748 if (!table)
12749 continue;
12750
12751 top = bgp_table_top(table);
9bcb3eef
DS
12752 for (ndest = bgp_table_top(table); ndest;
12753 ndest = bgp_route_next(ndest))
12754 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12755 } else {
9bcb3eef 12756 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12757 }
12758 }
9c14ec72 12759
d62a17ae 12760 return 0;
2815e61f 12761}
ff7924f6 12762
71f1613a
DA
12763static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12764 struct json_object *json_array)
12765{
12766 struct listnode *node, *nnode;
12767 struct bgp *bgp;
12768
12769 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12770 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12771}
12772
12773static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12774 safi_t safi, struct json_object *json_array)
2815e61f 12775{
d62a17ae 12776 struct bgp_table_stats ts;
12777 unsigned int i;
893cccd0
PG
12778 int ret = CMD_SUCCESS;
12779 char temp_buf[20];
6c9d22e2
PG
12780 struct json_object *json = NULL;
12781
12782 if (json_array)
12783 json = json_object_new_object();
019386c2 12784
d62a17ae 12785 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12786 char warning_msg[50];
12787
12788 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12789 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12790 safi);
6c9d22e2
PG
12791
12792 if (!json)
893cccd0
PG
12793 vty_out(vty, "%s\n", warning_msg);
12794 else
9ab0cf58 12795 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12796
893cccd0
PG
12797 ret = CMD_WARNING;
12798 goto end_table_stats;
d62a17ae 12799 }
019386c2 12800
893cccd0 12801 if (!json)
5290ceab
DA
12802 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12803 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12804 else
12805 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12806
d62a17ae 12807 /* labeled-unicast routes live in the unicast table */
12808 if (safi == SAFI_LABELED_UNICAST)
12809 safi = SAFI_UNICAST;
019386c2 12810
d62a17ae 12811 memset(&ts, 0, sizeof(ts));
12812 ts.table = bgp->rib[afi][safi];
12813 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12814
d62a17ae 12815 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12816 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12817 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12818 continue;
12819
12820 switch (i) {
d62a17ae 12821 case BGP_STATS_ASPATH_TOTHOPS:
12822 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12823 if (!json) {
9ab0cf58
PG
12824 snprintf(
12825 temp_buf, sizeof(temp_buf), "%12.2f",
12826 ts.counts[i]
12827 ? (float)ts.counts[i]
12828 / (float)ts.counts
12829 [BGP_STATS_ASPATH_COUNT]
12830 : 0);
893cccd0 12831 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12832 table_stats_strs[i]
12833 [TABLE_STATS_IDX_VTY],
893cccd0 12834 temp_buf);
9ab0cf58
PG
12835 } else {
12836 json_object_double_add(
12837 json,
12838 table_stats_strs[i]
12839 [TABLE_STATS_IDX_JSON],
12840 ts.counts[i]
12841 ? (double)ts.counts[i]
12842 / (double)ts.counts
d62a17ae 12843 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12844 : 0);
12845 }
d62a17ae 12846 break;
12847 case BGP_STATS_TOTPLEN:
6c9d22e2 12848 if (!json) {
9ab0cf58
PG
12849 snprintf(
12850 temp_buf, sizeof(temp_buf), "%12.2f",
12851 ts.counts[i]
12852 ? (float)ts.counts[i]
12853 / (float)ts.counts
12854 [BGP_STATS_PREFIXES]
12855 : 0);
893cccd0 12856 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12857 table_stats_strs[i]
12858 [TABLE_STATS_IDX_VTY],
893cccd0 12859 temp_buf);
9ab0cf58
PG
12860 } else {
12861 json_object_double_add(
12862 json,
12863 table_stats_strs[i]
12864 [TABLE_STATS_IDX_JSON],
12865 ts.counts[i]
12866 ? (double)ts.counts[i]
12867 / (double)ts.counts
d62a17ae 12868 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12869 : 0);
12870 }
d62a17ae 12871 break;
12872 case BGP_STATS_SPACE:
6c9d22e2
PG
12873 if (!json) {
12874 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12875 ts.total_space);
893cccd0 12876 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12877 table_stats_strs[i]
12878 [TABLE_STATS_IDX_VTY],
893cccd0 12879 temp_buf);
9ab0cf58
PG
12880 } else {
12881 json_object_double_add(
12882 json,
12883 table_stats_strs[i]
12884 [TABLE_STATS_IDX_JSON],
12885 (double)ts.total_space);
12886 }
8d0ab76d 12887 if (afi == AFI_IP6) {
6c9d22e2
PG
12888 if (!json) {
12889 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12890 "%12g",
12891 ts.total_space
12892 * pow(2.0, -128 + 32));
6c9d22e2
PG
12893 vty_out(vty, "%30s: %s\n",
12894 "/32 equivalent %s\n",
12895 temp_buf);
9ab0cf58
PG
12896 } else {
12897 json_object_double_add(
12898 json, "/32equivalent",
12899 (double)(ts.total_space
12900 * pow(2.0,
12901 -128 + 32)));
12902 }
6c9d22e2
PG
12903 if (!json) {
12904 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12905 "%12g",
12906 ts.total_space
12907 * pow(2.0, -128 + 48));
6c9d22e2
PG
12908 vty_out(vty, "%30s: %s\n",
12909 "/48 equivalent %s\n",
12910 temp_buf);
9ab0cf58
PG
12911 } else {
12912 json_object_double_add(
12913 json, "/48equivalent",
12914 (double)(ts.total_space
12915 * pow(2.0,
12916 -128 + 48)));
12917 }
8d0ab76d 12918 } else {
6c9d22e2
PG
12919 if (!json) {
12920 snprintf(temp_buf, sizeof(temp_buf),
12921 "%12.2f",
9ab0cf58
PG
12922 ts.total_space * 100.
12923 * pow(2.0, -32));
6c9d22e2 12924 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12925 "% announced ", temp_buf);
12926 } else {
12927 json_object_double_add(
12928 json, "%announced",
12929 (double)(ts.total_space * 100.
12930 * pow(2.0, -32)));
12931 }
6c9d22e2
PG
12932 if (!json) {
12933 snprintf(temp_buf, sizeof(temp_buf),
12934 "%12.2f",
9ab0cf58
PG
12935 ts.total_space
12936 * pow(2.0, -32 + 8));
6c9d22e2
PG
12937 vty_out(vty, "%30s: %s\n",
12938 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12939 } else {
12940 json_object_double_add(
12941 json, "/8equivalent",
12942 (double)(ts.total_space
12943 * pow(2.0, -32 + 8)));
12944 }
6c9d22e2
PG
12945 if (!json) {
12946 snprintf(temp_buf, sizeof(temp_buf),
12947 "%12.2f",
9ab0cf58
PG
12948 ts.total_space
12949 * pow(2.0, -32 + 24));
6c9d22e2 12950 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12951 "/24 equivalent ", temp_buf);
12952 } else {
12953 json_object_double_add(
12954 json, "/24equivalent",
12955 (double)(ts.total_space
12956 * pow(2.0, -32 + 24)));
12957 }
8d0ab76d 12958 }
d62a17ae 12959 break;
12960 default:
6c9d22e2
PG
12961 if (!json) {
12962 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12963 ts.counts[i]);
893cccd0 12964 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12965 table_stats_strs[i]
12966 [TABLE_STATS_IDX_VTY],
12967 temp_buf);
12968 } else {
12969 json_object_int_add(
12970 json,
12971 table_stats_strs[i]
12972 [TABLE_STATS_IDX_JSON],
12973 ts.counts[i]);
12974 }
d62a17ae 12975 }
893cccd0
PG
12976 if (!json)
12977 vty_out(vty, "\n");
d62a17ae 12978 }
9ab0cf58 12979end_table_stats:
6c9d22e2
PG
12980 if (json)
12981 json_object_array_add(json_array, json);
893cccd0 12982 return ret;
d62a17ae 12983}
12984
71f1613a
DA
12985static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12986 safi_t safi, struct json_object *json_array)
12987{
12988 if (!bgp) {
12989 bgp_table_stats_all(vty, afi, safi, json_array);
12990 return CMD_SUCCESS;
12991 }
12992
12993 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12994}
12995
d62a17ae 12996enum bgp_pcounts {
12997 PCOUNT_ADJ_IN = 0,
12998 PCOUNT_DAMPED,
12999 PCOUNT_REMOVED,
13000 PCOUNT_HISTORY,
13001 PCOUNT_STALE,
13002 PCOUNT_VALID,
13003 PCOUNT_ALL,
13004 PCOUNT_COUNTED,
7e3d9632 13005 PCOUNT_BPATH_SELECTED,
d62a17ae 13006 PCOUNT_PFCNT, /* the figure we display to users */
13007 PCOUNT_MAX,
a636c635 13008};
718e3744 13009
2b64873d 13010static const char *const pcount_strs[] = {
9d303b37
DL
13011 [PCOUNT_ADJ_IN] = "Adj-in",
13012 [PCOUNT_DAMPED] = "Damped",
13013 [PCOUNT_REMOVED] = "Removed",
13014 [PCOUNT_HISTORY] = "History",
13015 [PCOUNT_STALE] = "Stale",
13016 [PCOUNT_VALID] = "Valid",
13017 [PCOUNT_ALL] = "All RIB",
13018 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13019 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13020 [PCOUNT_PFCNT] = "Useable",
13021 [PCOUNT_MAX] = NULL,
a636c635 13022};
718e3744 13023
d62a17ae 13024struct peer_pcounts {
13025 unsigned int count[PCOUNT_MAX];
13026 const struct peer *peer;
13027 const struct bgp_table *table;
54317cba 13028 safi_t safi;
a636c635 13029};
47fc97cc 13030
9bcb3eef 13031static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13032{
54317cba
JW
13033 const struct bgp_adj_in *ain;
13034 const struct bgp_path_info *pi;
d62a17ae 13035 const struct peer *peer = pc->peer;
13036
54317cba
JW
13037 for (ain = rn->adj_in; ain; ain = ain->next)
13038 if (ain->peer == peer)
13039 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13040
9bcb3eef 13041 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13042
54317cba
JW
13043 if (pi->peer != peer)
13044 continue;
d62a17ae 13045
54317cba 13046 pc->count[PCOUNT_ALL]++;
d62a17ae 13047
54317cba
JW
13048 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13049 pc->count[PCOUNT_DAMPED]++;
13050 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13051 pc->count[PCOUNT_HISTORY]++;
13052 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13053 pc->count[PCOUNT_REMOVED]++;
13054 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13055 pc->count[PCOUNT_STALE]++;
13056 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13057 pc->count[PCOUNT_VALID]++;
13058 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13059 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13060 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13061 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13062
13063 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13064 pc->count[PCOUNT_COUNTED]++;
13065 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13066 flog_err(
13067 EC_LIB_DEVELOPMENT,
13068 "Attempting to count but flags say it is unusable");
13069 } else {
40381db7 13070 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13071 flog_err(
13072 EC_LIB_DEVELOPMENT,
13073 "Not counted but flags say we should");
d62a17ae 13074 }
13075 }
54317cba
JW
13076}
13077
13078static int bgp_peer_count_walker(struct thread *t)
13079{
9bcb3eef 13080 struct bgp_dest *rn, *rm;
54317cba
JW
13081 const struct bgp_table *table;
13082 struct peer_pcounts *pc = THREAD_ARG(t);
13083
13084 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13085 || pc->safi == SAFI_EVPN) {
13086 /* Special handling for 2-level routing tables. */
13087 for (rn = bgp_table_top(pc->table); rn;
13088 rn = bgp_route_next(rn)) {
9bcb3eef 13089 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13090 if (table != NULL)
13091 for (rm = bgp_table_top(table); rm;
13092 rm = bgp_route_next(rm))
13093 bgp_peer_count_proc(rm, pc);
13094 }
13095 } else
13096 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13097 bgp_peer_count_proc(rn, pc);
13098
d62a17ae 13099 return 0;
718e3744 13100}
13101
d62a17ae 13102static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13103 safi_t safi, bool use_json)
856ca177 13104{
d62a17ae 13105 struct peer_pcounts pcounts = {.peer = peer};
13106 unsigned int i;
13107 json_object *json = NULL;
13108 json_object *json_loop = NULL;
856ca177 13109
d62a17ae 13110 if (use_json) {
13111 json = json_object_new_object();
13112 json_loop = json_object_new_object();
13113 }
718e3744 13114
d62a17ae 13115 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13116 || !peer->bgp->rib[afi][safi]) {
13117 if (use_json) {
13118 json_object_string_add(
13119 json, "warning",
13120 "No such neighbor or address family");
13121 vty_out(vty, "%s\n", json_object_to_json_string(json));
13122 json_object_free(json);
d5f20468 13123 json_object_free(json_loop);
d62a17ae 13124 } else
13125 vty_out(vty, "%% No such neighbor or address family\n");
13126
13127 return CMD_WARNING;
13128 }
2a71e9ce 13129
d62a17ae 13130 memset(&pcounts, 0, sizeof(pcounts));
13131 pcounts.peer = peer;
13132 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13133 pcounts.safi = safi;
d62a17ae 13134
13135 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13136 * stats for the thread-walk (i.e. ensure this can't be blamed on
13137 * on just vty_read()).
13138 */
d62a17ae 13139 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13140
13141 if (use_json) {
13142 json_object_string_add(json, "prefixCountsFor", peer->host);
13143 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13144 get_afi_safi_str(afi, safi, true));
d62a17ae 13145 json_object_int_add(json, "pfxCounter",
13146 peer->pcount[afi][safi]);
13147
13148 for (i = 0; i < PCOUNT_MAX; i++)
13149 json_object_int_add(json_loop, pcount_strs[i],
13150 pcounts.count[i]);
13151
13152 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13153
13154 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13155 json_object_string_add(json, "pfxctDriftFor",
13156 peer->host);
13157 json_object_string_add(
13158 json, "recommended",
13159 "Please report this bug, with the above command output");
13160 }
75eeda93 13161 vty_json(vty, json);
d62a17ae 13162 } else {
13163
13164 if (peer->hostname
892fedb6 13165 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13166 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13167 peer->hostname, peer->host,
5cb5f4d0 13168 get_afi_safi_str(afi, safi, false));
d62a17ae 13169 } else {
13170 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13171 get_afi_safi_str(afi, safi, false));
d62a17ae 13172 }
13173
6cde4b45 13174 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13175 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13176
13177 for (i = 0; i < PCOUNT_MAX; i++)
13178 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13179 pcounts.count[i]);
13180
13181 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13182 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13183 vty_out(vty,
13184 "Please report this bug, with the above command output\n");
13185 }
13186 }
13187
13188 return CMD_SUCCESS;
718e3744 13189}
13190
a636c635
DW
13191DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13192 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13193 "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 13194 SHOW_STR
13195 IP_STR
13196 BGP_STR
8386ac43 13197 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13198 BGP_AFI_HELP_STR
13199 BGP_SAFI_HELP_STR
0b16f239
DS
13200 "Detailed information on TCP and BGP neighbor connections\n"
13201 "Neighbor to display information about\n"
13202 "Neighbor to display information about\n"
91d37724 13203 "Neighbor on BGP configured interface\n"
a636c635 13204 "Display detailed prefix count information\n"
9973d184 13205 JSON_STR)
0b16f239 13206{
d62a17ae 13207 afi_t afi = AFI_IP6;
13208 safi_t safi = SAFI_UNICAST;
13209 struct peer *peer;
13210 int idx = 0;
13211 struct bgp *bgp = NULL;
9f049418
DS
13212 bool uj = use_json(argc, argv);
13213
13214 if (uj)
13215 argc--;
856ca177 13216
d62a17ae 13217 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13218 &bgp, uj);
d62a17ae 13219 if (!idx)
13220 return CMD_WARNING;
0b16f239 13221
d62a17ae 13222 argv_find(argv, argc, "neighbors", &idx);
13223 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13224 if (!peer)
13225 return CMD_WARNING;
bb46e94f 13226
29c8d9da 13227 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13228}
0b16f239 13229
d6902373
PG
13230#ifdef KEEP_OLD_VPN_COMMANDS
13231DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13232 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13233 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13234 SHOW_STR
13235 IP_STR
13236 BGP_STR
d6902373 13237 BGP_VPNVX_HELP_STR
91d37724 13238 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13239 "Detailed information on TCP and BGP neighbor connections\n"
13240 "Neighbor to display information about\n"
13241 "Neighbor to display information about\n"
91d37724 13242 "Neighbor on BGP configured interface\n"
a636c635 13243 "Display detailed prefix count information\n"
9973d184 13244 JSON_STR)
a636c635 13245{
d62a17ae 13246 int idx_peer = 6;
13247 struct peer *peer;
9f049418 13248 bool uj = use_json(argc, argv);
a636c635 13249
d62a17ae 13250 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13251 if (!peer)
13252 return CMD_WARNING;
13253
13254 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13255}
13256
d6902373
PG
13257DEFUN (show_ip_bgp_vpn_all_route_prefix,
13258 show_ip_bgp_vpn_all_route_prefix_cmd,
13259 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13260 SHOW_STR
13261 IP_STR
13262 BGP_STR
d6902373 13263 BGP_VPNVX_HELP_STR
91d37724
QY
13264 "Display information about all VPNv4 NLRIs\n"
13265 "Network in the BGP routing table to display\n"
3a2d747c 13266 "Network in the BGP routing table to display\n"
9973d184 13267 JSON_STR)
91d37724 13268{
d62a17ae 13269 int idx = 0;
13270 char *network = NULL;
13271 struct bgp *bgp = bgp_get_default();
13272 if (!bgp) {
13273 vty_out(vty, "Can't find default instance\n");
13274 return CMD_WARNING;
13275 }
87e34b58 13276
d62a17ae 13277 if (argv_find(argv, argc, "A.B.C.D", &idx))
13278 network = argv[idx]->arg;
13279 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13280 network = argv[idx]->arg;
13281 else {
13282 vty_out(vty, "Unable to figure out Network\n");
13283 return CMD_WARNING;
13284 }
87e34b58 13285
d62a17ae 13286 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13287 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13288 use_json(argc, argv));
91d37724 13289}
d6902373 13290#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13291
44c69747
LK
13292DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13293 show_bgp_l2vpn_evpn_route_prefix_cmd,
13294 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13295 SHOW_STR
4c63a661
PG
13296 BGP_STR
13297 L2VPN_HELP_STR
13298 EVPN_HELP_STR
44c69747
LK
13299 "Network in the BGP routing table to display\n"
13300 "Network in the BGP routing table to display\n"
4c63a661
PG
13301 "Network in the BGP routing table to display\n"
13302 "Network in the BGP routing table to display\n"
13303 JSON_STR)
13304{
d62a17ae 13305 int idx = 0;
13306 char *network = NULL;
44c69747 13307 int prefix_check = 0;
a636c635 13308
44c69747
LK
13309 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13310 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13311 network = argv[idx]->arg;
44c69747 13312 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13313 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13314 network = argv[idx]->arg;
44c69747
LK
13315 prefix_check = 1;
13316 } else {
d62a17ae 13317 vty_out(vty, "Unable to figure out Network\n");
13318 return CMD_WARNING;
13319 }
44c69747
LK
13320 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13321 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13322 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13323}
13324
2f9bc755
DS
13325static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13326 struct bgp_table *table, int *header1,
13327 int *header2, json_object *json,
13328 json_object *json_scode,
13329 json_object *json_ocode, bool wide)
13330{
13331 uint64_t version = table ? table->version : 0;
13332
13333 if (*header1) {
13334 if (json) {
13335 json_object_int_add(json, "bgpTableVersion", version);
c949c771
DA
13336 json_object_string_addf(json, "bgpLocalRouterId",
13337 "%pI4", &bgp->router_id);
2f9bc755
DS
13338 json_object_int_add(json, "defaultLocPrf",
13339 bgp->default_local_pref);
13340 json_object_int_add(json, "localAS", bgp->as);
13341 json_object_object_add(json, "bgpStatusCodes",
13342 json_scode);
13343 json_object_object_add(json, "bgpOriginCodes",
13344 json_ocode);
13345 } else {
13346 vty_out(vty,
23d0a753
DA
13347 "BGP table version is %" PRIu64
13348 ", local router ID is %pI4, vrf id ",
13349 version, &bgp->router_id);
2f9bc755
DS
13350 if (bgp->vrf_id == VRF_UNKNOWN)
13351 vty_out(vty, "%s", VRFID_NONE_STR);
13352 else
13353 vty_out(vty, "%u", bgp->vrf_id);
13354 vty_out(vty, "\n");
13355 vty_out(vty, "Default local pref %u, ",
13356 bgp->default_local_pref);
13357 vty_out(vty, "local AS %u\n", bgp->as);
13358 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13359 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13360 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13361 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13362 }
13363 *header1 = 0;
13364 }
13365 if (*header2) {
13366 if (!json)
13367 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13368 : BGP_SHOW_HEADER));
13369 *header2 = 0;
13370 }
13371}
13372
d9478df0
TA
13373static void
13374show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13375 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13376 const char *rmap_name, json_object *json, json_object *json_ar,
13377 json_object *json_scode, json_object *json_ocode,
96c81f66 13378 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13379 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13380{
d62a17ae 13381 struct bgp_adj_in *ain;
13382 struct bgp_adj_out *adj;
9bcb3eef 13383 struct bgp_dest *dest;
d62a17ae 13384 struct bgp *bgp;
d62a17ae 13385 struct attr attr;
13386 int ret;
13387 struct update_subgroup *subgrp;
d62a17ae 13388 struct peer_af *paf;
f99def61 13389 bool route_filtered;
96f3485c
MK
13390 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13391 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13392 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13393 || (safi == SAFI_EVPN))
13394 ? true
13395 : false;
a636c635 13396
d62a17ae 13397 bgp = peer->bgp;
a636c635 13398
d62a17ae 13399 subgrp = peer_subgroup(peer, afi, safi);
13400
6392aaa6 13401 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13402 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13403 if (use_json) {
13404 json_object_int_add(json, "bgpTableVersion",
13405 table->version);
c949c771
DA
13406 json_object_string_addf(json, "bgpLocalRouterId",
13407 "%pI4", &bgp->router_id);
01eced22
AD
13408 json_object_int_add(json, "defaultLocPrf",
13409 bgp->default_local_pref);
13410 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13411 json_object_object_add(json, "bgpStatusCodes",
13412 json_scode);
13413 json_object_object_add(json, "bgpOriginCodes",
13414 json_ocode);
07d0c4ed
DA
13415 json_object_string_add(
13416 json, "bgpOriginatingDefaultNetwork",
13417 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13418 } else {
23d0a753
DA
13419 vty_out(vty,
13420 "BGP table version is %" PRIu64
13421 ", local router ID is %pI4, vrf id ",
13422 table->version, &bgp->router_id);
9df8b37c
PZ
13423 if (bgp->vrf_id == VRF_UNKNOWN)
13424 vty_out(vty, "%s", VRFID_NONE_STR);
13425 else
13426 vty_out(vty, "%u", bgp->vrf_id);
13427 vty_out(vty, "\n");
01eced22
AD
13428 vty_out(vty, "Default local pref %u, ",
13429 bgp->default_local_pref);
13430 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13431 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13432 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13433 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13434 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13435
07d0c4ed
DA
13436 vty_out(vty, "Originating default network %s\n\n",
13437 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13438 }
d9478df0 13439 *header1 = 0;
d62a17ae 13440 }
a636c635 13441
9bcb3eef 13442 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13443 if (type == bgp_show_adj_route_received
13444 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13445 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13446 if (ain->peer != peer)
ea47320b 13447 continue;
6392aaa6 13448
d9478df0
TA
13449 show_adj_route_header(vty, bgp, table, header1,
13450 header2, json, json_scode,
13451 json_ocode, wide);
13452
13453 if ((safi == SAFI_MPLS_VPN)
13454 || (safi == SAFI_ENCAP)
13455 || (safi == SAFI_EVPN)) {
13456 if (use_json)
13457 json_object_string_add(
13458 json_ar, "rd", rd_str);
13459 else if (show_rd && rd_str) {
13460 vty_out(vty,
13461 "Route Distinguisher: %s\n",
13462 rd_str);
13463 show_rd = false;
13464 }
13465 }
6392aaa6 13466
6f4f49b2 13467 attr = *ain->attr;
f99def61
AD
13468 route_filtered = false;
13469
13470 /* Filter prefix using distribute list,
13471 * filter list or prefix list
13472 */
b54892e0 13473 const struct prefix *rn_p =
9bcb3eef 13474 bgp_dest_get_prefix(dest);
b54892e0
DS
13475 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13476 safi))
13477 == FILTER_DENY)
f99def61
AD
13478 route_filtered = true;
13479
13480 /* Filter prefix using route-map */
b54892e0
DS
13481 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13482 safi, rmap_name, NULL,
13483 0, NULL);
6392aaa6 13484
13c8e163
AD
13485 if (type == bgp_show_adj_route_filtered &&
13486 !route_filtered && ret != RMAP_DENY) {
b755861b 13487 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13488 continue;
d62a17ae 13489 }
6392aaa6 13490
d9478df0
TA
13491 if (type == bgp_show_adj_route_received
13492 && (route_filtered || ret == RMAP_DENY))
13493 (*filtered_count)++;
6392aaa6 13494
7d3cae70 13495 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13496 use_json, json_ar, wide);
b755861b 13497 bgp_attr_undup(&attr, ain->attr);
d9478df0 13498 (*output_count)++;
d62a17ae 13499 }
6392aaa6 13500 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13501 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13502 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13503 if (paf->peer != peer || !adj->attr)
924c3f6a 13504 continue;
d62a17ae 13505
d9478df0
TA
13506 show_adj_route_header(vty, bgp, table,
13507 header1, header2,
13508 json, json_scode,
13509 json_ocode, wide);
d62a17ae 13510
b54892e0 13511 const struct prefix *rn_p =
9bcb3eef 13512 bgp_dest_get_prefix(dest);
b54892e0 13513
6f4f49b2 13514 attr = *adj->attr;
b755861b 13515 ret = bgp_output_modifier(
b54892e0 13516 peer, rn_p, &attr, afi, safi,
b755861b 13517 rmap_name);
f46d8e1e 13518
b755861b 13519 if (ret != RMAP_DENY) {
d9478df0
TA
13520 if ((safi == SAFI_MPLS_VPN)
13521 || (safi == SAFI_ENCAP)
13522 || (safi == SAFI_EVPN)) {
13523 if (use_json)
13524 json_object_string_add(
13525 json_ar,
13526 "rd",
13527 rd_str);
13528 else if (show_rd
13529 && rd_str) {
13530 vty_out(vty,
13531 "Route Distinguisher: %s\n",
13532 rd_str);
13533 show_rd = false;
13534 }
13535 }
b54892e0 13536 route_vty_out_tmp(
7d3cae70
DA
13537 vty, dest, rn_p, &attr,
13538 safi, use_json, json_ar,
ae248832 13539 wide);
d9478df0 13540 (*output_count)++;
b755861b 13541 } else {
d9478df0 13542 (*filtered_count)++;
a2addae8 13543 }
b755861b
PM
13544
13545 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13546 }
f20ce998
DS
13547 } else if (type == bgp_show_adj_route_bestpath) {
13548 struct bgp_path_info *pi;
13549
d9478df0
TA
13550 show_adj_route_header(vty, bgp, table, header1, header2,
13551 json, json_scode, json_ocode,
13552 wide);
f20ce998
DS
13553
13554 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13555 pi = pi->next) {
13556 if (pi->peer != peer)
13557 continue;
13558
13559 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13560 continue;
13561
7d3cae70 13562 route_vty_out_tmp(vty, dest,
f20ce998
DS
13563 bgp_dest_get_prefix(dest),
13564 pi->attr, safi, use_json,
13565 json_ar, wide);
d9478df0 13566 (*output_count)++;
f20ce998 13567 }
d62a17ae 13568 }
13569 }
a636c635 13570}
2a71e9ce 13571
d62a17ae 13572static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13573 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13574 const char *rmap_name, uint16_t show_flags)
0b16f239 13575{
d9478df0
TA
13576 struct bgp *bgp;
13577 struct bgp_table *table;
d62a17ae 13578 json_object *json = NULL;
d9478df0
TA
13579 json_object *json_scode = NULL;
13580 json_object *json_ocode = NULL;
13581 json_object *json_ar = NULL;
96f3485c 13582 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13583
d9478df0
TA
13584 /* Init BGP headers here so they're only displayed once
13585 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13586 */
13587 int header1 = 1;
13588 int header2 = 1;
13589
13590 /*
13591 * Initialize variables for each RD
13592 * All prefixes under an RD is aggregated within "json_routes"
13593 */
13594 char rd_str[BUFSIZ] = {0};
13595 json_object *json_routes = NULL;
13596
13597
13598 /* For 2-tier tables, prefix counts need to be
13599 * maintained across multiple runs of show_adj_route()
13600 */
13601 unsigned long output_count_per_rd;
13602 unsigned long filtered_count_per_rd;
13603 unsigned long output_count = 0;
13604 unsigned long filtered_count = 0;
13605
13606 if (use_json) {
d62a17ae 13607 json = json_object_new_object();
d9478df0
TA
13608 json_ar = json_object_new_object();
13609 json_scode = json_object_new_object();
13610 json_ocode = json_object_new_object();
13611
13612 json_object_string_add(json_scode, "suppressed", "s");
13613 json_object_string_add(json_scode, "damped", "d");
13614 json_object_string_add(json_scode, "history", "h");
13615 json_object_string_add(json_scode, "valid", "*");
13616 json_object_string_add(json_scode, "best", ">");
13617 json_object_string_add(json_scode, "multipath", "=");
13618 json_object_string_add(json_scode, "internal", "i");
13619 json_object_string_add(json_scode, "ribFailure", "r");
13620 json_object_string_add(json_scode, "stale", "S");
13621 json_object_string_add(json_scode, "removed", "R");
13622
13623 json_object_string_add(json_ocode, "igp", "i");
13624 json_object_string_add(json_ocode, "egp", "e");
13625 json_object_string_add(json_ocode, "incomplete", "?");
13626 }
0b16f239 13627
d62a17ae 13628 if (!peer || !peer->afc[afi][safi]) {
13629 if (use_json) {
13630 json_object_string_add(
13631 json, "warning",
13632 "No such neighbor or address family");
13633 vty_out(vty, "%s\n", json_object_to_json_string(json));
13634 json_object_free(json);
690c3134
MW
13635 json_object_free(json_ar);
13636 json_object_free(json_scode);
13637 json_object_free(json_ocode);
d62a17ae 13638 } else
13639 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13640
d62a17ae 13641 return CMD_WARNING;
13642 }
13643
6392aaa6
PM
13644 if ((type == bgp_show_adj_route_received
13645 || type == bgp_show_adj_route_filtered)
d62a17ae 13646 && !CHECK_FLAG(peer->af_flags[afi][safi],
13647 PEER_FLAG_SOFT_RECONFIG)) {
13648 if (use_json) {
13649 json_object_string_add(
13650 json, "warning",
13651 "Inbound soft reconfiguration not enabled");
13652 vty_out(vty, "%s\n", json_object_to_json_string(json));
13653 json_object_free(json);
690c3134
MW
13654 json_object_free(json_ar);
13655 json_object_free(json_scode);
13656 json_object_free(json_ocode);
d62a17ae 13657 } else
13658 vty_out(vty,
13659 "%% Inbound soft reconfiguration not enabled\n");
13660
13661 return CMD_WARNING;
13662 }
0b16f239 13663
d9478df0
TA
13664 bgp = peer->bgp;
13665
13666 /* labeled-unicast routes live in the unicast table */
13667 if (safi == SAFI_LABELED_UNICAST)
13668 table = bgp->rib[afi][SAFI_UNICAST];
13669 else
13670 table = bgp->rib[afi][safi];
13671
13672 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13673 || (safi == SAFI_EVPN)) {
13674
13675 struct bgp_dest *dest;
13676
13677 for (dest = bgp_table_top(table); dest;
13678 dest = bgp_route_next(dest)) {
13679 table = bgp_dest_get_bgp_table_info(dest);
13680 if (!table)
13681 continue;
13682
13683 output_count_per_rd = 0;
13684 filtered_count_per_rd = 0;
13685
13686 if (use_json)
13687 json_routes = json_object_new_object();
13688
13689 const struct prefix_rd *prd;
13690 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13691 dest);
13692
13693 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13694
13695 show_adj_route(vty, peer, table, afi, safi, type,
13696 rmap_name, json, json_routes, json_scode,
13697 json_ocode, show_flags, &header1,
13698 &header2, rd_str, &output_count_per_rd,
13699 &filtered_count_per_rd);
13700
13701 /* Don't include an empty RD in the output! */
13702 if (json_routes && (output_count_per_rd > 0))
13703 json_object_object_add(json_ar, rd_str,
13704 json_routes);
13705
13706 output_count += output_count_per_rd;
13707 filtered_count += filtered_count_per_rd;
13708 }
13709 } else
13710 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13711 json, json_ar, json_scode, json_ocode,
13712 show_flags, &header1, &header2, rd_str,
13713 &output_count, &filtered_count);
13714
13715 if (use_json) {
13716 json_object_object_add(json, "advertisedRoutes", json_ar);
13717 json_object_int_add(json, "totalPrefixCounter", output_count);
13718 json_object_int_add(json, "filteredPrefixCounter",
13719 filtered_count);
13720
690c3134
MW
13721 /*
13722 * These fields only give up ownership to `json` when `header1`
13723 * is used (set to zero). See code in `show_adj_route` and
13724 * `show_adj_route_header`.
13725 */
13726 if (header1 == 1) {
d9478df0
TA
13727 json_object_free(json_scode);
13728 json_object_free(json_ocode);
13729 }
13730
75eeda93 13731 vty_json(vty, json);
d9478df0
TA
13732 } else if (output_count > 0) {
13733 if (filtered_count > 0)
13734 vty_out(vty,
13735 "\nTotal number of prefixes %ld (%ld filtered)\n",
13736 output_count, filtered_count);
13737 else
13738 vty_out(vty, "\nTotal number of prefixes %ld\n",
13739 output_count);
13740 }
0b16f239 13741
d62a17ae 13742 return CMD_SUCCESS;
a636c635 13743}
50ef26d4 13744
f20ce998
DS
13745DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13746 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13747 "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]",
13748 SHOW_STR
13749 IP_STR
13750 BGP_STR
13751 BGP_INSTANCE_HELP_STR
13752 BGP_AFI_HELP_STR
13753 BGP_SAFI_WITH_LABEL_HELP_STR
13754 "Detailed information on TCP and BGP neighbor connections\n"
13755 "Neighbor to display information about\n"
13756 "Neighbor to display information about\n"
13757 "Neighbor on BGP configured interface\n"
13758 "Display the routes selected by best path\n"
13759 JSON_STR
13760 "Increase table width for longer prefixes\n")
13761{
13762 afi_t afi = AFI_IP6;
13763 safi_t safi = SAFI_UNICAST;
13764 char *rmap_name = NULL;
13765 char *peerstr = NULL;
13766 struct bgp *bgp = NULL;
13767 struct peer *peer;
13768 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13769 int idx = 0;
96c81f66 13770 uint16_t show_flags = 0;
96f3485c
MK
13771
13772 if (uj)
13773 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13774
13775 if (wide)
13776 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13777
13778 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13779 &bgp, uj);
13780
13781 if (!idx)
13782 return CMD_WARNING;
13783
13784 argv_find(argv, argc, "neighbors", &idx);
13785 peerstr = argv[++idx]->arg;
13786
13787 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13788 if (!peer)
13789 return CMD_WARNING;
13790
96f3485c
MK
13791 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13792 show_flags);
f20ce998
DS
13793}
13794
ae248832 13795DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13796 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13797 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
718e3744 13798 SHOW_STR
13799 IP_STR
13800 BGP_STR
a636c635 13801 BGP_INSTANCE_HELP_STR
7395a2c9 13802 BGP_AFI_HELP_STR
4dd6177e 13803 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13804 "Display the entries for all address families\n"
718e3744 13805 "Detailed information on TCP and BGP neighbor connections\n"
13806 "Neighbor to display information about\n"
13807 "Neighbor to display information about\n"
91d37724 13808 "Neighbor on BGP configured interface\n"
a636c635 13809 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13810 "Display the received routes from neighbor\n"
13811 "Display the filtered routes received from neighbor\n"
a636c635
DW
13812 "Route-map to modify the attributes\n"
13813 "Name of the route map\n"
ae248832
MK
13814 JSON_STR
13815 "Increase table width for longer prefixes\n")
718e3744 13816{
d62a17ae 13817 afi_t afi = AFI_IP6;
13818 safi_t safi = SAFI_UNICAST;
13819 char *rmap_name = NULL;
13820 char *peerstr = NULL;
d62a17ae 13821 struct bgp *bgp = NULL;
13822 struct peer *peer;
6392aaa6 13823 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13824 int idx = 0;
96f3485c 13825 bool first = true;
96c81f66 13826 uint16_t show_flags = 0;
6392aaa6 13827
96f3485c 13828 if (uj) {
d62a17ae 13829 argc--;
96f3485c
MK
13830 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13831 }
13832
13833 if (all) {
13834 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13835 if (argv_find(argv, argc, "ipv4", &idx))
13836 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13837
13838 if (argv_find(argv, argc, "ipv6", &idx))
13839 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13840 }
13841
13842 if (wide)
13843 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13844
9f049418
DS
13845 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13846 &bgp, uj);
13847 if (!idx)
13848 return CMD_WARNING;
13849
d62a17ae 13850 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13851 argv_find(argv, argc, "neighbors", &idx);
13852 peerstr = argv[++idx]->arg;
8c3deaae 13853
d62a17ae 13854 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13855 if (!peer)
13856 return CMD_WARNING;
856ca177 13857
d62a17ae 13858 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13859 type = bgp_show_adj_route_advertised;
13860 else if (argv_find(argv, argc, "received-routes", &idx))
13861 type = bgp_show_adj_route_received;
13862 else if (argv_find(argv, argc, "filtered-routes", &idx))
13863 type = bgp_show_adj_route_filtered;
13864
d62a17ae 13865 if (argv_find(argv, argc, "route-map", &idx))
13866 rmap_name = argv[++idx]->arg;
95cbbd2a 13867
96f3485c
MK
13868 if (!all)
13869 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13870 show_flags);
13871 if (uj)
13872 vty_out(vty, "{\n");
13873
13874 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13875 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13876 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13877 : AFI_IP6;
13878 FOREACH_SAFI (safi) {
96f3485c
MK
13879 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13880 continue;
13881
13882 if (uj) {
13883 if (first)
13884 first = false;
13885 else
13886 vty_out(vty, ",\n");
13887 vty_out(vty, "\"%s\":",
13888 get_afi_safi_str(afi, safi, true));
13889 } else
13890 vty_out(vty, "\nFor address family: %s\n",
13891 get_afi_safi_str(afi, safi, false));
13892
13893 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13894 show_flags);
13895 }
13896 } else {
13897 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13898 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13899 continue;
13900
13901 if (uj) {
13902 if (first)
13903 first = false;
13904 else
13905 vty_out(vty, ",\n");
13906 vty_out(vty, "\"%s\":",
13907 get_afi_safi_str(afi, safi, true));
13908 } else
13909 vty_out(vty, "\nFor address family: %s\n",
13910 get_afi_safi_str(afi, safi, false));
13911
13912 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13913 show_flags);
13914 }
13915 }
13916 if (uj)
13917 vty_out(vty, "}\n");
13918
13919 return CMD_SUCCESS;
95cbbd2a
ML
13920}
13921
718e3744 13922DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13923 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 13924 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13925 SHOW_STR
13926 IP_STR
13927 BGP_STR
d3120452 13928 BGP_INSTANCE_HELP_STR
8c3deaae
QY
13929 "Address Family\n"
13930 "Address Family\n"
718e3744 13931 "Address Family modifier\n"
13932 "Detailed information on TCP and BGP neighbor connections\n"
13933 "Neighbor to display information about\n"
13934 "Neighbor to display information about\n"
91d37724 13935 "Neighbor on BGP configured interface\n"
718e3744 13936 "Display information received from a BGP neighbor\n"
856ca177 13937 "Display the prefixlist filter\n"
9973d184 13938 JSON_STR)
718e3744 13939{
d62a17ae 13940 afi_t afi = AFI_IP6;
13941 safi_t safi = SAFI_UNICAST;
13942 char *peerstr = NULL;
d62a17ae 13943 char name[BUFSIZ];
d62a17ae 13944 struct peer *peer;
d3120452 13945 int count;
d62a17ae 13946 int idx = 0;
d3120452
IR
13947 struct bgp *bgp = NULL;
13948 bool uj = use_json(argc, argv);
13949
13950 if (uj)
13951 argc--;
13952
13953 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13954 &bgp, uj);
13955 if (!idx)
13956 return CMD_WARNING;
d62a17ae 13957
d62a17ae 13958 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13959 argv_find(argv, argc, "neighbors", &idx);
13960 peerstr = argv[++idx]->arg;
13961
d3120452
IR
13962 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13963 if (!peer)
13964 return CMD_WARNING;
718e3744 13965
4ced1a2c 13966 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13967 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13968 if (count) {
13969 if (!uj)
13970 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13971 get_afi_safi_str(afi, safi, false));
d62a17ae 13972 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13973 } else {
13974 if (uj)
13975 vty_out(vty, "{}\n");
13976 else
13977 vty_out(vty, "No functional output\n");
13978 }
718e3744 13979
d62a17ae 13980 return CMD_SUCCESS;
13981}
13982
13983static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13984 afi_t afi, safi_t safi,
9f049418 13985 enum bgp_show_type type, bool use_json)
d62a17ae 13986{
96c81f66 13987 uint16_t show_flags = 0;
96f3485c
MK
13988
13989 if (use_json)
13990 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13991
d62a17ae 13992 if (!peer || !peer->afc[afi][safi]) {
13993 if (use_json) {
13994 json_object *json_no = NULL;
13995 json_no = json_object_new_object();
13996 json_object_string_add(
13997 json_no, "warning",
13998 "No such neighbor or address family");
13999 vty_out(vty, "%s\n",
14000 json_object_to_json_string(json_no));
14001 json_object_free(json_no);
14002 } else
14003 vty_out(vty, "%% No such neighbor or address family\n");
14004 return CMD_WARNING;
14005 }
47fc97cc 14006
7daf25a3
TA
14007 /* labeled-unicast routes live in the unicast table */
14008 if (safi == SAFI_LABELED_UNICAST)
14009 safi = SAFI_UNICAST;
14010
1e2ce4f1
DS
14011 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14012 RPKI_NOT_BEING_USED);
718e3744 14013}
14014
dba3c1d3
PG
14015DEFUN (show_ip_bgp_flowspec_routes_detailed,
14016 show_ip_bgp_flowspec_routes_detailed_cmd,
14017 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14018 SHOW_STR
14019 IP_STR
14020 BGP_STR
14021 BGP_INSTANCE_HELP_STR
14022 BGP_AFI_HELP_STR
14023 "SAFI Flowspec\n"
14024 "Detailed information on flowspec entries\n"
14025 JSON_STR)
14026{
458c1475 14027 afi_t afi = AFI_IP6;
dba3c1d3
PG
14028 safi_t safi = SAFI_UNICAST;
14029 struct bgp *bgp = NULL;
14030 int idx = 0;
9f049418 14031 bool uj = use_json(argc, argv);
96c81f66 14032 uint16_t show_flags = 0;
9f049418 14033
96f3485c 14034 if (uj) {
9f049418 14035 argc--;
96f3485c
MK
14036 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14037 }
dba3c1d3
PG
14038
14039 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14040 &bgp, uj);
dba3c1d3
PG
14041 if (!idx)
14042 return CMD_WARNING;
14043
96f3485c 14044 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14045 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14046}
14047
718e3744 14048DEFUN (show_ip_bgp_neighbor_routes,
14049 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14050 "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 14051 SHOW_STR
14052 IP_STR
14053 BGP_STR
8386ac43 14054 BGP_INSTANCE_HELP_STR
4f280b15 14055 BGP_AFI_HELP_STR
4dd6177e 14056 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14057 "Detailed information on TCP and BGP neighbor connections\n"
14058 "Neighbor to display information about\n"
14059 "Neighbor to display information about\n"
91d37724 14060 "Neighbor on BGP configured interface\n"
2525cf39 14061 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14062 "Display the dampened routes received from neighbor\n"
14063 "Display routes learned from neighbor\n"
9973d184 14064 JSON_STR)
718e3744 14065{
d62a17ae 14066 char *peerstr = NULL;
14067 struct bgp *bgp = NULL;
14068 afi_t afi = AFI_IP6;
14069 safi_t safi = SAFI_UNICAST;
14070 struct peer *peer;
14071 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14072 int idx = 0;
9f049418
DS
14073 bool uj = use_json(argc, argv);
14074
14075 if (uj)
14076 argc--;
bb46e94f 14077
d62a17ae 14078 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14079 &bgp, uj);
d62a17ae 14080 if (!idx)
14081 return CMD_WARNING;
c493f2d8 14082
d62a17ae 14083 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14084 argv_find(argv, argc, "neighbors", &idx);
14085 peerstr = argv[++idx]->arg;
8c3deaae 14086
d62a17ae 14087 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14088 if (!peer)
d62a17ae 14089 return CMD_WARNING;
bb46e94f 14090
d62a17ae 14091 if (argv_find(argv, argc, "flap-statistics", &idx))
14092 sh_type = bgp_show_type_flap_neighbor;
14093 else if (argv_find(argv, argc, "dampened-routes", &idx))
14094 sh_type = bgp_show_type_damp_neighbor;
14095 else if (argv_find(argv, argc, "routes", &idx))
14096 sh_type = bgp_show_type_neighbor;
2525cf39 14097
d62a17ae 14098 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14099}
6b0655a2 14100
734b349e 14101struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14102
d62a17ae 14103struct bgp_distance {
14104 /* Distance value for the IP source prefix. */
d7c0a89a 14105 uint8_t distance;
718e3744 14106
d62a17ae 14107 /* Name of the access-list to be matched. */
14108 char *access_list;
718e3744 14109};
14110
4f280b15
LB
14111DEFUN (show_bgp_afi_vpn_rd_route,
14112 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14113 "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
14114 SHOW_STR
14115 BGP_STR
14116 BGP_AFI_HELP_STR
14117 "Address Family modifier\n"
14118 "Display information for a route distinguisher\n"
14119 "Route Distinguisher\n"
a111dd97 14120 "All Route Distinguishers\n"
7395a2c9
DS
14121 "Network in the BGP routing table to display\n"
14122 "Network in the BGP routing table to display\n"
14123 JSON_STR)
4f280b15 14124{
d62a17ae 14125 int ret;
14126 struct prefix_rd prd;
14127 afi_t afi = AFI_MAX;
14128 int idx = 0;
4f280b15 14129
ff6566f3
DS
14130 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14131 vty_out(vty, "%% Malformed Address Family\n");
14132 return CMD_WARNING;
14133 }
14134
a111dd97
TA
14135 if (!strcmp(argv[5]->arg, "all"))
14136 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14137 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14138 RPKI_NOT_BEING_USED,
14139 use_json(argc, argv));
14140
d62a17ae 14141 ret = str2prefix_rd(argv[5]->arg, &prd);
14142 if (!ret) {
14143 vty_out(vty, "%% Malformed Route Distinguisher\n");
14144 return CMD_WARNING;
14145 }
ff6566f3 14146
d62a17ae 14147 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14148 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14149 use_json(argc, argv));
4f280b15
LB
14150}
14151
d62a17ae 14152static struct bgp_distance *bgp_distance_new(void)
718e3744 14153{
d62a17ae 14154 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14155}
14156
d62a17ae 14157static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14158{
d62a17ae 14159 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14160}
14161
585f1adc
IR
14162static int bgp_distance_set(struct vty *vty, const char *distance_str,
14163 const char *ip_str, const char *access_list_str)
718e3744 14164{
d62a17ae 14165 int ret;
585f1adc
IR
14166 afi_t afi;
14167 safi_t safi;
d62a17ae 14168 struct prefix p;
585f1adc 14169 uint8_t distance;
9bcb3eef 14170 struct bgp_dest *dest;
d62a17ae 14171 struct bgp_distance *bdistance;
718e3744 14172
585f1adc
IR
14173 afi = bgp_node_afi(vty);
14174 safi = bgp_node_safi(vty);
14175
d62a17ae 14176 ret = str2prefix(ip_str, &p);
14177 if (ret == 0) {
585f1adc 14178 vty_out(vty, "Malformed prefix\n");
d62a17ae 14179 return CMD_WARNING_CONFIG_FAILED;
14180 }
718e3744 14181
585f1adc
IR
14182 distance = atoi(distance_str);
14183
d62a17ae 14184 /* Get BGP distance node. */
9bcb3eef
DS
14185 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14186 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14187 if (bdistance)
9bcb3eef 14188 bgp_dest_unlock_node(dest);
ca2e160d 14189 else {
d62a17ae 14190 bdistance = bgp_distance_new();
9bcb3eef 14191 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14192 }
718e3744 14193
d62a17ae 14194 /* Set distance value. */
14195 bdistance->distance = distance;
718e3744 14196
d62a17ae 14197 /* Reset access-list configuration. */
e1b36e13 14198 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14199 if (access_list_str)
14200 bdistance->access_list =
14201 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14202
d62a17ae 14203 return CMD_SUCCESS;
718e3744 14204}
14205
585f1adc
IR
14206static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14207 const char *ip_str, const char *access_list_str)
718e3744 14208{
d62a17ae 14209 int ret;
585f1adc
IR
14210 afi_t afi;
14211 safi_t safi;
d62a17ae 14212 struct prefix p;
585f1adc 14213 int distance;
9bcb3eef 14214 struct bgp_dest *dest;
d62a17ae 14215 struct bgp_distance *bdistance;
718e3744 14216
585f1adc
IR
14217 afi = bgp_node_afi(vty);
14218 safi = bgp_node_safi(vty);
14219
d62a17ae 14220 ret = str2prefix(ip_str, &p);
14221 if (ret == 0) {
585f1adc 14222 vty_out(vty, "Malformed prefix\n");
d62a17ae 14223 return CMD_WARNING_CONFIG_FAILED;
14224 }
718e3744 14225
9bcb3eef
DS
14226 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14227 if (!dest) {
585f1adc 14228 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14229 return CMD_WARNING_CONFIG_FAILED;
14230 }
718e3744 14231
9bcb3eef 14232 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14233 distance = atoi(distance_str);
1f9a9fff 14234
d62a17ae 14235 if (bdistance->distance != distance) {
585f1adc 14236 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14237 bgp_dest_unlock_node(dest);
d62a17ae 14238 return CMD_WARNING_CONFIG_FAILED;
14239 }
718e3744 14240
0a22ddfb 14241 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14242 bgp_distance_free(bdistance);
718e3744 14243
9bcb3eef
DS
14244 bgp_dest_set_bgp_path_info(dest, NULL);
14245 bgp_dest_unlock_node(dest);
14246 bgp_dest_unlock_node(dest);
718e3744 14247
d62a17ae 14248 return CMD_SUCCESS;
718e3744 14249}
14250
718e3744 14251/* Apply BGP information to distance method. */
b8685f9b 14252uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14253 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14254{
9bcb3eef 14255 struct bgp_dest *dest;
801bb996 14256 struct prefix q = {0};
d62a17ae 14257 struct peer *peer;
14258 struct bgp_distance *bdistance;
14259 struct access_list *alist;
14260 struct bgp_static *bgp_static;
14261
14262 if (!bgp)
14263 return 0;
14264
40381db7 14265 peer = pinfo->peer;
d62a17ae 14266
7b7d48e5
DS
14267 if (pinfo->attr->distance)
14268 return pinfo->attr->distance;
14269
801bb996
CS
14270 /* Check source address.
14271 * Note: for aggregate route, peer can have unspec af type.
14272 */
14273 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14274 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14275 return 0;
14276
9bcb3eef
DS
14277 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14278 if (dest) {
14279 bdistance = bgp_dest_get_bgp_distance_info(dest);
14280 bgp_dest_unlock_node(dest);
d62a17ae 14281
14282 if (bdistance->access_list) {
14283 alist = access_list_lookup(afi, bdistance->access_list);
14284 if (alist
14285 && access_list_apply(alist, p) == FILTER_PERMIT)
14286 return bdistance->distance;
14287 } else
14288 return bdistance->distance;
718e3744 14289 }
718e3744 14290
d62a17ae 14291 /* Backdoor check. */
9bcb3eef
DS
14292 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14293 if (dest) {
14294 bgp_static = bgp_dest_get_bgp_static_info(dest);
14295 bgp_dest_unlock_node(dest);
718e3744 14296
d62a17ae 14297 if (bgp_static->backdoor) {
14298 if (bgp->distance_local[afi][safi])
14299 return bgp->distance_local[afi][safi];
14300 else
14301 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14302 }
718e3744 14303 }
718e3744 14304
d62a17ae 14305 if (peer->sort == BGP_PEER_EBGP) {
14306 if (bgp->distance_ebgp[afi][safi])
14307 return bgp->distance_ebgp[afi][safi];
14308 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14309 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14310 if (bgp->distance_ibgp[afi][safi])
14311 return bgp->distance_ibgp[afi][safi];
14312 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14313 } else {
14314 if (bgp->distance_local[afi][safi])
14315 return bgp->distance_local[afi][safi];
14316 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14317 }
718e3744 14318}
14319
a612fb77
DA
14320/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14321 * we should tell ZEBRA update the routes for a specific
14322 * AFI/SAFI to reflect changes in RIB.
14323 */
585f1adc
IR
14324static void bgp_announce_routes_distance_update(struct bgp *bgp,
14325 afi_t update_afi,
14326 safi_t update_safi)
a612fb77
DA
14327{
14328 afi_t afi;
14329 safi_t safi;
14330
14331 FOREACH_AFI_SAFI (afi, safi) {
14332 if (!bgp_fibupd_safi(safi))
14333 continue;
14334
8b54bc30
DA
14335 if (afi != update_afi && safi != update_safi)
14336 continue;
14337
14338 if (BGP_DEBUG(zebra, ZEBRA))
14339 zlog_debug(
14340 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14341 __func__, afi, safi);
14342 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14343 }
14344}
14345
585f1adc
IR
14346DEFUN (bgp_distance,
14347 bgp_distance_cmd,
14348 "distance bgp (1-255) (1-255) (1-255)",
14349 "Define an administrative distance\n"
14350 "BGP distance\n"
14351 "Distance for routes external to the AS\n"
14352 "Distance for routes internal to the AS\n"
14353 "Distance for local routes\n")
718e3744 14354{
585f1adc 14355 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14356 int idx_number = 2;
14357 int idx_number_2 = 3;
14358 int idx_number_3 = 4;
585f1adc
IR
14359 int distance_ebgp = atoi(argv[idx_number]->arg);
14360 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14361 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14362 afi_t afi;
14363 safi_t safi;
718e3744 14364
d62a17ae 14365 afi = bgp_node_afi(vty);
14366 safi = bgp_node_safi(vty);
718e3744 14367
585f1adc
IR
14368 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14369 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14370 || bgp->distance_local[afi][safi] != distance_local) {
14371 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14372 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14373 bgp->distance_local[afi][safi] = distance_local;
14374 bgp_announce_routes_distance_update(bgp, afi, safi);
14375 }
14376 return CMD_SUCCESS;
14377}
37a87b8f 14378
585f1adc
IR
14379DEFUN (no_bgp_distance,
14380 no_bgp_distance_cmd,
14381 "no distance bgp [(1-255) (1-255) (1-255)]",
14382 NO_STR
14383 "Define an administrative distance\n"
14384 "BGP distance\n"
14385 "Distance for routes external to the AS\n"
14386 "Distance for routes internal to the AS\n"
14387 "Distance for local routes\n")
718e3744 14388{
585f1adc 14389 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14390 afi_t afi;
14391 safi_t safi;
37a87b8f
CS
14392
14393 afi = bgp_node_afi(vty);
14394 safi = bgp_node_safi(vty);
14395
585f1adc
IR
14396 if (bgp->distance_ebgp[afi][safi] != 0
14397 || bgp->distance_ibgp[afi][safi] != 0
14398 || bgp->distance_local[afi][safi] != 0) {
14399 bgp->distance_ebgp[afi][safi] = 0;
14400 bgp->distance_ibgp[afi][safi] = 0;
14401 bgp->distance_local[afi][safi] = 0;
14402 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14403 }
585f1adc
IR
14404 return CMD_SUCCESS;
14405}
37a87b8f 14406
37a87b8f 14407
585f1adc
IR
14408DEFUN (bgp_distance_source,
14409 bgp_distance_source_cmd,
14410 "distance (1-255) A.B.C.D/M",
14411 "Define an administrative distance\n"
14412 "Administrative distance\n"
14413 "IP source prefix\n")
14414{
14415 int idx_number = 1;
14416 int idx_ipv4_prefixlen = 2;
14417 bgp_distance_set(vty, argv[idx_number]->arg,
14418 argv[idx_ipv4_prefixlen]->arg, NULL);
14419 return CMD_SUCCESS;
734b349e
MZ
14420}
14421
585f1adc
IR
14422DEFUN (no_bgp_distance_source,
14423 no_bgp_distance_source_cmd,
14424 "no distance (1-255) A.B.C.D/M",
14425 NO_STR
14426 "Define an administrative distance\n"
14427 "Administrative distance\n"
14428 "IP source prefix\n")
37a87b8f 14429{
585f1adc
IR
14430 int idx_number = 2;
14431 int idx_ipv4_prefixlen = 3;
14432 bgp_distance_unset(vty, argv[idx_number]->arg,
14433 argv[idx_ipv4_prefixlen]->arg, NULL);
14434 return CMD_SUCCESS;
37a87b8f
CS
14435}
14436
585f1adc
IR
14437DEFUN (bgp_distance_source_access_list,
14438 bgp_distance_source_access_list_cmd,
14439 "distance (1-255) A.B.C.D/M WORD",
14440 "Define an administrative distance\n"
14441 "Administrative distance\n"
14442 "IP source prefix\n"
14443 "Access list name\n")
37a87b8f 14444{
585f1adc
IR
14445 int idx_number = 1;
14446 int idx_ipv4_prefixlen = 2;
14447 int idx_word = 3;
14448 bgp_distance_set(vty, argv[idx_number]->arg,
14449 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14450 return CMD_SUCCESS;
14451}
718e3744 14452
585f1adc
IR
14453DEFUN (no_bgp_distance_source_access_list,
14454 no_bgp_distance_source_access_list_cmd,
14455 "no distance (1-255) A.B.C.D/M WORD",
14456 NO_STR
14457 "Define an administrative distance\n"
14458 "Administrative distance\n"
14459 "IP source prefix\n"
14460 "Access list name\n")
14461{
14462 int idx_number = 2;
14463 int idx_ipv4_prefixlen = 3;
14464 int idx_word = 4;
14465 bgp_distance_unset(vty, argv[idx_number]->arg,
14466 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14467 return CMD_SUCCESS;
14468}
37a87b8f 14469
585f1adc
IR
14470DEFUN (ipv6_bgp_distance_source,
14471 ipv6_bgp_distance_source_cmd,
14472 "distance (1-255) X:X::X:X/M",
14473 "Define an administrative distance\n"
14474 "Administrative distance\n"
14475 "IP source prefix\n")
14476{
14477 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14478 return CMD_SUCCESS;
14479}
7ebe9748 14480
585f1adc
IR
14481DEFUN (no_ipv6_bgp_distance_source,
14482 no_ipv6_bgp_distance_source_cmd,
14483 "no distance (1-255) X:X::X:X/M",
14484 NO_STR
14485 "Define an administrative distance\n"
14486 "Administrative distance\n"
14487 "IP source prefix\n")
14488{
14489 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14490 return CMD_SUCCESS;
14491}
37a87b8f 14492
585f1adc
IR
14493DEFUN (ipv6_bgp_distance_source_access_list,
14494 ipv6_bgp_distance_source_access_list_cmd,
14495 "distance (1-255) X:X::X:X/M WORD",
14496 "Define an administrative distance\n"
14497 "Administrative distance\n"
14498 "IP source prefix\n"
14499 "Access list name\n")
14500{
14501 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14502 return CMD_SUCCESS;
718e3744 14503}
14504
585f1adc
IR
14505DEFUN (no_ipv6_bgp_distance_source_access_list,
14506 no_ipv6_bgp_distance_source_access_list_cmd,
14507 "no distance (1-255) X:X::X:X/M WORD",
14508 NO_STR
14509 "Define an administrative distance\n"
14510 "Administrative distance\n"
14511 "IP source prefix\n"
14512 "Access list name\n")
718e3744 14513{
585f1adc
IR
14514 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14515 return CMD_SUCCESS;
14516}
37a87b8f 14517
585f1adc
IR
14518DEFUN (bgp_damp_set,
14519 bgp_damp_set_cmd,
14520 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14521 "BGP Specific commands\n"
14522 "Enable route-flap dampening\n"
14523 "Half-life time for the penalty\n"
14524 "Value to start reusing a route\n"
14525 "Value to start suppressing a route\n"
14526 "Maximum duration to suppress a stable route\n")
14527{
14528 VTY_DECLVAR_CONTEXT(bgp, bgp);
14529 int idx_half_life = 2;
14530 int idx_reuse = 3;
14531 int idx_suppress = 4;
14532 int idx_max_suppress = 5;
37a87b8f
CS
14533 int half = DEFAULT_HALF_LIFE * 60;
14534 int reuse = DEFAULT_REUSE;
14535 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14536 int max = 4 * half;
14537
14538 if (argc == 6) {
14539 half = atoi(argv[idx_half_life]->arg) * 60;
14540 reuse = atoi(argv[idx_reuse]->arg);
14541 suppress = atoi(argv[idx_suppress]->arg);
14542 max = atoi(argv[idx_max_suppress]->arg) * 60;
14543 } else if (argc == 3) {
14544 half = atoi(argv[idx_half_life]->arg) * 60;
14545 max = 4 * half;
14546 }
14547
14548 /*
14549 * These can't be 0 but our SA doesn't understand the
14550 * way our cli is constructed
14551 */
14552 assert(reuse);
14553 assert(half);
14554 if (suppress < reuse) {
14555 vty_out(vty,
14556 "Suppress value cannot be less than reuse value \n");
14557 return 0;
14558 }
14559
14560 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14561 reuse, suppress, max);
14562}
14563
14564DEFUN (bgp_damp_unset,
14565 bgp_damp_unset_cmd,
14566 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14567 NO_STR
14568 "BGP Specific commands\n"
14569 "Enable route-flap dampening\n"
14570 "Half-life time for the penalty\n"
14571 "Value to start reusing a route\n"
14572 "Value to start suppressing a route\n"
14573 "Maximum duration to suppress a stable route\n")
14574{
14575 VTY_DECLVAR_CONTEXT(bgp, bgp);
14576 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14577}
14578
718e3744 14579/* Display specified route of BGP table. */
d62a17ae 14580static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14581 const char *ip_str, afi_t afi, safi_t safi,
14582 struct prefix_rd *prd, int prefix_check)
14583{
14584 int ret;
14585 struct prefix match;
9bcb3eef
DS
14586 struct bgp_dest *dest;
14587 struct bgp_dest *rm;
40381db7
DS
14588 struct bgp_path_info *pi;
14589 struct bgp_path_info *pi_temp;
d62a17ae 14590 struct bgp *bgp;
14591 struct bgp_table *table;
14592
14593 /* BGP structure lookup. */
14594 if (view_name) {
14595 bgp = bgp_lookup_by_name(view_name);
14596 if (bgp == NULL) {
14597 vty_out(vty, "%% Can't find BGP instance %s\n",
14598 view_name);
14599 return CMD_WARNING;
14600 }
14601 } else {
14602 bgp = bgp_get_default();
14603 if (bgp == NULL) {
14604 vty_out(vty, "%% No BGP process is configured\n");
14605 return CMD_WARNING;
14606 }
718e3744 14607 }
718e3744 14608
d62a17ae 14609 /* Check IP address argument. */
14610 ret = str2prefix(ip_str, &match);
14611 if (!ret) {
14612 vty_out(vty, "%% address is malformed\n");
14613 return CMD_WARNING;
14614 }
718e3744 14615
d62a17ae 14616 match.family = afi2family(afi);
14617
14618 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14619 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14620 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14621 dest = bgp_route_next(dest)) {
14622 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14623
9bcb3eef 14624 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14625 continue;
9bcb3eef 14626 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14627 if (!table)
ea47320b 14628 continue;
4953391b
DA
14629 rm = bgp_node_match(table, &match);
14630 if (rm == NULL)
ea47320b 14631 continue;
d62a17ae 14632
9bcb3eef 14633 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14634
ea47320b 14635 if (!prefix_check
b54892e0 14636 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14637 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14638 while (pi) {
14639 if (pi->extra && pi->extra->damp_info) {
14640 pi_temp = pi->next;
ea47320b 14641 bgp_damp_info_free(
19971c9a 14642 pi->extra->damp_info,
5c8846f6 14643 1, afi, safi);
40381db7 14644 pi = pi_temp;
ea47320b 14645 } else
40381db7 14646 pi = pi->next;
d62a17ae 14647 }
ea47320b
DL
14648 }
14649
9bcb3eef 14650 bgp_dest_unlock_node(rm);
d62a17ae 14651 }
14652 } else {
4953391b
DA
14653 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14654 if (dest != NULL) {
9bcb3eef 14655 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14656
d62a17ae 14657 if (!prefix_check
9bcb3eef
DS
14658 || dest_p->prefixlen == match.prefixlen) {
14659 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14660 while (pi) {
14661 if (pi->extra && pi->extra->damp_info) {
14662 pi_temp = pi->next;
d62a17ae 14663 bgp_damp_info_free(
19971c9a 14664 pi->extra->damp_info,
5c8846f6 14665 1, afi, safi);
40381db7 14666 pi = pi_temp;
d62a17ae 14667 } else
40381db7 14668 pi = pi->next;
d62a17ae 14669 }
14670 }
14671
9bcb3eef 14672 bgp_dest_unlock_node(dest);
d62a17ae 14673 }
14674 }
718e3744 14675
d62a17ae 14676 return CMD_SUCCESS;
718e3744 14677}
14678
14679DEFUN (clear_ip_bgp_dampening,
14680 clear_ip_bgp_dampening_cmd,
14681 "clear ip bgp dampening",
14682 CLEAR_STR
14683 IP_STR
14684 BGP_STR
14685 "Clear route flap dampening information\n")
14686{
b4f7f45b 14687 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14688 return CMD_SUCCESS;
718e3744 14689}
14690
14691DEFUN (clear_ip_bgp_dampening_prefix,
14692 clear_ip_bgp_dampening_prefix_cmd,
14693 "clear ip bgp dampening A.B.C.D/M",
14694 CLEAR_STR
14695 IP_STR
14696 BGP_STR
14697 "Clear route flap dampening information\n"
0c7b1b01 14698 "IPv4 prefix\n")
718e3744 14699{
d62a17ae 14700 int idx_ipv4_prefixlen = 4;
14701 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14702 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14703}
14704
14705DEFUN (clear_ip_bgp_dampening_address,
14706 clear_ip_bgp_dampening_address_cmd,
14707 "clear ip bgp dampening A.B.C.D",
14708 CLEAR_STR
14709 IP_STR
14710 BGP_STR
14711 "Clear route flap dampening information\n"
14712 "Network to clear damping information\n")
14713{
d62a17ae 14714 int idx_ipv4 = 4;
14715 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14716 SAFI_UNICAST, NULL, 0);
718e3744 14717}
14718
14719DEFUN (clear_ip_bgp_dampening_address_mask,
14720 clear_ip_bgp_dampening_address_mask_cmd,
14721 "clear ip bgp dampening A.B.C.D A.B.C.D",
14722 CLEAR_STR
14723 IP_STR
14724 BGP_STR
14725 "Clear route flap dampening information\n"
14726 "Network to clear damping information\n"
14727 "Network mask\n")
14728{
d62a17ae 14729 int idx_ipv4 = 4;
14730 int idx_ipv4_2 = 5;
14731 int ret;
14732 char prefix_str[BUFSIZ];
718e3744 14733
d62a17ae 14734 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14735 prefix_str, sizeof(prefix_str));
d62a17ae 14736 if (!ret) {
14737 vty_out(vty, "%% Inconsistent address and mask\n");
14738 return CMD_WARNING;
14739 }
718e3744 14740
d62a17ae 14741 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14742 NULL, 0);
718e3744 14743}
6b0655a2 14744
e3b78da8 14745static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14746{
14747 struct vty *vty = arg;
e3b78da8 14748 struct peer *peer = bucket->data;
825d9834
DS
14749 char buf[SU_ADDRSTRLEN];
14750
14751 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14752 sockunion2str(&peer->su, buf, sizeof(buf)));
14753}
14754
2a0e69ae
DS
14755DEFUN (show_bgp_listeners,
14756 show_bgp_listeners_cmd,
14757 "show bgp listeners",
14758 SHOW_STR
14759 BGP_STR
14760 "Display Listen Sockets and who created them\n")
14761{
14762 bgp_dump_listener_info(vty);
14763
14764 return CMD_SUCCESS;
14765}
14766
825d9834
DS
14767DEFUN (show_bgp_peerhash,
14768 show_bgp_peerhash_cmd,
14769 "show bgp peerhash",
14770 SHOW_STR
14771 BGP_STR
14772 "Display information about the BGP peerhash\n")
14773{
14774 struct list *instances = bm->bgp;
14775 struct listnode *node;
14776 struct bgp *bgp;
14777
14778 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14779 vty_out(vty, "BGP: %s\n", bgp->name);
14780 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14781 vty);
14782 }
14783
14784 return CMD_SUCCESS;
14785}
14786
587ff0fd 14787/* also used for encap safi */
2b791107
DL
14788static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14789 afi_t afi, safi_t safi)
d62a17ae 14790{
9bcb3eef
DS
14791 struct bgp_dest *pdest;
14792 struct bgp_dest *dest;
d62a17ae 14793 struct bgp_table *table;
b54892e0
DS
14794 const struct prefix *p;
14795 const struct prefix_rd *prd;
d62a17ae 14796 struct bgp_static *bgp_static;
14797 mpls_label_t label;
d62a17ae 14798 char rdbuf[RD_ADDRSTRLEN];
14799
14800 /* Network configuration. */
9bcb3eef
DS
14801 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14802 pdest = bgp_route_next(pdest)) {
14803 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14804 if (!table)
ea47320b 14805 continue;
d62a17ae 14806
9bcb3eef
DS
14807 for (dest = bgp_table_top(table); dest;
14808 dest = bgp_route_next(dest)) {
14809 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14810 if (bgp_static == NULL)
ea47320b 14811 continue;
d62a17ae 14812
9bcb3eef
DS
14813 p = bgp_dest_get_prefix(dest);
14814 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14815 pdest);
d62a17ae 14816
ea47320b 14817 /* "network" configuration display. */
06b9f471 14818 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14819 label = decode_label(&bgp_static->label);
14820
8228a9a7 14821 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14822 if (safi == SAFI_MPLS_VPN)
14823 vty_out(vty, " label %u", label);
14824
14825 if (bgp_static->rmap.name)
14826 vty_out(vty, " route-map %s",
14827 bgp_static->rmap.name);
e2a86ad9
DS
14828
14829 if (bgp_static->backdoor)
14830 vty_out(vty, " backdoor");
14831
ea47320b
DL
14832 vty_out(vty, "\n");
14833 }
14834 }
d62a17ae 14835}
14836
2b791107
DL
14837static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14838 afi_t afi, safi_t safi)
d62a17ae 14839{
9bcb3eef
DS
14840 struct bgp_dest *pdest;
14841 struct bgp_dest *dest;
d62a17ae 14842 struct bgp_table *table;
b54892e0
DS
14843 const struct prefix *p;
14844 const struct prefix_rd *prd;
d62a17ae 14845 struct bgp_static *bgp_static;
ff44f570 14846 char buf[PREFIX_STRLEN * 2];
d62a17ae 14847 char buf2[SU_ADDRSTRLEN];
14848 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14849 char esi_buf[ESI_BYTES];
d62a17ae 14850
14851 /* Network configuration. */
9bcb3eef
DS
14852 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14853 pdest = bgp_route_next(pdest)) {
14854 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14855 if (!table)
ea47320b 14856 continue;
d62a17ae 14857
9bcb3eef
DS
14858 for (dest = bgp_table_top(table); dest;
14859 dest = bgp_route_next(dest)) {
14860 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14861 if (bgp_static == NULL)
ea47320b 14862 continue;
d62a17ae 14863
ea47320b 14864 char *macrouter = NULL;
d62a17ae 14865
ea47320b
DL
14866 if (bgp_static->router_mac)
14867 macrouter = prefix_mac2str(
14868 bgp_static->router_mac, NULL, 0);
14869 if (bgp_static->eth_s_id)
0a50c248
AK
14870 esi_to_str(bgp_static->eth_s_id,
14871 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14872 p = bgp_dest_get_prefix(dest);
14873 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14874
ea47320b 14875 /* "network" configuration display. */
06b9f471 14876 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14877 if (p->u.prefix_evpn.route_type == 5) {
14878 char local_buf[PREFIX_STRLEN];
3714a385 14879 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14880 struct prefix_evpn *)p)
14881 ? AF_INET
14882 : AF_INET6;
3714a385 14883 inet_ntop(family,
14884 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14885 local_buf, PREFIX_STRLEN);
772270f3
QY
14886 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14887 p->u.prefix_evpn.prefix_addr
14888 .ip_prefix_length);
197cb530
PG
14889 } else {
14890 prefix2str(p, buf, sizeof(buf));
14891 }
ea47320b 14892
a4d82a8a
PZ
14893 if (bgp_static->gatewayIp.family == AF_INET
14894 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14895 inet_ntop(bgp_static->gatewayIp.family,
14896 &bgp_static->gatewayIp.u.prefix, buf2,
14897 sizeof(buf2));
ea47320b 14898 vty_out(vty,
7bcc8dac 14899 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14900 buf, rdbuf,
14901 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14902 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14903 macrouter);
14904
0a22ddfb 14905 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14906 }
14907 }
3da6fcd5
PG
14908}
14909
718e3744 14910/* Configuration of static route announcement and aggregate
14911 information. */
2b791107
DL
14912void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14913 safi_t safi)
d62a17ae 14914{
9bcb3eef 14915 struct bgp_dest *dest;
b54892e0 14916 const struct prefix *p;
d62a17ae 14917 struct bgp_static *bgp_static;
14918 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14919
2b791107
DL
14920 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14921 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14922 return;
14923 }
d62a17ae 14924
2b791107
DL
14925 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14926 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14927 return;
14928 }
d62a17ae 14929
14930 /* Network configuration. */
9bcb3eef
DS
14931 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14932 dest = bgp_route_next(dest)) {
14933 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14934 if (bgp_static == NULL)
ea47320b 14935 continue;
d62a17ae 14936
9bcb3eef 14937 p = bgp_dest_get_prefix(dest);
d62a17ae 14938
8228a9a7 14939 vty_out(vty, " network %pFX", p);
d62a17ae 14940
ea47320b
DL
14941 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14942 vty_out(vty, " label-index %u",
14943 bgp_static->label_index);
d62a17ae 14944
ea47320b
DL
14945 if (bgp_static->rmap.name)
14946 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14947
14948 if (bgp_static->backdoor)
14949 vty_out(vty, " backdoor");
718e3744 14950
ea47320b
DL
14951 vty_out(vty, "\n");
14952 }
14953
d62a17ae 14954 /* Aggregate-address configuration. */
9bcb3eef
DS
14955 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14956 dest = bgp_route_next(dest)) {
14957 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14958 if (bgp_aggregate == NULL)
ea47320b 14959 continue;
d62a17ae 14960
9bcb3eef 14961 p = bgp_dest_get_prefix(dest);
d62a17ae 14962
8228a9a7 14963 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14964
ea47320b
DL
14965 if (bgp_aggregate->as_set)
14966 vty_out(vty, " as-set");
d62a17ae 14967
ea47320b
DL
14968 if (bgp_aggregate->summary_only)
14969 vty_out(vty, " summary-only");
718e3744 14970
20894f50
DA
14971 if (bgp_aggregate->rmap.name)
14972 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14973
229757f1
DA
14974 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14975 vty_out(vty, " origin %s",
14976 bgp_origin2str(bgp_aggregate->origin));
14977
6aabb15d
RZ
14978 if (bgp_aggregate->match_med)
14979 vty_out(vty, " matching-MED-only");
14980
365ab2e7
RZ
14981 if (bgp_aggregate->suppress_map_name)
14982 vty_out(vty, " suppress-map %s",
14983 bgp_aggregate->suppress_map_name);
14984
ea47320b
DL
14985 vty_out(vty, "\n");
14986 }
d62a17ae 14987}
734b349e 14988
2b791107 14989void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14990 safi_t safi)
d62a17ae 14991{
9bcb3eef 14992 struct bgp_dest *dest;
d62a17ae 14993 struct bgp_distance *bdistance;
14994
14995 /* Distance configuration. */
14996 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14997 && bgp->distance_local[afi][safi]
14998 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14999 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15000 || bgp->distance_local[afi][safi]
15001 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15002 vty_out(vty, " distance bgp %d %d %d\n",
15003 bgp->distance_ebgp[afi][safi],
15004 bgp->distance_ibgp[afi][safi],
15005 bgp->distance_local[afi][safi]);
15006 }
734b349e 15007
9bcb3eef
DS
15008 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15009 dest = bgp_route_next(dest)) {
15010 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15011 if (bdistance != NULL)
56ca3b5b 15012 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15013 bdistance->distance, dest,
d62a17ae 15014 bdistance->access_list ? bdistance->access_list
15015 : "");
ca2e160d 15016 }
718e3744 15017}
15018
15019/* Allocate routing table structure and install commands. */
d62a17ae 15020void bgp_route_init(void)
15021{
15022 afi_t afi;
15023 safi_t safi;
15024
15025 /* Init BGP distance table. */
05c7a1cc 15026 FOREACH_AFI_SAFI (afi, safi)
960035b2 15027 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15028
15029 /* IPv4 BGP commands. */
15030 install_element(BGP_NODE, &bgp_table_map_cmd);
15031 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15032 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15033
554b3b10 15034 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15035
15036 /* IPv4 unicast configuration. */
15037 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15038 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15039 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15040
554b3b10 15041 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15042
15043 /* IPv4 multicast configuration. */
15044 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15045 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15046 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15047 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15048
15049 /* IPv4 labeled-unicast configuration. */
fb985e0c 15050 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15051 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15052
d62a17ae 15053 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15054 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15055 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15056 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15057 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15058 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15059 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15060 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15061
15062 install_element(VIEW_NODE,
15063 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15064 install_element(VIEW_NODE,
15065 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15066 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15067 install_element(VIEW_NODE,
15068 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15069#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15070 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15071#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15072 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15073 install_element(VIEW_NODE,
44c69747 15074 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15075
d62a17ae 15076 /* BGP dampening clear commands */
15077 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15078 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15079
d62a17ae 15080 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15081 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15082
15083 /* prefix count */
15084 install_element(ENABLE_NODE,
15085 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15086#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15087 install_element(ENABLE_NODE,
15088 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15089#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15090
d62a17ae 15091 /* New config IPv6 BGP commands. */
15092 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15093 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15094 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15095
554b3b10 15096 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15097
15098 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15099
fb985e0c
DA
15100 /* IPv6 labeled unicast address family. */
15101 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15102 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15103
d62a17ae 15104 install_element(BGP_NODE, &bgp_distance_cmd);
15105 install_element(BGP_NODE, &no_bgp_distance_cmd);
15106 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15107 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15108 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15109 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15110 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15111 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15112 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15113 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15114 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15115 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15116 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15117 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15118 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15119 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15120 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15121 install_element(BGP_IPV4M_NODE,
15122 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15123 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15124 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15125 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15126 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15127 install_element(BGP_IPV6_NODE,
15128 &ipv6_bgp_distance_source_access_list_cmd);
15129 install_element(BGP_IPV6_NODE,
15130 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15131 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15132 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15133 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15134 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15135 install_element(BGP_IPV6M_NODE,
15136 &ipv6_bgp_distance_source_access_list_cmd);
15137 install_element(BGP_IPV6M_NODE,
15138 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15139
ef5f4b23 15140 /* BGP dampening */
585f1adc
IR
15141 install_element(BGP_NODE, &bgp_damp_set_cmd);
15142 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15143 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15144 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15145 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15146 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15147 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15148 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15149 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15150 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15151 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15152 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15153 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15154 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15155
15156 /* Large Communities */
15157 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15158 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15159
15160 /* show bgp ipv4 flowspec detailed */
15161 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15162
2a0e69ae 15163 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15164 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15165}
15166
15167void bgp_route_finish(void)
15168{
15169 afi_t afi;
15170 safi_t safi;
15171
05c7a1cc
QY
15172 FOREACH_AFI_SAFI (afi, safi) {
15173 bgp_table_unlock(bgp_distance_table[afi][safi]);
15174 bgp_distance_table[afi][safi] = NULL;
15175 }
228da428 15176}