]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #10867 from donaldsharp/ifp_use_after_free
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
7fd28dd2
PR
96DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 98 (rn, pi, added));
7fd28dd2 99
b5b99af8
DS
100DEFINE_HOOK(bgp_rpki_prefix_status,
101 (struct peer *peer, struct attr *attr,
102 const struct prefix *prefix),
8451921b 103 (peer, attr, prefix));
b5b99af8 104
2aad8c42
MS
105/* Render dest to prefix_rd based on safi */
106static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
107 safi_t safi);
108
718e3744 109/* Extern from bgp_dump.c */
dde72586
SH
110extern const char *bgp_origin_str[];
111extern const char *bgp_origin_long_str[];
3742de8d 112
b7d08f5a 113/* PMSI strings. */
114#define PMSI_TNLTYPE_STR_NO_INFO "No info"
115#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116static const struct message bgp_pmsi_tnltype_str[] = {
117 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 125 {0}
126};
b7d08f5a 127
9df8b37c 128#define VRFID_NONE_STR "-"
46aeabed 129#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 130
4a11bf2c 131DEFINE_HOOK(bgp_process,
9bcb3eef
DS
132 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
133 struct peer *peer, bool withdraw),
8451921b 134 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 135
4056a5f6
RZ
136/** Test if path is suppressed. */
137static bool bgp_path_suppressed(struct bgp_path_info *pi)
138{
139 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
140 return false;
141
142 return listcount(pi->extra->aggr_suppressors) > 0;
143}
4a11bf2c 144
9bcb3eef 145struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 146 safi_t safi, const struct prefix *p,
d62a17ae 147 struct prefix_rd *prd)
148{
9bcb3eef
DS
149 struct bgp_dest *dest;
150 struct bgp_dest *pdest = NULL;
d62a17ae 151
152 assert(table);
d62a17ae 153
154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN)) {
9bcb3eef 156 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 157
9bcb3eef
DS
158 if (!bgp_dest_has_bgp_path_info_data(pdest))
159 bgp_dest_set_bgp_table_info(
160 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 161 else
9bcb3eef
DS
162 bgp_dest_unlock_node(pdest);
163 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 164 }
718e3744 165
9bcb3eef 166 dest = bgp_node_get(table, p);
718e3744 167
d62a17ae 168 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
169 || (safi == SAFI_EVPN))
9bcb3eef 170 dest->pdest = pdest;
718e3744 171
9bcb3eef 172 return dest;
718e3744 173}
6b0655a2 174
9bcb3eef 175struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 176 safi_t safi, const struct prefix *p,
d62a17ae 177 struct prefix_rd *prd)
128ea8ab 178{
9bcb3eef
DS
179 struct bgp_dest *dest;
180 struct bgp_dest *pdest = NULL;
128ea8ab 181
d62a17ae 182 if (!table)
183 return NULL;
128ea8ab 184
d62a17ae 185 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
186 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
187 pdest = bgp_node_lookup(table, (struct prefix *)prd);
188 if (!pdest)
d62a17ae 189 return NULL;
128ea8ab 190
9bcb3eef
DS
191 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
192 bgp_dest_unlock_node(pdest);
d62a17ae 193 return NULL;
194 }
128ea8ab 195
9bcb3eef 196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 197 }
128ea8ab 198
9bcb3eef 199 dest = bgp_node_lookup(table, p);
128ea8ab 200
9bcb3eef 201 return dest;
128ea8ab 202}
203
18ee8310
DS
204/* Allocate bgp_path_info_extra */
205static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 206{
4b7e6066
DS
207 struct bgp_path_info_extra *new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
209 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
210 new->label[0] = MPLS_INVALID_LABEL;
211 new->num_labels = 0;
3e3708cb
PG
212 new->bgp_fs_pbr = NULL;
213 new->bgp_fs_iprule = NULL;
d62a17ae 214 return new;
fb982c25
PJ
215}
216
a2e219fe 217void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 218{
4b7e6066 219 struct bgp_path_info_extra *e;
d62a17ae 220
c93a3b77
DS
221 if (!extra || !*extra)
222 return;
d62a17ae 223
c93a3b77 224 e = *extra;
4538f895 225 if (e->damp_info)
b4f7f45b
IR
226 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
227 e->damp_info->safi);
4538f895 228
c93a3b77
DS
229 e->damp_info = NULL;
230 if (e->parent) {
40381db7 231 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 232
40381db7 233 if (bpi->net) {
0e70e6c8
DL
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
237 *
40381db7
DS
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
0e70e6c8
DL
241 */
242 unsigned refcount;
243
40381db7 244 bpi = bgp_path_info_lock(bpi);
c10e14e9 245 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 246 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 247 if (!refcount)
40381db7
DS
248 bpi->net = NULL;
249 bgp_path_info_unlock(bpi);
0e70e6c8 250 }
18ee8310 251 bgp_path_info_unlock(e->parent);
c93a3b77 252 e->parent = NULL;
d62a17ae 253 }
c93a3b77
DS
254
255 if (e->bgp_orig)
256 bgp_unlock(e->bgp_orig);
c26edcda 257
ff3bf9a4
DS
258 if (e->aggr_suppressors)
259 list_delete(&e->aggr_suppressors);
260
60605cbc
AK
261 if (e->mh_info)
262 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 263
ce3c0614
PG
264 if ((*extra)->bgp_fs_iprule)
265 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 266 if ((*extra)->bgp_fs_pbr)
6a154c88 267 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 268 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
269}
270
18ee8310
DS
271/* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
fb982c25 273 */
40381db7 274struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 275{
40381db7
DS
276 if (!pi->extra)
277 pi->extra = bgp_path_info_extra_new();
278 return pi->extra;
fb982c25
PJ
279}
280
718e3744 281/* Free bgp route information. */
9b6d8fcf 282static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 283{
05864da7 284 bgp_attr_unintern(&path->attr);
fb018d25 285
9b6d8fcf
DS
286 bgp_unlink_nexthop(path);
287 bgp_path_info_extra_free(&path->extra);
288 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
289 if (path->net)
290 bgp_addpath_free_info_data(&path->tx_addpath,
291 &path->net->tx_addpath);
718e3744 292
9b6d8fcf 293 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 294
9b6d8fcf 295 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 296}
297
9b6d8fcf 298struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 299{
9b6d8fcf
DS
300 path->lock++;
301 return path;
200df115 302}
303
9b6d8fcf 304struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 305{
9b6d8fcf
DS
306 assert(path && path->lock > 0);
307 path->lock--;
d62a17ae 308
9b6d8fcf 309 if (path->lock == 0) {
9b6d8fcf 310 bgp_path_info_free(path);
d62a17ae 311 return NULL;
312 }
200df115 313
9b6d8fcf 314 return path;
200df115 315}
316
f009ff26 317/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 318static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 319{
320 struct peer *peer;
321 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 322 bool set_flag = false;
f009ff26 323 struct bgp *bgp = NULL;
324 struct bgp_table *table = NULL;
325 afi_t afi = 0;
326 safi_t safi = 0;
f009ff26 327
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
330 */
9bcb3eef 331 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 332 return 0;
333
9bcb3eef 334 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 335 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 336 zlog_debug(
56ca3b5b
DL
337 "Route %pBD is in workqueue and being processed, not deferred.",
338 dest);
b54892e0 339
5f9c1aa2 340 return 0;
341 }
342
9bcb3eef 343 table = bgp_dest_table(dest);
f009ff26 344 if (table) {
345 bgp = table->bgp;
346 afi = table->afi;
347 safi = table->safi;
348 }
349
9bcb3eef 350 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 351 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
352 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
353 continue;
354
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
357 */
36235319
QY
358 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
359 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 360 set_flag = true;
f009ff26 361 } else {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
364 */
365 peer = old_pi->peer;
36235319
QY
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
367 && BGP_PEER_RESTARTING_MODE(peer)
368 && (old_pi
369 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 370 set_flag = true;
f009ff26 371 }
372 }
373 if (set_flag)
374 break;
375 }
376
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
378 * is active
379 */
2ba1fe69 380 if (set_flag && table) {
f009ff26 381 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
382 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
383 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 384 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 385 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
386 zlog_debug("DEFER route %pBD, dest %p", dest,
387 dest);
f009ff26 388 return 0;
389 }
390 }
391 return -1;
392}
393
9bcb3eef 394void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 395{
4b7e6066 396 struct bgp_path_info *top;
718e3744 397
9bcb3eef 398 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 399
6f94b685 400 pi->next = top;
40381db7 401 pi->prev = NULL;
d62a17ae 402 if (top)
40381db7 403 top->prev = pi;
9bcb3eef 404 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 405
40381db7 406 bgp_path_info_lock(pi);
9bcb3eef 407 bgp_dest_lock_node(dest);
40381db7 408 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 409 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 410 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 411}
412
d62a17ae 413/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 414 completion callback *only* */
9bcb3eef 415void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 416{
40381db7
DS
417 if (pi->next)
418 pi->next->prev = pi->prev;
419 if (pi->prev)
420 pi->prev->next = pi->next;
d62a17ae 421 else
9bcb3eef 422 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 423
40381db7
DS
424 bgp_path_info_mpath_dequeue(pi);
425 bgp_path_info_unlock(pi);
7fd28dd2 426 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 427 bgp_dest_unlock_node(dest);
718e3744 428}
429
9bcb3eef 430void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 431{
9bcb3eef 432 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 433 /* set of previous already took care of pcount */
40381db7 434 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 435}
436
18ee8310 437/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
438 called when a route is deleted and then quickly re-added before the
439 deletion has been processed */
9bcb3eef 440void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 441{
9bcb3eef 442 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 443 /* unset of previous already took care of pcount */
40381db7 444 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
445}
446
d62a17ae 447/* Adjust pcount as required */
9bcb3eef 448static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 449{
d62a17ae 450 struct bgp_table *table;
67174041 451
9bcb3eef 452 assert(dest && bgp_dest_table(dest));
40381db7 453 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 454
9bcb3eef 455 table = bgp_dest_table(dest);
67174041 456
40381db7 457 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 458 return;
459
40381db7
DS
460 if (!BGP_PATH_COUNTABLE(pi)
461 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 462
40381db7 463 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 464
465 /* slight hack, but more robust against errors. */
40381db7
DS
466 if (pi->peer->pcount[table->afi][table->safi])
467 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 468 else
450971aa 469 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 470 "Asked to decrement 0 prefix count for peer");
40381db7
DS
471 } else if (BGP_PATH_COUNTABLE(pi)
472 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
473 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
474 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 475 }
1a392d46
PJ
476}
477
40381db7
DS
478static int bgp_label_index_differs(struct bgp_path_info *pi1,
479 struct bgp_path_info *pi2)
28d58fd7 480{
40381db7 481 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 482}
1a392d46 483
18ee8310 484/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
485 * This is here primarily to keep prefix-count in check.
486 */
9bcb3eef 487void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 488 uint32_t flag)
1a392d46 489{
40381db7 490 SET_FLAG(pi->flags, flag);
d62a17ae 491
492 /* early bath if we know it's not a flag that changes countability state
493 */
494 if (!CHECK_FLAG(flag,
1defdda8 495 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 496 return;
497
9bcb3eef 498 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
499}
500
9bcb3eef 501void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 502 uint32_t flag)
1a392d46 503{
40381db7 504 UNSET_FLAG(pi->flags, flag);
d62a17ae 505
506 /* early bath if we know it's not a flag that changes countability state
507 */
508 if (!CHECK_FLAG(flag,
1defdda8 509 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 510 return;
511
9bcb3eef 512 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
513}
514
718e3744 515/* Get MED value. If MED value is missing and "bgp bestpath
516 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 517static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 518{
519 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
520 return attr->med;
521 else {
892fedb6 522 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 523 return BGP_MED_MAX;
524 else
525 return 0;
526 }
718e3744 527}
528
7533cad7
QY
529void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
530 size_t buf_len)
2ec1e66f 531{
40381db7 532 if (pi->addpath_rx_id)
7533cad7
QY
533 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
534 pi->peer->host, pi->addpath_rx_id);
d62a17ae 535 else
7533cad7 536 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 537}
9fbdd100 538
da0c0ef7
KM
539
540/*
541 * Get the ultimate path info.
542 */
543struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
544{
545 struct bgp_path_info *bpi_ultimate;
546
547 if (info->sub_type != BGP_ROUTE_IMPORTED)
548 return info;
549
550 for (bpi_ultimate = info;
551 bpi_ultimate->extra && bpi_ultimate->extra->parent;
552 bpi_ultimate = bpi_ultimate->extra->parent)
553 ;
554
555 return bpi_ultimate;
556}
557
d62a17ae 558/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 */
18ee8310
DS
560static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
561 struct bgp_path_info *exist, int *paths_eq,
562 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
563 char *pfx_buf, afi_t afi, safi_t safi,
564 enum bgp_path_selection_reason *reason)
d62a17ae 565{
5df26422 566 const struct prefix *new_p;
d62a17ae 567 struct attr *newattr, *existattr;
568 bgp_peer_sort_t new_sort;
569 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
570 uint32_t new_pref;
571 uint32_t exist_pref;
572 uint32_t new_med;
573 uint32_t exist_med;
574 uint32_t new_weight;
575 uint32_t exist_weight;
d62a17ae 576 uint32_t newm, existm;
577 struct in_addr new_id;
578 struct in_addr exist_id;
579 int new_cluster;
580 int exist_cluster;
581 int internal_as_route;
582 int confed_as_route;
04d14c8b 583 int ret = 0;
ee88563a
JM
584 int igp_metric_ret = 0;
585 int peer_sort_ret = -1;
d62a17ae 586 char new_buf[PATH_ADDPATH_STR_BUFFER];
587 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
588 uint32_t new_mm_seq;
589 uint32_t exist_mm_seq;
6d8c603a 590 int nh_cmp;
d071f237
AK
591 esi_t *exist_esi;
592 esi_t *new_esi;
593 bool same_esi;
594 bool old_proxy;
595 bool new_proxy;
33c6e933 596 bool new_origin, exist_origin;
da0c0ef7 597 struct bgp_path_info *bpi_ultimate;
d62a17ae 598
599 *paths_eq = 0;
600
601 /* 0. Null check. */
602 if (new == NULL) {
fdf81fa0 603 *reason = bgp_path_selection_none;
d62a17ae 604 if (debug)
605 zlog_debug("%s: new is NULL", pfx_buf);
606 return 0;
607 }
2ec1e66f 608
da0c0ef7
KM
609 if (debug) {
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 612 sizeof(new_buf));
da0c0ef7 613 }
718e3744 614
d62a17ae 615 if (exist == NULL) {
fdf81fa0 616 *reason = bgp_path_selection_first;
d62a17ae 617 if (debug)
4378495a
DS
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 620 return 1;
621 }
2ec1e66f 622
d62a17ae 623 if (debug) {
da0c0ef7
KM
624 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 626 sizeof(exist_buf));
4378495a
DS
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf, bgp->name_pretty, new_buf, new->flags,
629 exist_buf, exist->flags);
d62a17ae 630 }
8ff56318 631
d62a17ae 632 newattr = new->attr;
633 existattr = exist->attr;
634
1479ed2f
DA
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
639 *
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
643 */
9a706b42
DA
644 if (bgp_attr_get_community(newattr) &&
645 community_include(bgp_attr_get_community(newattr),
646 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
647 if (debug)
648 zlog_debug(
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf, new_buf, exist_buf);
651 return 0;
652 }
653
9a706b42
DA
654 if (bgp_attr_get_community(existattr) &&
655 community_include(bgp_attr_get_community(existattr),
656 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
657 if (debug)
658 zlog_debug(
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf, new_buf, exist_buf);
661 return 1;
662 }
663
5df26422
NS
664 new_p = bgp_dest_get_prefix(new->net);
665
d62a17ae 666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
668 */
5df26422
NS
669 if ((safi == SAFI_EVPN)
670 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 671 /* This is an error condition described in RFC 7432 Section
672 * 15.2. The RFC
673 * states that in this scenario "the PE MUST alert the operator"
674 * but it
675 * does not state what other action to take. In order to provide
676 * some
677 * consistency in this scenario we are going to prefer the path
678 * with the
679 * sticky flag.
680 */
681 if (newattr->sticky != existattr->sticky) {
682 if (!debug) {
5df26422
NS
683 prefix2str(new_p, pfx_buf,
684 sizeof(*pfx_buf)
685 * PREFIX2STR_BUFFER);
18ee8310 686 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
687 new, new_buf, sizeof(new_buf));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist, exist_buf, sizeof(exist_buf));
d62a17ae 690 }
691
692 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 693 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
694 if (debug)
695 zlog_debug(
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf, new_buf, exist_buf);
d62a17ae 698 return 1;
699 }
700
701 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 702 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
703 if (debug)
704 zlog_debug(
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf, new_buf, exist_buf);
d62a17ae 707 return 0;
708 }
709 }
128ea8ab 710
d071f237
AK
711 new_esi = bgp_evpn_attr_get_esi(newattr);
712 exist_esi = bgp_evpn_attr_get_esi(existattr);
713 if (bgp_evpn_is_esi_valid(new_esi) &&
714 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
715 same_esi = true;
716 } else {
717 same_esi = false;
718 }
719
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
726 */
727 if (same_esi) {
728 char esi_buf[ESI_STR_LEN];
729
730 if (bgp_evpn_is_path_local(bgp, new)) {
731 *reason = bgp_path_selection_evpn_local_path;
732 if (debug)
733 zlog_debug(
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf, new_buf, exist_buf,
736 esi_to_str(new_esi, esi_buf,
737 sizeof(esi_buf)));
738 return 1;
739 }
740 if (bgp_evpn_is_path_local(bgp, exist)) {
741 *reason = bgp_path_selection_evpn_local_path;
742 if (debug)
743 zlog_debug(
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf, new_buf, exist_buf,
746 esi_to_str(new_esi, esi_buf,
747 sizeof(esi_buf)));
748 return 0;
749 }
750 }
751
d62a17ae 752 new_mm_seq = mac_mobility_seqnum(newattr);
753 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 754
d62a17ae 755 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 756 *reason = bgp_path_selection_evpn_seq;
d62a17ae 757 if (debug)
758 zlog_debug(
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf, new_buf, exist_buf, new_mm_seq,
761 exist_mm_seq);
762 return 1;
763 }
8ff56318 764
d62a17ae 765 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 766 *reason = bgp_path_selection_evpn_seq;
d62a17ae 767 if (debug)
768 zlog_debug(
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf, new_buf, exist_buf, new_mm_seq,
771 exist_mm_seq);
772 return 0;
773 }
6d8c603a 774
d071f237
AK
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
777 */
778 new_proxy = bgp_evpn_attr_is_proxy(newattr);
779 old_proxy = bgp_evpn_attr_is_proxy(existattr);
780 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
781 old_proxy != new_proxy) {
782 if (!new_proxy) {
783 *reason = bgp_path_selection_evpn_non_proxy;
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf, new_buf, exist_buf);
788 return 1;
789 }
790
791 *reason = bgp_path_selection_evpn_non_proxy;
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf, new_buf, exist_buf);
796 return 0;
797 }
798
6d8c603a
AK
799 /*
800 * if sequence numbers are the same path with the lowest IP
801 * wins
802 */
803 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
804 if (nh_cmp < 0) {
fdf81fa0 805 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
806 if (debug)
807 zlog_debug(
23d0a753 808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 809 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 810 &new->attr->nexthop);
6d8c603a
AK
811 return 1;
812 }
813 if (nh_cmp > 0) {
fdf81fa0 814 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
815 if (debug)
816 zlog_debug(
23d0a753 817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 818 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 819 &new->attr->nexthop);
6d8c603a
AK
820 return 0;
821 }
d62a17ae 822 }
9fbdd100 823
d62a17ae 824 /* 1. Weight check. */
d62a17ae 825 new_weight = newattr->weight;
826 exist_weight = existattr->weight;
8ff56318 827
d62a17ae 828 if (new_weight > exist_weight) {
fdf81fa0 829 *reason = bgp_path_selection_weight;
d62a17ae 830 if (debug)
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf, new_buf, exist_buf, new_weight,
833 exist_weight);
834 return 1;
835 }
718e3744 836
d62a17ae 837 if (new_weight < exist_weight) {
fdf81fa0 838 *reason = bgp_path_selection_weight;
d62a17ae 839 if (debug)
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf, new_buf, exist_buf, new_weight,
842 exist_weight);
843 return 0;
844 }
9fbdd100 845
d62a17ae 846 /* 2. Local preference check. */
847 new_pref = exist_pref = bgp->default_local_pref;
848
849 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 new_pref = newattr->local_pref;
851 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
852 exist_pref = existattr->local_pref;
853
854 if (new_pref > exist_pref) {
fdf81fa0 855 *reason = bgp_path_selection_local_pref;
d62a17ae 856 if (debug)
857 zlog_debug(
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf, new_buf, exist_buf, new_pref,
860 exist_pref);
861 return 1;
862 }
718e3744 863
d62a17ae 864 if (new_pref < exist_pref) {
fdf81fa0 865 *reason = bgp_path_selection_local_pref;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf, new_buf, exist_buf, new_pref,
870 exist_pref);
871 return 0;
872 }
9fbdd100 873
d62a17ae 874 /* 3. Local route check. We prefer:
875 * - BGP_ROUTE_STATIC
876 * - BGP_ROUTE_AGGREGATE
877 * - BGP_ROUTE_REDISTRIBUTE
878 */
33c6e933
DS
879 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
880 new->sub_type == BGP_ROUTE_IMPORTED);
881 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
882 exist->sub_type == BGP_ROUTE_IMPORTED);
883
884 if (new_origin && !exist_origin) {
fdf81fa0 885 *reason = bgp_path_selection_local_route;
d62a17ae 886 if (debug)
887 zlog_debug(
888 "%s: %s wins over %s due to preferred BGP_ROUTE type",
889 pfx_buf, new_buf, exist_buf);
890 return 1;
891 }
718e3744 892
33c6e933 893 if (!new_origin && exist_origin) {
fdf81fa0 894 *reason = bgp_path_selection_local_route;
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s loses to %s due to preferred BGP_ROUTE type",
898 pfx_buf, new_buf, exist_buf);
899 return 0;
6811845b 900 }
718e3744 901
da0c0ef7
KM
902 /* Here if these are imported routes then get ultimate pi for
903 * path compare.
904 */
905 new = bgp_get_imported_bpi_ultimate(new);
906 exist = bgp_get_imported_bpi_ultimate(exist);
907 newattr = new->attr;
908 existattr = exist->attr;
909
d62a17ae 910 /* 4. AS path length check. */
892fedb6 911 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 912 int exist_hops = aspath_count_hops(existattr->aspath);
913 int exist_confeds = aspath_count_confeds(existattr->aspath);
914
892fedb6 915 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 916 int aspath_hops;
917
918 aspath_hops = aspath_count_hops(newattr->aspath);
919 aspath_hops += aspath_count_confeds(newattr->aspath);
920
921 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 922 *reason = bgp_path_selection_confed_as_path;
d62a17ae 923 if (debug)
924 zlog_debug(
925 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
926 pfx_buf, new_buf, exist_buf,
927 aspath_hops,
928 (exist_hops + exist_confeds));
929 return 1;
930 }
931
932 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 933 *reason = bgp_path_selection_confed_as_path;
d62a17ae 934 if (debug)
935 zlog_debug(
936 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
937 pfx_buf, new_buf, exist_buf,
938 aspath_hops,
939 (exist_hops + exist_confeds));
940 return 0;
941 }
942 } else {
943 int newhops = aspath_count_hops(newattr->aspath);
944
945 if (newhops < exist_hops) {
fdf81fa0 946 *reason = bgp_path_selection_as_path;
d62a17ae 947 if (debug)
948 zlog_debug(
949 "%s: %s wins over %s due to aspath hopcount %d < %d",
950 pfx_buf, new_buf, exist_buf,
951 newhops, exist_hops);
952 return 1;
953 }
954
955 if (newhops > exist_hops) {
fdf81fa0 956 *reason = bgp_path_selection_as_path;
d62a17ae 957 if (debug)
958 zlog_debug(
959 "%s: %s loses to %s due to aspath hopcount %d > %d",
960 pfx_buf, new_buf, exist_buf,
961 newhops, exist_hops);
962 return 0;
963 }
964 }
965 }
9fbdd100 966
d62a17ae 967 /* 5. Origin check. */
968 if (newattr->origin < existattr->origin) {
fdf81fa0 969 *reason = bgp_path_selection_origin;
d62a17ae 970 if (debug)
971 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
972 pfx_buf, new_buf, exist_buf,
973 bgp_origin_long_str[newattr->origin],
974 bgp_origin_long_str[existattr->origin]);
975 return 1;
976 }
718e3744 977
d62a17ae 978 if (newattr->origin > existattr->origin) {
fdf81fa0 979 *reason = bgp_path_selection_origin;
d62a17ae 980 if (debug)
981 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
982 pfx_buf, new_buf, exist_buf,
983 bgp_origin_long_str[newattr->origin],
984 bgp_origin_long_str[existattr->origin]);
985 return 0;
986 }
718e3744 987
d62a17ae 988 /* 6. MED check. */
989 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
990 && aspath_count_hops(existattr->aspath) == 0);
991 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
992 && aspath_count_confeds(existattr->aspath) > 0
993 && aspath_count_hops(newattr->aspath) == 0
994 && aspath_count_hops(existattr->aspath) == 0);
995
892fedb6
DA
996 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
997 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 998 || aspath_cmp_left(newattr->aspath, existattr->aspath)
999 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1000 || internal_as_route) {
1001 new_med = bgp_med_value(new->attr, bgp);
1002 exist_med = bgp_med_value(exist->attr, bgp);
1003
1004 if (new_med < exist_med) {
fdf81fa0 1005 *reason = bgp_path_selection_med;
d62a17ae 1006 if (debug)
1007 zlog_debug(
1008 "%s: %s wins over %s due to MED %d < %d",
1009 pfx_buf, new_buf, exist_buf, new_med,
1010 exist_med);
1011 return 1;
1012 }
8ff56318 1013
d62a17ae 1014 if (new_med > exist_med) {
fdf81fa0 1015 *reason = bgp_path_selection_med;
d62a17ae 1016 if (debug)
1017 zlog_debug(
1018 "%s: %s loses to %s due to MED %d > %d",
1019 pfx_buf, new_buf, exist_buf, new_med,
1020 exist_med);
1021 return 0;
1022 }
1023 }
9fbdd100 1024
d62a17ae 1025 /* 7. Peer type check. */
1026 new_sort = new->peer->sort;
1027 exist_sort = exist->peer->sort;
1028
1029 if (new_sort == BGP_PEER_EBGP
1030 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1031 *reason = bgp_path_selection_peer;
d62a17ae 1032 if (debug)
1033 zlog_debug(
1034 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1035 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1036 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1037 return 1;
1038 peer_sort_ret = 1;
d62a17ae 1039 }
718e3744 1040
d62a17ae 1041 if (exist_sort == BGP_PEER_EBGP
1042 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1043 *reason = bgp_path_selection_peer;
d62a17ae 1044 if (debug)
1045 zlog_debug(
1046 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1047 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1048 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1049 return 0;
1050 peer_sort_ret = 0;
d62a17ae 1051 }
8ff56318 1052
d62a17ae 1053 /* 8. IGP metric check. */
1054 newm = existm = 0;
8ff56318 1055
d62a17ae 1056 if (new->extra)
1057 newm = new->extra->igpmetric;
1058 if (exist->extra)
1059 existm = exist->extra->igpmetric;
9fbdd100 1060
d62a17ae 1061 if (newm < existm) {
ee88563a 1062 if (debug && peer_sort_ret < 0)
d62a17ae 1063 zlog_debug(
d588b995 1064 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1065 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1066 igp_metric_ret = 1;
d62a17ae 1067 }
718e3744 1068
d62a17ae 1069 if (newm > existm) {
ee88563a 1070 if (debug && peer_sort_ret < 0)
d62a17ae 1071 zlog_debug(
d588b995 1072 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1073 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1074 igp_metric_ret = 0;
5e242b0d 1075 }
5e242b0d 1076
d62a17ae 1077 /* 9. Same IGP metric. Compare the cluster list length as
1078 representative of IGP hops metric. Rewrite the metric value
1079 pair (newm, existm) with the cluster list length. Prefer the
1080 path with smaller cluster list length. */
1081 if (newm == existm) {
bf0d28dc
DS
1082 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1083 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1084 && (mpath_cfg == NULL
1085 || CHECK_FLAG(
1086 mpath_cfg->ibgp_flags,
1087 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1088 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1089 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1090
1091 if (newm < existm) {
ee88563a 1092 if (debug && peer_sort_ret < 0)
d62a17ae 1093 zlog_debug(
d588b995 1094 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1095 pfx_buf, new_buf, exist_buf,
1096 newm, existm);
ee88563a 1097 igp_metric_ret = 1;
d62a17ae 1098 }
1099
1100 if (newm > existm) {
ee88563a 1101 if (debug && peer_sort_ret < 0)
d62a17ae 1102 zlog_debug(
d588b995 1103 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1104 pfx_buf, new_buf, exist_buf,
1105 newm, existm);
ee88563a 1106 igp_metric_ret = 0;
d62a17ae 1107 }
1108 }
1109 }
31a4638f 1110
d62a17ae 1111 /* 10. confed-external vs. confed-internal */
1112 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1113 if (new_sort == BGP_PEER_CONFED
1114 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1115 *reason = bgp_path_selection_confed;
d62a17ae 1116 if (debug)
1117 zlog_debug(
1118 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1119 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1120 if (!CHECK_FLAG(bgp->flags,
1121 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1122 return 1;
1123 peer_sort_ret = 1;
d62a17ae 1124 }
718e3744 1125
d62a17ae 1126 if (exist_sort == BGP_PEER_CONFED
1127 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1128 *reason = bgp_path_selection_confed;
d62a17ae 1129 if (debug)
1130 zlog_debug(
1131 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1132 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1133 if (!CHECK_FLAG(bgp->flags,
1134 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1135 return 0;
1136 peer_sort_ret = 0;
d62a17ae 1137 }
1138 }
718e3744 1139
d62a17ae 1140 /* 11. Maximum path check. */
1141 if (newm == existm) {
1142 /* If one path has a label but the other does not, do not treat
1143 * them as equals for multipath
1144 */
a4d82a8a 1145 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1146 != (exist->extra
b57ba6d2 1147 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1148 if (debug)
1149 zlog_debug(
1150 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1151 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1152 } else if (CHECK_FLAG(bgp->flags,
1153 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1154
1155 /*
1156 * For the two paths, all comparison steps till IGP
1157 * metric
1158 * have succeeded - including AS_PATH hop count. Since
1159 * 'bgp
1160 * bestpath as-path multipath-relax' knob is on, we
1161 * don't need
1162 * an exact match of AS_PATH. Thus, mark the paths are
1163 * equal.
1164 * That will trigger both these paths to get into the
1165 * multipath
1166 * array.
1167 */
1168 *paths_eq = 1;
1169
1170 if (debug)
1171 zlog_debug(
1172 "%s: %s and %s are equal via multipath-relax",
1173 pfx_buf, new_buf, exist_buf);
1174 } else if (new->peer->sort == BGP_PEER_IBGP) {
1175 if (aspath_cmp(new->attr->aspath,
1176 exist->attr->aspath)) {
1177 *paths_eq = 1;
1178
1179 if (debug)
1180 zlog_debug(
1181 "%s: %s and %s are equal via matching aspaths",
1182 pfx_buf, new_buf, exist_buf);
1183 }
1184 } else if (new->peer->as == exist->peer->as) {
1185 *paths_eq = 1;
1186
1187 if (debug)
1188 zlog_debug(
1189 "%s: %s and %s are equal via same remote-as",
1190 pfx_buf, new_buf, exist_buf);
1191 }
1192 } else {
1193 /*
1194 * TODO: If unequal cost ibgp multipath is enabled we can
1195 * mark the paths as equal here instead of returning
1196 */
ee88563a
JM
1197
1198 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1199 * if either step 7 or 10 (peer type checks) yielded a winner,
1200 * that result was returned immediately. Returning from step 10
1201 * ignored the return value computed in steps 8 and 9 (IGP
1202 * metric checks). In order to preserve that behavior, if
1203 * peer_sort_ret is set, return that rather than igp_metric_ret.
1204 */
1205 ret = peer_sort_ret;
1206 if (peer_sort_ret < 0) {
1207 ret = igp_metric_ret;
1208 if (debug) {
1209 if (ret == 1)
1210 zlog_debug(
1211 "%s: %s wins over %s after IGP metric comparison",
1212 pfx_buf, new_buf, exist_buf);
1213 else
1214 zlog_debug(
1215 "%s: %s loses to %s after IGP metric comparison",
1216 pfx_buf, new_buf, exist_buf);
1217 }
1218 *reason = bgp_path_selection_igp_metric;
d62a17ae 1219 }
1220 return ret;
1221 }
718e3744 1222
ee88563a
JM
1223 /*
1224 * At this point, the decision whether to set *paths_eq = 1 has been
1225 * completed. If we deferred returning because of bestpath peer-type
1226 * relax configuration, return now.
1227 */
1228 if (peer_sort_ret >= 0)
1229 return peer_sort_ret;
1230
d62a17ae 1231 /* 12. If both paths are external, prefer the path that was received
1232 first (the oldest one). This step minimizes route-flap, since a
1233 newer path won't displace an older one, even if it was the
1234 preferred route based on the additional decision criteria below. */
892fedb6 1235 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1236 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1237 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1238 *reason = bgp_path_selection_older;
d62a17ae 1239 if (debug)
1240 zlog_debug(
1241 "%s: %s wins over %s due to oldest external",
1242 pfx_buf, new_buf, exist_buf);
1243 return 1;
1244 }
9fbdd100 1245
1defdda8 1246 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1247 *reason = bgp_path_selection_older;
d62a17ae 1248 if (debug)
1249 zlog_debug(
1250 "%s: %s loses to %s due to oldest external",
1251 pfx_buf, new_buf, exist_buf);
1252 return 0;
1253 }
1254 }
718e3744 1255
d62a17ae 1256 /* 13. Router-ID comparision. */
1257 /* If one of the paths is "stale", the corresponding peer router-id will
1258 * be 0 and would always win over the other path. If originator id is
1259 * used for the comparision, it will decide which path is better.
1260 */
1261 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1262 new_id.s_addr = newattr->originator_id.s_addr;
1263 else
1264 new_id.s_addr = new->peer->remote_id.s_addr;
1265 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1266 exist_id.s_addr = existattr->originator_id.s_addr;
1267 else
1268 exist_id.s_addr = exist->peer->remote_id.s_addr;
1269
1270 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1271 *reason = bgp_path_selection_router_id;
d62a17ae 1272 if (debug)
1273 zlog_debug(
1274 "%s: %s wins over %s due to Router-ID comparison",
1275 pfx_buf, new_buf, exist_buf);
1276 return 1;
1277 }
718e3744 1278
d62a17ae 1279 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1280 *reason = bgp_path_selection_router_id;
d62a17ae 1281 if (debug)
1282 zlog_debug(
1283 "%s: %s loses to %s due to Router-ID comparison",
1284 pfx_buf, new_buf, exist_buf);
1285 return 0;
1286 }
9fbdd100 1287
d62a17ae 1288 /* 14. Cluster length comparision. */
1289 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1290 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1291
1292 if (new_cluster < exist_cluster) {
fdf81fa0 1293 *reason = bgp_path_selection_cluster_length;
d62a17ae 1294 if (debug)
1295 zlog_debug(
1296 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1297 pfx_buf, new_buf, exist_buf, new_cluster,
1298 exist_cluster);
1299 return 1;
1300 }
718e3744 1301
d62a17ae 1302 if (new_cluster > exist_cluster) {
fdf81fa0 1303 *reason = bgp_path_selection_cluster_length;
d62a17ae 1304 if (debug)
1305 zlog_debug(
1306 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1307 pfx_buf, new_buf, exist_buf, new_cluster,
1308 exist_cluster);
1309 return 0;
1310 }
9fbdd100 1311
d62a17ae 1312 /* 15. Neighbor address comparision. */
1313 /* Do this only if neither path is "stale" as stale paths do not have
1314 * valid peer information (as the connection may or may not be up).
1315 */
1defdda8 1316 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1317 *reason = bgp_path_selection_stale;
d62a17ae 1318 if (debug)
1319 zlog_debug(
1320 "%s: %s wins over %s due to latter path being STALE",
1321 pfx_buf, new_buf, exist_buf);
1322 return 1;
1323 }
0de5153c 1324
1defdda8 1325 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1326 *reason = bgp_path_selection_stale;
d62a17ae 1327 if (debug)
1328 zlog_debug(
1329 "%s: %s loses to %s due to former path being STALE",
1330 pfx_buf, new_buf, exist_buf);
1331 return 0;
1332 }
718e3744 1333
d62a17ae 1334 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1335 if (new->peer->su_remote == NULL) {
1336 *reason = bgp_path_selection_local_configured;
d62a17ae 1337 return 0;
fdf81fa0
DS
1338 }
1339 if (exist->peer->su_remote == NULL) {
1340 *reason = bgp_path_selection_local_configured;
d62a17ae 1341 return 1;
fdf81fa0 1342 }
9fbdd100 1343
d62a17ae 1344 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1345
1346 if (ret == 1) {
fdf81fa0 1347 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1348 if (debug)
1349 zlog_debug(
1350 "%s: %s loses to %s due to Neighor IP comparison",
1351 pfx_buf, new_buf, exist_buf);
1352 return 0;
1353 }
1354
1355 if (ret == -1) {
fdf81fa0 1356 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1357 if (debug)
1358 zlog_debug(
1359 "%s: %s wins over %s due to Neighor IP comparison",
1360 pfx_buf, new_buf, exist_buf);
1361 return 1;
1362 }
9fbdd100 1363
fdf81fa0 1364 *reason = bgp_path_selection_default;
d62a17ae 1365 if (debug)
1366 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1367 pfx_buf, new_buf, exist_buf);
718e3744 1368
d62a17ae 1369 return 1;
718e3744 1370}
1371
d071f237
AK
1372
1373int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1374 struct bgp_path_info *exist, int *paths_eq)
1375{
1376 enum bgp_path_selection_reason reason;
1377 char pfx_buf[PREFIX2STR_BUFFER];
1378
1379 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1380 AFI_L2VPN, SAFI_EVPN, &reason);
1381}
1382
65efcfce
LB
1383/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1384 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1385 * multipath is enabled
65efcfce 1386 * This version is compatible with */
18ee8310
DS
1387int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1388 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1389 afi_t afi, safi_t safi,
1390 enum bgp_path_selection_reason *reason)
d62a17ae 1391{
1392 int paths_eq;
1393 int ret;
18ee8310 1394 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1395 afi, safi, reason);
d62a17ae 1396
1397 if (paths_eq)
1398 ret = 0;
1399 else {
1400 if (ret == 1)
1401 ret = -1;
1402 else
1403 ret = 1;
1404 }
1405 return ret;
65efcfce
LB
1406}
1407
5a1ae2c2
DS
1408static enum filter_type bgp_input_filter(struct peer *peer,
1409 const struct prefix *p,
d62a17ae 1410 struct attr *attr, afi_t afi,
1411 safi_t safi)
718e3744 1412{
d62a17ae 1413 struct bgp_filter *filter;
6401252f 1414 enum filter_type ret = FILTER_PERMIT;
718e3744 1415
d62a17ae 1416 filter = &peer->filter[afi][safi];
718e3744 1417
d62a17ae 1418#define FILTER_EXIST_WARN(F, f, filter) \
1419 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1420 zlog_debug("%s: Could not find configured input %s-list %s!", \
1421 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1422
1423 if (DISTRIBUTE_IN_NAME(filter)) {
1424 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1425
6401252f
QY
1426 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1427 == FILTER_DENY) {
1428 ret = FILTER_DENY;
1429 goto done;
1430 }
d62a17ae 1431 }
1432
1433 if (PREFIX_LIST_IN_NAME(filter)) {
1434 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1435
6401252f
QY
1436 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1437 == PREFIX_DENY) {
1438 ret = FILTER_DENY;
1439 goto done;
1440 }
d62a17ae 1441 }
1442
1443 if (FILTER_LIST_IN_NAME(filter)) {
1444 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1445
1446 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1447 == AS_FILTER_DENY) {
1448 ret = FILTER_DENY;
1449 goto done;
1450 }
d62a17ae 1451 }
1452
6401252f 1453done:
c7bb4f00 1454 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1455 char pfxprint[PREFIX2STR_BUFFER];
1456
1457 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1458 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1459 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1460 }
1461
1462 return ret;
650f76c2 1463#undef FILTER_EXIST_WARN
718e3744 1464}
1465
b8685f9b
DS
1466static enum filter_type bgp_output_filter(struct peer *peer,
1467 const struct prefix *p,
d62a17ae 1468 struct attr *attr, afi_t afi,
1469 safi_t safi)
718e3744 1470{
d62a17ae 1471 struct bgp_filter *filter;
6401252f 1472 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1473
1474 filter = &peer->filter[afi][safi];
1475
1476#define FILTER_EXIST_WARN(F, f, filter) \
1477 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1478 zlog_debug("%s: Could not find configured output %s-list %s!", \
1479 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1480
d62a17ae 1481 if (DISTRIBUTE_OUT_NAME(filter)) {
1482 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1483
6401252f
QY
1484 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1485 == FILTER_DENY) {
1486 ret = FILTER_DENY;
1487 goto done;
1488 }
d62a17ae 1489 }
1490
1491 if (PREFIX_LIST_OUT_NAME(filter)) {
1492 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1493
d62a17ae 1494 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1495 == PREFIX_DENY) {
1496 ret = FILTER_DENY;
1497 goto done;
1498 }
d62a17ae 1499 }
718e3744 1500
d62a17ae 1501 if (FILTER_LIST_OUT_NAME(filter)) {
1502 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1503
d62a17ae 1504 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1505 == AS_FILTER_DENY) {
1506 ret = FILTER_DENY;
1507 goto done;
1508 }
1509 }
1510
c7bb4f00 1511 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1512 char pfxprint[PREFIX2STR_BUFFER];
1513
1514 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1515 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1516 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1517 }
718e3744 1518
6401252f
QY
1519done:
1520 return ret;
650f76c2 1521#undef FILTER_EXIST_WARN
718e3744 1522}
1523
1524/* If community attribute includes no_export then return 1. */
3dc339cd 1525static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1526{
9a706b42 1527 if (bgp_attr_get_community(attr)) {
d62a17ae 1528 /* NO_ADVERTISE check. */
9a706b42
DA
1529 if (community_include(bgp_attr_get_community(attr),
1530 COMMUNITY_NO_ADVERTISE))
3dc339cd 1531 return true;
d62a17ae 1532
1533 /* NO_EXPORT check. */
9a706b42
DA
1534 if (peer->sort == BGP_PEER_EBGP &&
1535 community_include(bgp_attr_get_community(attr),
1536 COMMUNITY_NO_EXPORT))
3dc339cd 1537 return true;
d62a17ae 1538
1539 /* NO_EXPORT_SUBCONFED check. */
1540 if (peer->sort == BGP_PEER_EBGP
1541 || peer->sort == BGP_PEER_CONFED)
9a706b42 1542 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1543 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1544 return true;
d62a17ae 1545 }
3dc339cd 1546 return false;
718e3744 1547}
1548
1549/* Route reflection loop check. */
3dc339cd 1550static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1551{
d62a17ae 1552 struct in_addr cluster_id;
779fee93 1553 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1554
779fee93 1555 if (cluster) {
d62a17ae 1556 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1557 cluster_id = peer->bgp->cluster_id;
1558 else
1559 cluster_id = peer->bgp->router_id;
1560
779fee93 1561 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1562 return true;
d62a17ae 1563 }
3dc339cd 1564 return false;
718e3744 1565}
6b0655a2 1566
5a1ae2c2 1567static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1568 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1569 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1570 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1571{
d62a17ae 1572 struct bgp_filter *filter;
82b692c0
LK
1573 struct bgp_path_info rmap_path = { 0 };
1574 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1575 route_map_result_t ret;
1576 struct route_map *rmap = NULL;
718e3744 1577
d62a17ae 1578 filter = &peer->filter[afi][safi];
718e3744 1579
d62a17ae 1580 /* Apply default weight value. */
1581 if (peer->weight[afi][safi])
1582 attr->weight = peer->weight[afi][safi];
718e3744 1583
d62a17ae 1584 if (rmap_name) {
1585 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1586
d62a17ae 1587 if (rmap == NULL)
1588 return RMAP_DENY;
1589 } else {
1590 if (ROUTE_MAP_IN_NAME(filter)) {
1591 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1592
d62a17ae 1593 if (rmap == NULL)
1594 return RMAP_DENY;
1595 }
1596 }
0b16f239 1597
d62a17ae 1598 /* Route map apply. */
1599 if (rmap) {
40381db7 1600 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1601 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1602 rmap_path.peer = peer;
1603 rmap_path.attr = attr;
82b692c0 1604 rmap_path.extra = &extra;
9bcb3eef 1605 rmap_path.net = dest;
196c6b09 1606
82b692c0
LK
1607 extra.num_labels = num_labels;
1608 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1609 memcpy(extra.label, label,
1610 num_labels * sizeof(mpls_label_t));
718e3744 1611
d62a17ae 1612 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1613
d62a17ae 1614 /* Apply BGP route map to the attribute. */
1782514f 1615 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1616
d62a17ae 1617 peer->rmap_type = 0;
0b16f239 1618
1f2263be 1619 if (ret == RMAP_DENYMATCH)
d62a17ae 1620 return RMAP_DENY;
0b16f239 1621 }
d62a17ae 1622 return RMAP_PERMIT;
0b16f239
DS
1623}
1624
5f040085 1625static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1626 struct attr *attr, afi_t afi, safi_t safi,
1627 const char *rmap_name)
0b16f239 1628{
40381db7 1629 struct bgp_path_info rmap_path;
d62a17ae 1630 route_map_result_t ret;
1631 struct route_map *rmap = NULL;
d7c0a89a 1632 uint8_t rmap_type;
0b16f239 1633
b787157a
DS
1634 /*
1635 * So if we get to this point and have no rmap_name
1636 * we want to just show the output as it currently
1637 * exists.
1638 */
1639 if (!rmap_name)
1640 return RMAP_PERMIT;
0b16f239 1641
d62a17ae 1642 /* Apply default weight value. */
1643 if (peer->weight[afi][safi])
1644 attr->weight = peer->weight[afi][safi];
0b16f239 1645
b787157a 1646 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1647
b787157a
DS
1648 /*
1649 * If we have a route map name and we do not find
1650 * the routemap that means we have an implicit
1651 * deny.
1652 */
1653 if (rmap == NULL)
1654 return RMAP_DENY;
0b16f239 1655
40381db7 1656 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1657 /* Route map apply. */
b787157a 1658 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1659 rmap_path.peer = peer;
1660 rmap_path.attr = attr;
0b16f239 1661
0f672529 1662 rmap_type = peer->rmap_type;
b787157a 1663 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1664
b787157a 1665 /* Apply BGP route map to the attribute. */
1782514f 1666 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1667
0f672529 1668 peer->rmap_type = rmap_type;
b787157a
DS
1669
1670 if (ret == RMAP_DENYMATCH)
1671 /*
1672 * caller has multiple error paths with bgp_attr_flush()
1673 */
1674 return RMAP_DENY;
ac41b2a2 1675
d62a17ae 1676 return RMAP_PERMIT;
718e3744 1677}
6b0655a2 1678
5000f21c 1679/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1680static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1681 struct peer *peer, struct attr *attr)
1682{
1683 if (peer->sort == BGP_PEER_EBGP
1684 && (peer_af_flag_check(peer, afi, safi,
1685 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1686 || peer_af_flag_check(peer, afi, safi,
1687 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1688 || peer_af_flag_check(peer, afi, safi,
1689 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1690 || peer_af_flag_check(peer, afi, safi,
1691 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1692 // Take action on the entire aspath
1693 if (peer_af_flag_check(peer, afi, safi,
1694 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1695 || peer_af_flag_check(peer, afi, safi,
1696 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1697 if (peer_af_flag_check(
1698 peer, afi, safi,
1699 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1700 attr->aspath = aspath_replace_private_asns(
bf26b80e 1701 attr->aspath, bgp->as, peer->as);
d62a17ae 1702
179d5a0e
TA
1703 /*
1704 * Even if the aspath consists of just private ASNs we
1705 * need to walk the AS-Path to maintain all instances
1706 * of the peer's ASN to break possible loops.
1707 */
d62a17ae 1708 else
1709 attr->aspath = aspath_remove_private_asns(
bf26b80e 1710 attr->aspath, peer->as);
d62a17ae 1711 }
1712
1713 // 'all' was not specified so the entire aspath must be private
1714 // ASNs
1715 // for us to do anything
1716 else if (aspath_private_as_check(attr->aspath)) {
1717 if (peer_af_flag_check(
1718 peer, afi, safi,
1719 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1720 attr->aspath = aspath_replace_private_asns(
bf26b80e 1721 attr->aspath, bgp->as, peer->as);
d62a17ae 1722 else
179d5a0e
TA
1723 /*
1724 * Walk the aspath to retain any instances of
1725 * the peer_asn
1726 */
1727 attr->aspath = aspath_remove_private_asns(
1728 attr->aspath, peer->as);
d62a17ae 1729 }
1730 }
5000f21c
DS
1731}
1732
c7122e14 1733/* If this is an EBGP peer with as-override */
d62a17ae 1734static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1735 struct peer *peer, struct attr *attr)
1736{
1737 if (peer->sort == BGP_PEER_EBGP
1738 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1739 if (aspath_single_asn_check(attr->aspath, peer->as))
1740 attr->aspath = aspath_replace_specific_asn(
1741 attr->aspath, peer->as, bgp->as);
1742 }
1743}
1744
1479ed2f
DA
1745void bgp_attr_add_llgr_community(struct attr *attr)
1746{
1747 struct community *old;
1748 struct community *new;
1749 struct community *merge;
1750 struct community *llgr;
1751
9a706b42 1752 old = bgp_attr_get_community(attr);
1479ed2f
DA
1753 llgr = community_str2com("llgr-stale");
1754
1755 assert(llgr);
1756
1757 if (old) {
1758 merge = community_merge(community_dup(old), llgr);
1759
1760 if (old->refcnt == 0)
1761 community_free(&old);
1762
1763 new = community_uniq_sort(merge);
1764 community_free(&merge);
1765 } else {
1766 new = community_dup(llgr);
1767 }
1768
1769 community_free(&llgr);
1770
9a706b42 1771 bgp_attr_set_community(attr, new);
1479ed2f
DA
1772 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1773}
1774
7f323236
DW
1775void bgp_attr_add_gshut_community(struct attr *attr)
1776{
1777 struct community *old;
1778 struct community *new;
1779 struct community *merge;
1780 struct community *gshut;
1781
9a706b42 1782 old = bgp_attr_get_community(attr);
7f323236
DW
1783 gshut = community_str2com("graceful-shutdown");
1784
990f4f91 1785 assert(gshut);
1786
7f323236
DW
1787 if (old) {
1788 merge = community_merge(community_dup(old), gshut);
1789
a4d82a8a 1790 if (old->refcnt == 0)
3c1f53de 1791 community_free(&old);
7f323236
DW
1792
1793 new = community_uniq_sort(merge);
3c1f53de 1794 community_free(&merge);
7f323236
DW
1795 } else {
1796 new = community_dup(gshut);
1797 }
1798
3c1f53de 1799 community_free(&gshut);
9a706b42 1800 bgp_attr_set_community(attr, new);
7f323236
DW
1801 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1802
1803 /* When we add the graceful-shutdown community we must also
1804 * lower the local-preference */
1805 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1806 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1807}
1808
1809
e73c112e
MK
1810/* Notify BGP Conditional advertisement scanner process. */
1811void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1812{
e73c112e 1813 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1814 afi_t afi = SUBGRP_AFI(subgrp);
1815 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1816 struct bgp_filter *filter = &peer->filter[afi][safi];
1817
1818 if (!ADVERTISE_MAP_NAME(filter))
1819 return;
1820
52979c3b
DS
1821 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1822 return;
e73c112e 1823
52979c3b 1824 peer->advmap_table_change = true;
e73c112e
MK
1825}
1826
1827
f2ee6d5c 1828void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1829{
960035b2 1830 if (family == AF_INET) {
975a328e
DA
1831 attr->nexthop.s_addr = INADDR_ANY;
1832 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1833 }
d62a17ae 1834 if (family == AF_INET6)
1835 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1836 if (family == AF_EVPN)
1837 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1838}
1839
9bcb3eef 1840bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1841 struct update_subgroup *subgrp,
7f7940e6 1842 const struct prefix *p, struct attr *attr,
51c3a7de 1843 struct attr *post_attr)
d62a17ae 1844{
1845 struct bgp_filter *filter;
1846 struct peer *from;
1847 struct peer *peer;
1848 struct peer *onlypeer;
1849 struct bgp *bgp;
40381db7 1850 struct attr *piattr;
b68885f9 1851 route_map_result_t ret;
d62a17ae 1852 int transparent;
1853 int reflect;
1854 afi_t afi;
1855 safi_t safi;
1856 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1857 bool nh_reset = false;
1858 uint64_t cum_bw;
d62a17ae 1859
1860 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1861 return false;
d62a17ae 1862
1863 afi = SUBGRP_AFI(subgrp);
1864 safi = SUBGRP_SAFI(subgrp);
1865 peer = SUBGRP_PEER(subgrp);
1866 onlypeer = NULL;
1867 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1868 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1869
40381db7 1870 from = pi->peer;
d62a17ae 1871 filter = &peer->filter[afi][safi];
1872 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1873 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1874 : pi->attr;
3f9c7369 1875
d0bf49ec
LS
1876 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1877 peer->pmax_out[afi][safi] != 0 &&
1878 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1879 if (BGP_DEBUG(update, UPDATE_OUT) ||
1880 BGP_DEBUG(update, UPDATE_PREFIX)) {
1881 zlog_debug("%s reached maximum prefix to be send (%u)",
1882 peer->host, peer->pmax_out[afi][safi]);
1883 }
1884 return false;
1885 }
1886
49e5a4a0 1887#ifdef ENABLE_BGP_VNC
d62a17ae 1888 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1889 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1890 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1891
1892 /*
1893 * direct and direct_ext type routes originate internally even
1894 * though they can have peer pointers that reference other
1895 * systems
1896 */
8228a9a7
DS
1897 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1898 __func__, p);
d62a17ae 1899 samepeer_safe = 1;
1900 }
65efcfce
LB
1901#endif
1902
ddb5b488
PZ
1903 if (((afi == AFI_IP) || (afi == AFI_IP6))
1904 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1905 && (pi->type == ZEBRA_ROUTE_BGP)
1906 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1907
1908 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1909
1910 samepeer_safe = 1;
1911 }
1912
d62a17ae 1913 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1914 * pi is valid */
1915 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1916 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1917 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1918 return false;
d62a17ae 1919 }
adbac85e 1920
d62a17ae 1921 /* If this is not the bestpath then check to see if there is an enabled
1922 * addpath
1923 * feature that requires us to advertise it */
40381db7 1924 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1925 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1926 return false;
d62a17ae 1927 }
1928 }
06370dac 1929
d62a17ae 1930 /* Aggregate-address suppress check. */
4056a5f6
RZ
1931 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1932 return false;
3f9c7369 1933
13b7e7f0
DS
1934 /*
1935 * If we are doing VRF 2 VRF leaking via the import
1936 * statement, we want to prevent the route going
1937 * off box as that the RT and RD created are localy
1938 * significant and globaly useless.
1939 */
40381db7
DS
1940 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1941 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1942 return false;
13b7e7f0 1943
d62a17ae 1944 /* If it's labeled safi, make sure the route has a valid label. */
1945 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1946 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1947 if (!bgp_is_valid_label(&label)) {
1948 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1949 zlog_debug("u%" PRIu64 ":s%" PRIu64
1950 " %pFX is filtered - no label (%p)",
d62a17ae 1951 subgrp->update_group->id, subgrp->id,
8228a9a7 1952 p, &label);
3dc339cd 1953 return false;
d62a17ae 1954 }
1955 }
cd1964ff 1956
d62a17ae 1957 /* Do not send back route to sender. */
1958 if (onlypeer && from == onlypeer) {
3dc339cd 1959 return false;
d62a17ae 1960 }
3f9c7369 1961
d62a17ae 1962 /* Do not send the default route in the BGP table if the neighbor is
1963 * configured for default-originate */
1964 if (CHECK_FLAG(peer->af_flags[afi][safi],
1965 PEER_FLAG_DEFAULT_ORIGINATE)) {
1966 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1967 return false;
d62a17ae 1968 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1969 return false;
d62a17ae 1970 }
4125bb67 1971
d62a17ae 1972 /* Transparency check. */
1973 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1974 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1975 transparent = 1;
1976 else
1977 transparent = 0;
1978
1979 /* If community is not disabled check the no-export and local. */
40381db7 1980 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1981 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1982 zlog_debug("%s: community filter check fail for %pFX",
1983 __func__, p);
3dc339cd 1984 return false;
d62a17ae 1985 }
3f9c7369 1986
d62a17ae 1987 /* If the attribute has originator-id and it is same as remote
1988 peer's id. */
40381db7
DS
1989 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1990 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1991 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1992 zlog_debug(
8228a9a7
DS
1993 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1994 onlypeer->host, p);
3dc339cd 1995 return false;
d62a17ae 1996 }
3f9c7369 1997
d62a17ae 1998 /* ORF prefix-list filter check */
1999 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2000 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2001 || CHECK_FLAG(peer->af_cap[afi][safi],
2002 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2003 if (peer->orf_plist[afi][safi]) {
2004 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2005 == PREFIX_DENY) {
2006 if (bgp_debug_update(NULL, p,
2007 subgrp->update_group, 0))
2008 zlog_debug(
8228a9a7
DS
2009 "%s [Update:SEND] %pFX is filtered via ORF",
2010 peer->host, p);
3dc339cd 2011 return false;
d62a17ae 2012 }
2013 }
2014
2015 /* Output filter check. */
40381db7 2016 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2017 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2018 zlog_debug("%s [Update:SEND] %pFX is filtered",
2019 peer->host, p);
3dc339cd 2020 return false;
d62a17ae 2021 }
3f9c7369 2022
d62a17ae 2023 /* AS path loop check. */
2b31007c
RZ
2024 if (onlypeer && onlypeer->as_path_loop_detection
2025 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2026 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2027 zlog_debug(
3efd0893 2028 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 2029 onlypeer->host, onlypeer->as);
3dc339cd 2030 return false;
d62a17ae 2031 }
3f9c7369 2032
d62a17ae 2033 /* If we're a CONFED we need to loop check the CONFED ID too */
2034 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2035 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2036 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2037 zlog_debug(
3efd0893 2038 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 2039 peer->host, bgp->confed_id);
3dc339cd 2040 return false;
d62a17ae 2041 }
3f9c7369 2042 }
3f9c7369 2043
d62a17ae 2044 /* Route-Reflect check. */
2045 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2046 reflect = 1;
2047 else
2048 reflect = 0;
2049
2050 /* IBGP reflection check. */
2051 if (reflect && !samepeer_safe) {
2052 /* A route from a Client peer. */
2053 if (CHECK_FLAG(from->af_flags[afi][safi],
2054 PEER_FLAG_REFLECTOR_CLIENT)) {
2055 /* Reflect to all the Non-Client peers and also to the
2056 Client peers other than the originator. Originator
2057 check
2058 is already done. So there is noting to do. */
2059 /* no bgp client-to-client reflection check. */
892fedb6
DA
2060 if (CHECK_FLAG(bgp->flags,
2061 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2062 if (CHECK_FLAG(peer->af_flags[afi][safi],
2063 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2064 return false;
d62a17ae 2065 } else {
2066 /* A route from a Non-client peer. Reflect to all other
2067 clients. */
2068 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2069 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2070 return false;
d62a17ae 2071 }
2072 }
3f9c7369 2073
51c3a7de
DA
2074 /* For modify attribute, copy it to temporary structure.
2075 * post_attr comes from BGP conditional advertisements, where
2076 * attributes are already processed by advertise-map route-map,
2077 * and this needs to be saved instead of overwriting from the
2078 * path attributes.
2079 */
2080 if (post_attr)
2081 *attr = *post_attr;
2082 else
2083 *attr = *piattr;
d62a17ae 2084
2085 /* If local-preference is not set. */
2086 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2087 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2088 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2089 attr->local_pref = bgp->default_local_pref;
3f9c7369 2090 }
3f9c7369 2091
d62a17ae 2092 /* If originator-id is not set and the route is to be reflected,
2093 set the originator id */
2094 if (reflect
2095 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2096 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2097 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2098 }
3f9c7369 2099
d62a17ae 2100 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2101 */
2102 if (peer->sort == BGP_PEER_EBGP
2103 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2104 if (from != bgp->peer_self && !transparent
2105 && !CHECK_FLAG(peer->af_flags[afi][safi],
2106 PEER_FLAG_MED_UNCHANGED))
2107 attr->flag &=
2108 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2109 }
3f9c7369 2110
d62a17ae 2111 /* Since the nexthop attribute can vary per peer, it is not explicitly
2112 * set
2113 * in announce check, only certain flags and length (or number of
2114 * nexthops
2115 * -- for IPv6/MP_REACH) are set here in order to guide the update
2116 * formation
2117 * code in setting the nexthop(s) on a per peer basis in
2118 * reformat_peer().
2119 * Typically, the source nexthop in the attribute is preserved but in
2120 * the
2121 * scenarios where we know it will always be overwritten, we reset the
2122 * nexthop to "0" in an attempt to achieve better Update packing. An
2123 * example of this is when a prefix from each of 2 IBGP peers needs to
2124 * be
2125 * announced to an EBGP peer (and they have the same attributes barring
2126 * their nexthop).
2127 */
2128 if (reflect)
2129 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2130
2131#define NEXTHOP_IS_V6 \
2132 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2133 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2134 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2135 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2136
2137 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2138 * if
2139 * the peer (group) is configured to receive link-local nexthop
2140 * unchanged
c728d027
DA
2141 * and it is available in the prefix OR we're not reflecting the route,
2142 * link-local nexthop address is valid and
d62a17ae 2143 * the peer (group) to whom we're going to announce is on a shared
2144 * network
2145 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2146 * By checking if nexthop LL address is valid we are sure that
2147 * we do not announce LL address as `::`.
d62a17ae 2148 */
2149 if (NEXTHOP_IS_V6) {
2150 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2151 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2152 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2153 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2154 || (!reflect && !transparent
c728d027
DA
2155 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2156 && peer->shared_network
d62a17ae 2157 && (from == bgp->peer_self
2158 || peer->sort == BGP_PEER_EBGP))) {
2159 attr->mp_nexthop_len =
2160 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2161 }
3f9c7369 2162
d62a17ae 2163 /* Clear off link-local nexthop in source, whenever it is not
2164 * needed to
2165 * ensure more prefixes share the same attribute for
2166 * announcement.
2167 */
2168 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2169 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2170 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2171 }
3f9c7369 2172
d62a17ae 2173 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2174 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2175
2176 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2177 if (!post_attr &&
2178 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2179 struct bgp_path_info rmap_path = {0};
2180 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2181 struct attr dummy_attr = {0};
d62a17ae 2182
e34291b8 2183 /* Fill temp path_info */
9bcb3eef
DS
2184 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2185 pi, peer, attr);
16f7ce2b 2186
d62a17ae 2187 /* don't confuse inbound and outbound setting */
2188 RESET_FLAG(attr->rmap_change_flags);
2189
2190 /*
2191 * The route reflector is not allowed to modify the attributes
2192 * of the reflected IBGP routes unless explicitly allowed.
2193 */
2194 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2195 && !CHECK_FLAG(bgp->flags,
2196 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2197 dummy_attr = *attr;
40381db7 2198 rmap_path.attr = &dummy_attr;
d62a17ae 2199 }
3f9c7369 2200
d62a17ae 2201 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2202
4056a5f6 2203 if (bgp_path_suppressed(pi))
d62a17ae 2204 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2205 &rmap_path);
d62a17ae 2206 else
2207 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2208 &rmap_path);
d62a17ae 2209
2210 peer->rmap_type = 0;
2211
2212 if (ret == RMAP_DENYMATCH) {
778048bf 2213 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2214 zlog_debug(
02494580
DA
2215 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2216 peer->host, p,
2217 ROUTE_MAP_OUT_NAME(filter));
778048bf 2218
686826e9 2219 bgp_attr_flush(&dummy_attr);
3dc339cd 2220 return false;
d62a17ae 2221 }
3f9c7369 2222 }
3f9c7369 2223
9dac9fc8
DA
2224 /* RFC 8212 to prevent route leaks.
2225 * This specification intends to improve this situation by requiring the
2226 * explicit configuration of both BGP Import and Export Policies for any
2227 * External BGP (EBGP) session such as customers, peers, or
2228 * confederation boundaries for all enabled address families. Through
2229 * codification of the aforementioned requirement, operators will
2230 * benefit from consistent behavior across different BGP
2231 * implementations.
2232 */
1d3fdccf 2233 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2234 if (!bgp_outbound_policy_exists(peer, filter)) {
2235 if (monotime_since(&bgp->ebgprequirespolicywarning,
2236 NULL) > FIFTEENMINUTE2USEC ||
2237 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2238 zlog_warn(
2239 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2240 monotime(&bgp->ebgprequirespolicywarning);
2241 }
3dc339cd 2242 return false;
b17826b7 2243 }
9dac9fc8 2244
fb29348a
DA
2245 /* draft-ietf-idr-deprecate-as-set-confed-set
2246 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2247 * Eventually, This document (if approved) updates RFC 4271
2248 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2249 * and obsoletes RFC 6472.
2250 */
7f972cd8 2251 if (peer->bgp->reject_as_sets)
fb29348a 2252 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2253 return false;
fb29348a 2254
33d022bc
DA
2255 /* Codification of AS 0 Processing */
2256 if (aspath_check_as_zero(attr->aspath))
e2369003 2257 return false;
33d022bc 2258
637e5ba4 2259 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2260 if (peer->sort == BGP_PEER_IBGP
2261 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2262 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2263 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2264 } else {
2265 bgp_attr_add_gshut_community(attr);
2266 }
2267 }
2268
1479ed2f
DA
2269 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2270 * Capability" to a neighbor MUST perform the following upon receiving
2271 * a route from that neighbor with the "LLGR_STALE" community, or upon
2272 * attaching the "LLGR_STALE" community itself per Section 4.2:
2273 *
2274 * The route SHOULD NOT be advertised to any neighbor from which the
2275 * Long-lived Graceful Restart Capability has not been received.
2276 */
9a706b42
DA
2277 if (bgp_attr_get_community(attr) &&
2278 community_include(bgp_attr_get_community(attr),
2279 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2280 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2281 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2282 return false;
2283
d62a17ae 2284 /* After route-map has been applied, we check to see if the nexthop to
2285 * be carried in the attribute (that is used for the announcement) can
2286 * be cleared off or not. We do this in all cases where we would be
2287 * setting the nexthop to "ourselves". For IPv6, we only need to
2288 * consider
2289 * the global nexthop here; the link-local nexthop would have been
2290 * cleared
2291 * already, and if not, it is required by the update formation code.
2292 * Also see earlier comments in this function.
2293 */
2294 /*
2295 * If route-map has performed some operation on the nexthop or the peer
2296 * configuration says to pass it unchanged, we cannot reset the nexthop
2297 * here, so only attempt to do it if these aren't true. Note that the
2298 * route-map handler itself might have cleared the nexthop, if for
2299 * example,
2300 * it is configured as 'peer-address'.
2301 */
2302 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2303 piattr->rmap_change_flags)
d62a17ae 2304 && !transparent
2305 && !CHECK_FLAG(peer->af_flags[afi][safi],
2306 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2307 /* We can reset the nexthop, if setting (or forcing) it to
2308 * 'self' */
2309 if (CHECK_FLAG(peer->af_flags[afi][safi],
2310 PEER_FLAG_NEXTHOP_SELF)
2311 || CHECK_FLAG(peer->af_flags[afi][safi],
2312 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2313 if (!reflect
2314 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2315 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2316 subgroup_announce_reset_nhop(
2317 (peer_cap_enhe(peer, afi, safi)
2318 ? AF_INET6
2319 : p->family),
2320 attr);
7b651a32 2321 nh_reset = true;
2322 }
d62a17ae 2323 } else if (peer->sort == BGP_PEER_EBGP) {
2324 /* Can also reset the nexthop if announcing to EBGP, but
2325 * only if
2326 * no peer in the subgroup is on a shared subnet.
2327 * Note: 3rd party nexthop currently implemented for
2328 * IPv4 only.
2329 */
737af885
BS
2330 if ((p->family == AF_INET) &&
2331 (!bgp_subgrp_multiaccess_check_v4(
2332 piattr->nexthop,
7b651a32 2333 subgrp, from))) {
d62a17ae 2334 subgroup_announce_reset_nhop(
2335 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2336 ? AF_INET6
2337 : p->family),
737af885 2338 attr);
7b651a32 2339 nh_reset = true;
2340 }
737af885
BS
2341
2342 if ((p->family == AF_INET6) &&
2343 (!bgp_subgrp_multiaccess_check_v6(
2344 piattr->mp_nexthop_global,
7b651a32 2345 subgrp, from))) {
737af885
BS
2346 subgroup_announce_reset_nhop(
2347 (peer_cap_enhe(peer, afi, safi)
2348 ? AF_INET6
2349 : p->family),
2350 attr);
7b651a32 2351 nh_reset = true;
2352 }
737af885
BS
2353
2354
2355
40381db7 2356 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2357 /*
2358 * This flag is used for leaked vpn-vrf routes
2359 */
2360 int family = p->family;
2361
2362 if (peer_cap_enhe(peer, afi, safi))
2363 family = AF_INET6;
2364
2365 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2366 zlog_debug(
1defdda8 2367 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2368 __func__, family2str(family));
2369 subgroup_announce_reset_nhop(family, attr);
7b651a32 2370 nh_reset = true;
d62a17ae 2371 }
63696f1d 2372 }
960035b2 2373
63696f1d 2374 /* If IPv6/MP and nexthop does not have any override and happens
2375 * to
2376 * be a link-local address, reset it so that we don't pass along
2377 * the
2378 * source's link-local IPv6 address to recipients who may not be
2379 * on
2380 * the same interface.
2381 */
2382 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2383 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2384 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2385 nh_reset = true;
2386 }
d62a17ae 2387 }
3f9c7369 2388
7b651a32 2389 /*
2390 * When the next hop is set to ourselves, if all multipaths have
2391 * link-bandwidth announce the cumulative bandwidth as that makes
2392 * the most sense. However, don't modify if the link-bandwidth has
2393 * been explicitly set by user policy.
2394 */
2395 if (nh_reset &&
f7e1c681 2396 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2397 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2398 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2399 bgp_attr_set_ecommunity(
2400 attr,
2401 ecommunity_replace_linkbw(
2402 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2403 CHECK_FLAG(
2404 peer->flags,
2405 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2406
3dc339cd 2407 return true;
3f9c7369
DS
2408}
2409
cc9f21da 2410static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2411{
2412 struct afi_safi_info *info;
2413 afi_t afi;
2414 safi_t safi;
2415 struct bgp *bgp;
2416
2417 info = THREAD_ARG(thread);
2418 afi = info->afi;
2419 safi = info->safi;
2420 bgp = info->bgp;
2421
2422 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2423 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2424 safi);
f009ff26 2425
2426 bgp->gr_info[afi][safi].t_route_select = NULL;
2427
2428 XFREE(MTYPE_TMP, info);
2429
2430 /* Best path selection */
cc9f21da 2431 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2432}
2433
9bcb3eef 2434void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2435 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2436 struct bgp_path_info_pair *result, afi_t afi,
2437 safi_t safi)
2438{
2439 struct bgp_path_info *new_select;
2440 struct bgp_path_info *old_select;
40381db7
DS
2441 struct bgp_path_info *pi;
2442 struct bgp_path_info *pi1;
2443 struct bgp_path_info *pi2;
2444 struct bgp_path_info *nextpi = NULL;
d62a17ae 2445 int paths_eq, do_mpath, debug;
2446 struct list mp_list;
2447 char pfx_buf[PREFIX2STR_BUFFER];
2448 char path_buf[PATH_ADDPATH_STR_BUFFER];
2449
2450 bgp_mp_list_init(&mp_list);
2451 do_mpath =
2452 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2453
9bcb3eef 2454 debug = bgp_debug_bestpath(dest);
d62a17ae 2455
2456 if (debug)
9bcb3eef 2457 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2458
9bcb3eef 2459 dest->reason = bgp_path_selection_none;
d62a17ae 2460 /* bgp deterministic-med */
2461 new_select = NULL;
892fedb6 2462 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2463
1defdda8 2464 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2465 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2466 pi1 = pi1->next)
9bcb3eef 2467 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2468 BGP_PATH_DMED_SELECTED);
d62a17ae 2469
9bcb3eef 2470 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2471 pi1 = pi1->next) {
40381db7 2472 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2473 continue;
40381db7 2474 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2475 continue;
ea8b2282 2476 if (pi1->peer != bgp->peer_self)
feb17238 2477 if (!peer_established(pi1->peer))
d62a17ae 2478 continue;
2479
40381db7
DS
2480 new_select = pi1;
2481 if (pi1->next) {
2482 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2483 if (CHECK_FLAG(pi2->flags,
1defdda8 2484 BGP_PATH_DMED_CHECK))
d62a17ae 2485 continue;
40381db7 2486 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2487 continue;
ea8b2282 2488 if (pi2->peer != bgp->peer_self
d62a17ae 2489 && !CHECK_FLAG(
ea8b2282
DS
2490 pi2->peer->sflags,
2491 PEER_STATUS_NSF_WAIT))
40381db7 2492 if (pi2->peer->status
d62a17ae 2493 != Established)
2494 continue;
2495
121e245d
DS
2496 if (!aspath_cmp_left(pi1->attr->aspath,
2497 pi2->attr->aspath)
2498 && !aspath_cmp_left_confed(
40381db7 2499 pi1->attr->aspath,
121e245d
DS
2500 pi2->attr->aspath))
2501 continue;
d62a17ae 2502
121e245d
DS
2503 if (bgp_path_info_cmp(
2504 bgp, pi2, new_select,
2505 &paths_eq, mpath_cfg, debug,
fdf81fa0 2506 pfx_buf, afi, safi,
9bcb3eef 2507 &dest->reason)) {
121e245d 2508 bgp_path_info_unset_flag(
9bcb3eef 2509 dest, new_select,
121e245d
DS
2510 BGP_PATH_DMED_SELECTED);
2511 new_select = pi2;
d62a17ae 2512 }
121e245d
DS
2513
2514 bgp_path_info_set_flag(
9bcb3eef 2515 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2516 }
2517 }
9bcb3eef 2518 bgp_path_info_set_flag(dest, new_select,
18ee8310 2519 BGP_PATH_DMED_CHECK);
9bcb3eef 2520 bgp_path_info_set_flag(dest, new_select,
18ee8310 2521 BGP_PATH_DMED_SELECTED);
d62a17ae 2522
2523 if (debug) {
18ee8310 2524 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2525 new_select, path_buf, sizeof(path_buf));
8228a9a7 2526 zlog_debug(
4378495a
DS
2527 "%pBD(%s): %s is the bestpath from AS %u",
2528 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2529 aspath_get_first_as(
2530 new_select->attr->aspath));
d62a17ae 2531 }
2532 }
2533 }
96450faf 2534
d62a17ae 2535 /* Check old selected route and new selected route. */
2536 old_select = NULL;
2537 new_select = NULL;
9bcb3eef 2538 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2539 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2540 enum bgp_path_selection_reason reason;
2541
40381db7
DS
2542 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2543 old_select = pi;
d62a17ae 2544
40381db7 2545 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2546 /* reap REMOVED routes, if needs be
2547 * selected route must stay for a while longer though
2548 */
40381db7
DS
2549 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2550 && (pi != old_select))
9bcb3eef 2551 bgp_path_info_reap(dest, pi);
d62a17ae 2552
ddb5b488 2553 if (debug)
40381db7
DS
2554 zlog_debug("%s: pi %p in holddown", __func__,
2555 pi);
ddb5b488 2556
d62a17ae 2557 continue;
2558 }
96450faf 2559
40381db7
DS
2560 if (pi->peer && pi->peer != bgp->peer_self
2561 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2562 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2563
2564 if (debug)
2565 zlog_debug(
40381db7
DS
2566 "%s: pi %p non self peer %s not estab state",
2567 __func__, pi, pi->peer->host);
ddb5b488 2568
d62a17ae 2569 continue;
ddb5b488 2570 }
9fbdd100 2571
892fedb6 2572 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2573 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2574 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2575 if (debug)
40381db7 2576 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2577 continue;
2578 }
9fbdd100 2579
9bcb3eef 2580 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2581
9bcb3eef 2582 reason = dest->reason;
40381db7 2583 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2584 debug, pfx_buf, afi, safi,
2585 &dest->reason)) {
19ea4cec
DS
2586 if (new_select == NULL &&
2587 reason != bgp_path_selection_none)
9bcb3eef 2588 dest->reason = reason;
40381db7 2589 new_select = pi;
d62a17ae 2590 }
2591 }
718e3744 2592
d62a17ae 2593 /* Now that we know which path is the bestpath see if any of the other
2594 * paths
2595 * qualify as multipaths
2596 */
2597 if (debug) {
2598 if (new_select)
7533cad7
QY
2599 bgp_path_info_path_with_addpath_rx_str(
2600 new_select, path_buf, sizeof(path_buf));
d62a17ae 2601 else
772270f3 2602 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2603 zlog_debug(
4378495a
DS
2604 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2605 dest, bgp->name_pretty, path_buf,
d62a17ae 2606 old_select ? old_select->peer->host : "NONE");
96450faf 2607 }
9fbdd100 2608
d62a17ae 2609 if (do_mpath && new_select) {
9bcb3eef 2610 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2611 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2612
2613 if (debug)
18ee8310 2614 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2615 pi, path_buf, sizeof(path_buf));
d62a17ae 2616
40381db7 2617 if (pi == new_select) {
d62a17ae 2618 if (debug)
2619 zlog_debug(
4378495a
DS
2620 "%pBD(%s): %s is the bestpath, add to the multipath list",
2621 dest, bgp->name_pretty,
2622 path_buf);
40381db7 2623 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2624 continue;
2625 }
2626
40381db7 2627 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2628 continue;
2629
40381db7
DS
2630 if (pi->peer && pi->peer != bgp->peer_self
2631 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2632 PEER_STATUS_NSF_WAIT))
feb17238 2633 if (!peer_established(pi->peer))
d62a17ae 2634 continue;
2635
40381db7 2636 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2637 if (debug)
2638 zlog_debug(
8228a9a7
DS
2639 "%pBD: %s has the same nexthop as the bestpath, skip it",
2640 dest, path_buf);
d62a17ae 2641 continue;
2642 }
2643
40381db7 2644 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2645 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2646 &dest->reason);
d62a17ae 2647
2648 if (paths_eq) {
2649 if (debug)
2650 zlog_debug(
8228a9a7
DS
2651 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2652 dest, path_buf);
40381db7 2653 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2654 }
2655 }
2656 }
fee0f4c6 2657
4378495a 2658 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2659 mpath_cfg);
2660 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2661 bgp_mp_list_clear(&mp_list);
96450faf 2662
9bcb3eef 2663 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2664
d62a17ae 2665 result->old = old_select;
2666 result->new = new_select;
96450faf 2667
d62a17ae 2668 return;
fee0f4c6 2669}
2670
3f9c7369
DS
2671/*
2672 * A new route/change in bestpath of an existing route. Evaluate the path
2673 * for advertisement to the subgroup.
2674 */
3dc339cd
DA
2675void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2676 struct bgp_path_info *selected,
9bcb3eef 2677 struct bgp_dest *dest,
3dc339cd 2678 uint32_t addpath_tx_id)
d62a17ae 2679{
b54892e0 2680 const struct prefix *p;
d62a17ae 2681 struct peer *onlypeer;
2682 struct attr attr;
2683 afi_t afi;
2684 safi_t safi;
a77e2f4b
S
2685 struct bgp *bgp;
2686 bool advertise;
adbac85e 2687
9bcb3eef 2688 p = bgp_dest_get_prefix(dest);
d62a17ae 2689 afi = SUBGRP_AFI(subgrp);
2690 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2691 bgp = SUBGRP_INST(subgrp);
d62a17ae 2692 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2693 : NULL);
2694
2dbe669b
DA
2695 if (BGP_DEBUG(update, UPDATE_OUT))
2696 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2697
d62a17ae 2698 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2699 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2700 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2701 return;
d62a17ae 2702
2703 memset(&attr, 0, sizeof(struct attr));
2704 /* It's initialized in bgp_announce_check() */
2705
a77e2f4b
S
2706 /* Announcement to the subgroup. If the route is filtered withdraw it.
2707 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2708 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2709 * route
d62a17ae 2710 */
a77e2f4b
S
2711 advertise = bgp_check_advertise(bgp, dest);
2712
d62a17ae 2713 if (selected) {
7f7940e6 2714 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2715 NULL)) {
a77e2f4b
S
2716 /* Route is selected, if the route is already installed
2717 * in FIB, then it is advertised
2718 */
be785e35
DS
2719 if (advertise) {
2720 if (!bgp_check_withdrawal(bgp, dest))
2721 bgp_adj_out_set_subgroup(
2722 dest, subgrp, &attr, selected);
2723 else
2724 bgp_adj_out_unset_subgroup(
2725 dest, subgrp, 1, addpath_tx_id);
2726 }
a77e2f4b 2727 } else
9bcb3eef 2728 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2729 addpath_tx_id);
d62a17ae 2730 }
2731
2732 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2733 else {
9bcb3eef 2734 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2735 }
200df115 2736}
fee0f4c6 2737
3064bf43 2738/*
e1072051 2739 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2740 * This is called at the end of route processing.
3064bf43 2741 */
9bcb3eef 2742void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2743{
40381db7 2744 struct bgp_path_info *pi;
3064bf43 2745
9bcb3eef 2746 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2747 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2748 continue;
40381db7
DS
2749 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2750 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2751 }
3064bf43 2752}
2753
2754/*
2755 * Has the route changed from the RIB's perspective? This is invoked only
2756 * if the route selection returns the same best route as earlier - to
2757 * determine if we need to update zebra or not.
2758 */
9bcb3eef 2759bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2760{
4b7e6066 2761 struct bgp_path_info *mpinfo;
d62a17ae 2762
2bb9eff4
DS
2763 /* If this is multipath, check all selected paths for any nexthop
2764 * change or attribute change. Some attribute changes (e.g., community)
2765 * aren't of relevance to the RIB, but we'll update zebra to ensure
2766 * we handle the case of BGP nexthop change. This is the behavior
2767 * when the best path has an attribute change anyway.
d62a17ae 2768 */
1defdda8 2769 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2770 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2771 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2772 return true;
d62a17ae 2773
2bb9eff4
DS
2774 /*
2775 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2776 */
18ee8310
DS
2777 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2778 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2779 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2780 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2781 return true;
d62a17ae 2782 }
3064bf43 2783
d62a17ae 2784 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2785 return false;
3064bf43 2786}
2787
d62a17ae 2788struct bgp_process_queue {
2789 struct bgp *bgp;
9bcb3eef 2790 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2791#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2792 unsigned int flags;
2793 unsigned int queued;
200df115 2794};
2795
3b0c17e1 2796static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2797 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2798 struct bgp_path_info *new_select,
2799 struct bgp_path_info *old_select)
2800{
9bcb3eef 2801 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2802
2803 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2804 return;
2805
2806 if (advertise_type5_routes(bgp, afi) && new_select
2807 && is_route_injectable_into_evpn(new_select)) {
2808
2809 /* apply the route-map */
2810 if (bgp->adv_cmd_rmap[afi][safi].map) {
2811 route_map_result_t ret;
2812 struct bgp_path_info rmap_path;
2813 struct bgp_path_info_extra rmap_path_extra;
2814 struct attr dummy_attr;
2815
2816 dummy_attr = *new_select->attr;
2817
2818 /* Fill temp path_info */
9bcb3eef 2819 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2820 new_select, new_select->peer,
2821 &dummy_attr);
2822
2823 RESET_FLAG(dummy_attr.rmap_change_flags);
2824
2825 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2826 p, &rmap_path);
3b0c17e1 2827
2828 if (ret == RMAP_DENYMATCH) {
2829 bgp_attr_flush(&dummy_attr);
2830 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2831 safi);
2832 } else
2833 bgp_evpn_advertise_type5_route(
2834 bgp, p, &dummy_attr, afi, safi);
2835 } else {
2836 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2837 afi, safi);
2838 }
2839 } else if (advertise_type5_routes(bgp, afi) && old_select
2840 && is_route_injectable_into_evpn(old_select))
2841 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2842}
2843
bb2ca692
MS
2844/*
2845 * Utility to determine whether a particular path_info should use
2846 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2847 * in a path where we basically _know_ this is a BGP-LU route.
2848 */
2849static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2850{
2851 /* Certain types get imp null; so do paths where the nexthop is
2852 * not labeled.
2853 */
2854 if (new_select->sub_type == BGP_ROUTE_STATIC
2855 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2856 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2857 return true;
2858 else if (new_select->extra == NULL ||
2859 !bgp_is_valid_label(&new_select->extra->label[0]))
2860 /* TODO -- should be configurable? */
2861 return true;
2862 else
2863 return false;
2864}
2865
3103e8d2
DS
2866/*
2867 * old_select = The old best path
2868 * new_select = the new best path
2869 *
2870 * if (!old_select && new_select)
2871 * We are sending new information on.
2872 *
2873 * if (old_select && new_select) {
2874 * if (new_select != old_select)
2875 * We have a new best path send a change
2876 * else
2877 * We've received a update with new attributes that needs
2878 * to be passed on.
2879 * }
2880 *
2881 * if (old_select && !new_select)
2882 * We have no eligible route that we can announce or the rn
2883 * is being removed.
2884 */
9bcb3eef 2885static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2886 afi_t afi, safi_t safi)
d62a17ae 2887{
4b7e6066
DS
2888 struct bgp_path_info *new_select;
2889 struct bgp_path_info *old_select;
2890 struct bgp_path_info_pair old_and_new;
ddb5b488 2891 int debug = 0;
d62a17ae 2892
892fedb6 2893 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2894 if (dest)
2895 debug = bgp_debug_bestpath(dest);
b54892e0 2896 if (debug)
f4c713ae 2897 zlog_debug(
56ca3b5b 2898 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2899 __func__, dest);
f4c713ae
LB
2900 return;
2901 }
d62a17ae 2902 /* Is it end of initial update? (after startup) */
9bcb3eef 2903 if (!dest) {
e36f61b5
DS
2904 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2905 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2906
2907 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2908 FOREACH_AFI_SAFI (afi, safi) {
2909 if (bgp_fibupd_safi(safi))
2910 bgp_zebra_announce_table(bgp, afi, safi);
2911 }
d62a17ae 2912 bgp->main_peers_update_hold = 0;
2913
2914 bgp_start_routeadv(bgp);
aac24838 2915 return;
d62a17ae 2916 }
cb1faec9 2917
9bcb3eef 2918 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2919
9bcb3eef 2920 debug = bgp_debug_bestpath(dest);
b54892e0 2921 if (debug)
4378495a
DS
2922 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2923 dest, bgp->name_pretty, afi2str(afi),
2924 safi2str(safi));
ddb5b488 2925
f009ff26 2926 /* The best path calculation for the route is deferred if
2927 * BGP_NODE_SELECT_DEFER is set
2928 */
9bcb3eef 2929 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2930 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2931 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2932 return;
2933 }
2934
d62a17ae 2935 /* Best path selection. */
9bcb3eef 2936 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2937 afi, safi);
2938 old_select = old_and_new.old;
2939 new_select = old_and_new.new;
2940
2941 /* Do we need to allocate or free labels?
2942 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2943 * necessary to do this upon changes to best path. Exceptions:
2944 * - label index has changed -> recalculate resulting label
2945 * - path_info sub_type changed -> switch to/from implicit-null
2946 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2947 */
318cac96 2948 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2949 if (new_select) {
2950 if (!old_select
2951 || bgp_label_index_differs(new_select, old_select)
57592a53 2952 || new_select->sub_type != old_select->sub_type
9bcb3eef 2953 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2954 /* Enforced penultimate hop popping:
2955 * implicit-null for local routes, aggregate
2956 * and redistributed routes
2957 */
bb2ca692 2958 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 2959 if (CHECK_FLAG(
9bcb3eef 2960 dest->flags,
992dd67e
PR
2961 BGP_NODE_REGISTERED_FOR_LABEL)
2962 || CHECK_FLAG(
2963 dest->flags,
2964 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2965 bgp_unregister_for_label(dest);
70e98a7f 2966 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2967 &dest->local_label);
2968 bgp_set_valid_label(&dest->local_label);
d62a17ae 2969 } else
9bcb3eef
DS
2970 bgp_register_for_label(dest,
2971 new_select);
d62a17ae 2972 }
9bcb3eef 2973 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2974 BGP_NODE_REGISTERED_FOR_LABEL)
2975 || CHECK_FLAG(dest->flags,
2976 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2977 bgp_unregister_for_label(dest);
318cac96 2978 }
992dd67e
PR
2979 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2980 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2981 bgp_unregister_for_label(dest);
d62a17ae 2982 }
cd1964ff 2983
b54892e0 2984 if (debug)
ddb5b488 2985 zlog_debug(
4378495a
DS
2986 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2987 __func__, dest, bgp->name_pretty, afi2str(afi),
2988 safi2str(safi), old_select, new_select);
ddb5b488 2989
d62a17ae 2990 /* If best route remains the same and this is not due to user-initiated
2991 * clear, see exactly what needs to be done.
2992 */
d62a17ae 2993 if (old_select && old_select == new_select
9bcb3eef 2994 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2995 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2996 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2997 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2998#ifdef ENABLE_BGP_VNC
d62a17ae 2999 vnc_import_bgp_add_route(bgp, p, old_select);
3000 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3001#endif
bb744275 3002 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3003 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3004
be785e35
DS
3005 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3006 && new_select->sub_type == BGP_ROUTE_NORMAL)
3007 SET_FLAG(dest->flags,
3008 BGP_NODE_FIB_INSTALL_PENDING);
3009
ddb5b488
PZ
3010 if (new_select->type == ZEBRA_ROUTE_BGP
3011 && (new_select->sub_type == BGP_ROUTE_NORMAL
3012 || new_select->sub_type
3013 == BGP_ROUTE_IMPORTED))
3014
9bcb3eef 3015 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3016 bgp, afi, safi);
3017 }
d62a17ae 3018 }
d62a17ae 3019
3020 /* If there is a change of interest to peers, reannounce the
3021 * route. */
1defdda8 3022 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3023 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3024 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3025 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3026
3027 /* unicast routes must also be annouced to
3028 * labeled-unicast update-groups */
3029 if (safi == SAFI_UNICAST)
3030 group_announce_route(bgp, afi,
9bcb3eef 3031 SAFI_LABELED_UNICAST, dest,
d62a17ae 3032 new_select);
3033
1defdda8 3034 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3035 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3036 }
fee0f4c6 3037
3b0c17e1 3038 /* advertise/withdraw type-5 routes */
3039 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3040 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3041 bgp_process_evpn_route_injection(
9bcb3eef 3042 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3043
b1875e65 3044 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3045 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3046 bgp_zebra_clear_route_change_flags(dest);
3047 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3048 return;
d62a17ae 3049 }
8ad7271d 3050
d62a17ae 3051 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3052 */
9bcb3eef 3053 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3054
3055 /* bestpath has changed; bump version */
3056 if (old_select || new_select) {
9bcb3eef 3057 bgp_bump_version(dest);
d62a17ae 3058
3059 if (!bgp->t_rmap_def_originate_eval) {
3060 bgp_lock(bgp);
3061 thread_add_timer(
3062 bm->master,
3063 update_group_refresh_default_originate_route_map,
3064 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3065 &bgp->t_rmap_def_originate_eval);
3066 }
3067 }
3f9c7369 3068
d62a17ae 3069 if (old_select)
9bcb3eef 3070 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3071 if (new_select) {
ddb5b488
PZ
3072 if (debug)
3073 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3074 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3075 bgp_path_info_unset_flag(dest, new_select,
3076 BGP_PATH_ATTR_CHANGED);
1defdda8 3077 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3078 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3079 }
338b3424 3080
49e5a4a0 3081#ifdef ENABLE_BGP_VNC
d62a17ae 3082 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3083 if (old_select != new_select) {
3084 if (old_select) {
3085 vnc_import_bgp_exterior_del_route(bgp, p,
3086 old_select);
3087 vnc_import_bgp_del_route(bgp, p, old_select);
3088 }
3089 if (new_select) {
3090 vnc_import_bgp_exterior_add_route(bgp, p,
3091 new_select);
3092 vnc_import_bgp_add_route(bgp, p, new_select);
3093 }
3094 }
3095 }
65efcfce
LB
3096#endif
3097
9bcb3eef 3098 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3099
3100 /* unicast routes must also be annouced to labeled-unicast update-groups
3101 */
3102 if (safi == SAFI_UNICAST)
9bcb3eef 3103 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3104 new_select);
3105
3106 /* FIB update. */
3107 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3108 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3109
d62a17ae 3110 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3111 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3112 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3113 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3114
be785e35
DS
3115 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3116 SET_FLAG(dest->flags,
3117 BGP_NODE_FIB_INSTALL_PENDING);
3118
2b659f33
MK
3119 /* if this is an evpn imported type-5 prefix,
3120 * we need to withdraw the route first to clear
3121 * the nh neigh and the RMAC entry.
3122 */
3123 if (old_select &&
3124 is_route_parent_evpn(old_select))
3125 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3126
9bcb3eef 3127 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3128 } else {
d62a17ae 3129 /* Withdraw the route from the kernel. */
3130 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3131 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3132 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3133 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3134
568e10ca 3135 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3136 }
718e3744 3137 }
3064bf43 3138
9bcb3eef 3139 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3140 old_select);
5424b7ba 3141
d62a17ae 3142 /* Clear any route change flags. */
9bcb3eef 3143 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3144
18ee8310 3145 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3146 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3147 bgp_path_info_reap(dest, old_select);
d62a17ae 3148
9bcb3eef 3149 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3150 return;
718e3744 3151}
3152
f009ff26 3153/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3154int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3155{
9bcb3eef 3156 struct bgp_dest *dest;
f009ff26 3157 int cnt = 0;
3158 struct afi_safi_info *thread_info;
f009ff26 3159
56c226e7
DS
3160 if (bgp->gr_info[afi][safi].t_route_select) {
3161 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3162
3163 thread_info = THREAD_ARG(t);
3164 XFREE(MTYPE_TMP, thread_info);
f009ff26 3165 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3166 }
f009ff26 3167
3168 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3169 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3170 get_afi_safi_str(afi, safi, false),
26742171 3171 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3172 }
3173
3174 /* Process the route list */
6338d242
DS
3175 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3176 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3177 dest = bgp_route_next(dest)) {
3178 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3179 continue;
3180
3181 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3182 bgp->gr_info[afi][safi].gr_deferred--;
3183 bgp_process_main_one(bgp, dest, afi, safi);
3184 cnt++;
3185 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3186 bgp_dest_unlock_node(dest);
3187 break;
f009ff26 3188 }
f009ff26 3189 }
3190
9e3b51a7 3191 /* Send EOR message when all routes are processed */
6338d242 3192 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3193 bgp_send_delayed_eor(bgp);
8c48b3b6 3194 /* Send route processing complete message to RIB */
3195 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3196 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3197 return 0;
9e3b51a7 3198 }
f009ff26 3199
3200 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3201
3202 thread_info->afi = afi;
3203 thread_info->safi = safi;
3204 thread_info->bgp = bgp;
3205
3206 /* If there are more routes to be processed, start the
3207 * selection timer
3208 */
3209 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3210 BGP_ROUTE_SELECT_DELAY,
3211 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3212 return 0;
3213}
3214
aac24838 3215static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3216{
aac24838
JB
3217 struct bgp_process_queue *pqnode = data;
3218 struct bgp *bgp = pqnode->bgp;
d62a17ae 3219 struct bgp_table *table;
9bcb3eef 3220 struct bgp_dest *dest;
aac24838
JB
3221
3222 /* eoiu marker */
3223 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3224 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3225 /* should always have dedicated wq call */
3226 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3227 return WQ_SUCCESS;
3228 }
3229
ac021f40 3230 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3231 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3232 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3233 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3234 table = bgp_dest_table(dest);
3235 /* note, new DESTs may be added as part of processing */
3236 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3237
9bcb3eef 3238 bgp_dest_unlock_node(dest);
d62a17ae 3239 bgp_table_unlock(table);
3240 }
aac24838
JB
3241
3242 return WQ_SUCCESS;
3243}
3244
3245static void bgp_processq_del(struct work_queue *wq, void *data)
3246{
3247 struct bgp_process_queue *pqnode = data;
3248
3249 bgp_unlock(pqnode->bgp);
3250
3251 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3252}
3253
b6c386bb 3254void bgp_process_queue_init(struct bgp *bgp)
200df115 3255{
b6c386bb
DS
3256 if (!bgp->process_queue) {
3257 char name[BUFSIZ];
3258
3259 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3260 bgp->process_queue = work_queue_new(bm->master, name);
3261 }
3262
3263 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3264 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3265 bgp->process_queue->spec.max_retries = 0;
3266 bgp->process_queue->spec.hold = 50;
d62a17ae 3267 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3268 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3269}
3270
cfe8d15a 3271static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3272{
3273 struct bgp_process_queue *pqnode;
3274
a4d82a8a
PZ
3275 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3276 sizeof(struct bgp_process_queue));
aac24838
JB
3277
3278 /* unlocked in bgp_processq_del */
3279 pqnode->bgp = bgp_lock(bgp);
3280 STAILQ_INIT(&pqnode->pqueue);
3281
aac24838
JB
3282 return pqnode;
3283}
3284
9bcb3eef 3285void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3286{
aac24838 3287#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3288 struct work_queue *wq = bgp->process_queue;
d62a17ae 3289 struct bgp_process_queue *pqnode;
cfe8d15a 3290 int pqnode_reuse = 0;
495f0b13 3291
d62a17ae 3292 /* already scheduled for processing? */
9bcb3eef 3293 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3294 return;
2e02b9b2 3295
f009ff26 3296 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3297 * the workqueue
3298 */
9bcb3eef 3299 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3300 if (BGP_DEBUG(update, UPDATE_OUT))
3301 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3302 dest);
f009ff26 3303 return;
3304 }
3305
46aeabed
LS
3306 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3307 if (BGP_DEBUG(update, UPDATE_OUT))
3308 zlog_debug(
3309 "Soft reconfigure table in progress for route %p",
3310 dest);
3311 return;
3312 }
3313
aac24838 3314 if (wq == NULL)
d62a17ae 3315 return;
3316
aac24838 3317 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3318 limit only if is from the same BGP view and it's not an EOIU marker
3319 */
aac24838
JB
3320 if (work_queue_item_count(wq)) {
3321 struct work_queue_item *item = work_queue_last_item(wq);
3322 pqnode = item->data;
228da428 3323
a4d82a8a
PZ
3324 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3325 || pqnode->bgp != bgp
3326 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3327 pqnode = bgp_processq_alloc(bgp);
3328 else
3329 pqnode_reuse = 1;
aac24838 3330 } else
cfe8d15a 3331 pqnode = bgp_processq_alloc(bgp);
aac24838 3332 /* all unlocked in bgp_process_wq */
9bcb3eef 3333 bgp_table_lock(bgp_dest_table(dest));
aac24838 3334
9bcb3eef
DS
3335 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3336 bgp_dest_lock_node(dest);
aac24838 3337
60466a63 3338 /* can't be enqueued twice */
9bcb3eef
DS
3339 assert(STAILQ_NEXT(dest, pq) == NULL);
3340 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3341 pqnode->queued++;
3342
cfe8d15a
LB
3343 if (!pqnode_reuse)
3344 work_queue_add(wq, pqnode);
3345
d62a17ae 3346 return;
fee0f4c6 3347}
0a486e5f 3348
d62a17ae 3349void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3350{
d62a17ae 3351 struct bgp_process_queue *pqnode;
cb1faec9 3352
b6c386bb 3353 if (bgp->process_queue == NULL)
d62a17ae 3354 return;
2e02b9b2 3355
cfe8d15a 3356 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3357
aac24838 3358 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3359 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3360}
3361
cc9f21da 3362static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3363{
d62a17ae 3364 struct peer *peer;
0a486e5f 3365
d62a17ae 3366 peer = THREAD_ARG(thread);
3367 peer->t_pmax_restart = NULL;
0a486e5f 3368
d62a17ae 3369 if (bgp_debug_neighbor_events(peer))
3370 zlog_debug(
3371 "%s Maximum-prefix restart timer expired, restore peering",
3372 peer->host);
0a486e5f 3373
a9bafa95 3374 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3375 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3376}
3377
9cbd06e0
DA
3378static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3379 safi_t safi)
3380{
3381 uint32_t count = 0;
f41b0459 3382 bool filtered = false;
9cbd06e0
DA
3383 struct bgp_dest *dest;
3384 struct bgp_adj_in *ain;
40bb2ccf 3385 struct attr attr = {};
9cbd06e0
DA
3386 struct bgp_table *table = peer->bgp->rib[afi][safi];
3387
3388 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3389 for (ain = dest->adj_in; ain; ain = ain->next) {
3390 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3391
3392 attr = *ain->attr;
9cbd06e0
DA
3393
3394 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3395 == FILTER_DENY)
f41b0459
DA
3396 filtered = true;
3397
3398 if (bgp_input_modifier(
3399 peer, rn_p, &attr, afi, safi,
3400 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3401 NULL, 0, NULL)
3402 == RMAP_DENY)
3403 filtered = true;
3404
3405 if (filtered)
9cbd06e0 3406 count++;
f41b0459 3407
d498917e 3408 bgp_attr_flush(&attr);
9cbd06e0
DA
3409 }
3410 }
3411
3412 return count;
3413}
3414
3dc339cd
DA
3415bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3416 int always)
718e3744 3417{
d62a17ae 3418 iana_afi_t pkt_afi;
5c525538 3419 iana_safi_t pkt_safi;
9cbd06e0
DA
3420 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3421 PEER_FLAG_MAX_PREFIX_FORCE))
3422 ? bgp_filtered_routes_count(peer, afi, safi)
3423 + peer->pcount[afi][safi]
3424 : peer->pcount[afi][safi];
9cabb64b 3425
d62a17ae 3426 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3427 return false;
e0701b79 3428
9cbd06e0 3429 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3430 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3431 PEER_STATUS_PREFIX_LIMIT)
3432 && !always)
3dc339cd 3433 return false;
e0701b79 3434
d62a17ae 3435 zlog_info(
6cde4b45 3436 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3437 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3438 peer->pmax[afi][safi]);
d62a17ae 3439 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3440
3441 if (CHECK_FLAG(peer->af_flags[afi][safi],
3442 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3443 return false;
d62a17ae 3444
3445 /* Convert AFI, SAFI to values for packet. */
3446 pkt_afi = afi_int2iana(afi);
3447 pkt_safi = safi_int2iana(safi);
3448 {
d7c0a89a 3449 uint8_t ndata[7];
d62a17ae 3450
3451 ndata[0] = (pkt_afi >> 8);
3452 ndata[1] = pkt_afi;
3453 ndata[2] = pkt_safi;
3454 ndata[3] = (peer->pmax[afi][safi] >> 24);
3455 ndata[4] = (peer->pmax[afi][safi] >> 16);
3456 ndata[5] = (peer->pmax[afi][safi] >> 8);
3457 ndata[6] = (peer->pmax[afi][safi]);
3458
3459 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3460 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3461 BGP_NOTIFY_CEASE_MAX_PREFIX,
3462 ndata, 7);
3463 }
3464
3465 /* Dynamic peers will just close their connection. */
3466 if (peer_dynamic_neighbor(peer))
3dc339cd 3467 return true;
d62a17ae 3468
3469 /* restart timer start */
3470 if (peer->pmax_restart[afi][safi]) {
3471 peer->v_pmax_restart =
3472 peer->pmax_restart[afi][safi] * 60;
3473
3474 if (bgp_debug_neighbor_events(peer))
3475 zlog_debug(
3476 "%s Maximum-prefix restart timer started for %d secs",
3477 peer->host, peer->v_pmax_restart);
3478
3479 BGP_TIMER_ON(peer->t_pmax_restart,
3480 bgp_maximum_prefix_restart_timer,
3481 peer->v_pmax_restart);
3482 }
3483
3dc339cd 3484 return true;
d62a17ae 3485 } else
3486 UNSET_FLAG(peer->af_sflags[afi][safi],
3487 PEER_STATUS_PREFIX_LIMIT);
3488
b1823b69
DS
3489 if (pcount
3490 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3491 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3492 PEER_STATUS_PREFIX_THRESHOLD)
3493 && !always)
3dc339cd 3494 return false;
d62a17ae 3495
3496 zlog_info(
6cde4b45 3497 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3498 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3499 peer->pmax[afi][safi]);
d62a17ae 3500 SET_FLAG(peer->af_sflags[afi][safi],
3501 PEER_STATUS_PREFIX_THRESHOLD);
3502 } else
3503 UNSET_FLAG(peer->af_sflags[afi][safi],
3504 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3505 return false;
718e3744 3506}
3507
b40d939b 3508/* Unconditionally remove the route from the RIB, without taking
3509 * damping into consideration (eg, because the session went down)
3510 */
9bcb3eef 3511void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3512 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3513{
f009ff26 3514
3515 struct bgp *bgp = NULL;
3516 bool delete_route = false;
3517
9bcb3eef
DS
3518 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3519 safi);
d62a17ae 3520
f009ff26 3521 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3522 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3523
f009ff26 3524 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3525 * flag
3526 */
3527 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3528 delete_route = true;
9bcb3eef 3529 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3530 delete_route = true;
f009ff26 3531 if (delete_route) {
9bcb3eef
DS
3532 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3533 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3534 bgp = pi->peer->bgp;
26742171 3535 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3536 }
3537 }
3538 }
4a11bf2c 3539
9bcb3eef
DS
3540 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3541 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3542}
3543
9bcb3eef 3544static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3545 struct peer *peer, afi_t afi, safi_t safi,
3546 struct prefix_rd *prd)
3547{
9bcb3eef 3548 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3549
d62a17ae 3550 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3551 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3552 */
b4f7f45b
IR
3553 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3554 && peer->sort == BGP_PEER_EBGP)
3555 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3556 == BGP_DAMP_SUPPRESSED) {
3557 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3558 safi);
3559 return;
d62a17ae 3560 }
3561
49e5a4a0 3562#ifdef ENABLE_BGP_VNC
d62a17ae 3563 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3564 struct bgp_dest *pdest = NULL;
d62a17ae 3565 struct bgp_table *table = NULL;
3566
9bcb3eef
DS
3567 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3568 (struct prefix *)prd);
3569 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3570 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3571
3572 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3573 peer->bgp, prd, table, p, pi);
d62a17ae 3574 }
9bcb3eef 3575 bgp_dest_unlock_node(pdest);
d62a17ae 3576 }
3577 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3578 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3579
b54892e0
DS
3580 vnc_import_bgp_del_route(peer->bgp, p, pi);
3581 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3582 }
65efcfce 3583 }
d62a17ae 3584#endif
128ea8ab 3585
d62a17ae 3586 /* If this is an EVPN route, process for un-import. */
3587 if (safi == SAFI_EVPN)
b54892e0 3588 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3589
9bcb3eef 3590 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3591}
3592
4b7e6066
DS
3593struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3594 struct peer *peer, struct attr *attr,
9bcb3eef 3595 struct bgp_dest *dest)
fb018d25 3596{
4b7e6066 3597 struct bgp_path_info *new;
fb018d25 3598
d62a17ae 3599 /* Make new BGP info. */
4b7e6066 3600 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3601 new->type = type;
3602 new->instance = instance;
3603 new->sub_type = sub_type;
3604 new->peer = peer;
3605 new->attr = attr;
3606 new->uptime = bgp_clock();
9bcb3eef 3607 new->net = dest;
d62a17ae 3608 return new;
fb018d25
DS
3609}
3610
c265ee22 3611/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3612bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3613 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3614 struct bgp_dest *dest)
d62a17ae 3615{
2dbe3fa9 3616 bool ret = false;
b099a5c8
DA
3617 bool is_bgp_static_route =
3618 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3619 : false;
d62a17ae 3620
e8442016
DS
3621 /*
3622 * Only validated for unicast and multicast currently.
3623 * Also valid for EVPN where the nexthop is an IP address.
3624 * If we are a bgp static route being checked then there is
3625 * no need to check to see if the nexthop is martian as
3626 * that it should be ok.
3627 */
3628 if (is_bgp_static_route ||
3629 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3630 return false;
d62a17ae 3631
3632 /* If NEXT_HOP is present, validate it. */
3633 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3634 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3635 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3636 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3637 return true;
d62a17ae 3638 }
c265ee22 3639
d62a17ae 3640 /* If MP_NEXTHOP is present, validate it. */
3641 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3642 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3643 * it is not an IPv6 link-local address.
0355b41d
DA
3644 *
3645 * If we receive an UPDATE with nexthop length set to 32 bytes
3646 * we shouldn't discard an UPDATE if it's set to (::).
3647 * The link-local (2st) is validated along the code path later.
d62a17ae 3648 */
3649 if (attr->mp_nexthop_len) {
3650 switch (attr->mp_nexthop_len) {
3651 case BGP_ATTR_NHLEN_IPV4:
3652 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3653 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3654 || IPV4_CLASS_DE(
3655 ntohl(attr->mp_nexthop_global_in.s_addr))
3656 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3657 dest));
d62a17ae 3658 break;
3659
3660 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3661 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3662 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3663 &attr->mp_nexthop_global)
d62a17ae 3664 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3665 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3666 &attr->mp_nexthop_global)
3667 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3668 dest));
d62a17ae 3669 break;
0355b41d
DA
3670 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3671 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3672 || IN6_IS_ADDR_MULTICAST(
3673 &attr->mp_nexthop_global)
3674 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3675 dest));
0355b41d 3676 break;
d62a17ae 3677
3678 default:
3dc339cd 3679 ret = true;
d62a17ae 3680 break;
3681 }
3682 }
c265ee22 3683
d62a17ae 3684 return ret;
3685}
3686
aade37d7 3687static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3688{
3689 struct community *old;
3690 struct community *new;
3691 struct community *merge;
aade37d7 3692 struct community *no_export;
2721dd61 3693
9a706b42 3694 old = bgp_attr_get_community(attr);
aade37d7 3695 no_export = community_str2com("no-export");
2721dd61 3696
b4efa101
DA
3697 assert(no_export);
3698
2721dd61 3699 if (old) {
aade37d7 3700 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3701
3702 if (!old->refcnt)
3703 community_free(&old);
3704
3705 new = community_uniq_sort(merge);
3706 community_free(&merge);
3707 } else {
aade37d7 3708 new = community_dup(no_export);
2721dd61
DA
3709 }
3710
aade37d7 3711 community_free(&no_export);
2721dd61 3712
9a706b42 3713 bgp_attr_set_community(attr, new);
2721dd61
DA
3714 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3715}
3716
5a1ae2c2 3717int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3718 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3719 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3720 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3721 struct bgp_route_evpn *evpn)
d62a17ae 3722{
3723 int ret;
3724 int aspath_loop_count = 0;
9bcb3eef 3725 struct bgp_dest *dest;
d62a17ae 3726 struct bgp *bgp;
3727 struct attr new_attr;
3728 struct attr *attr_new;
40381db7 3729 struct bgp_path_info *pi;
4b7e6066
DS
3730 struct bgp_path_info *new;
3731 struct bgp_path_info_extra *extra;
d62a17ae 3732 const char *reason;
3733 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3734 int connected = 0;
3735 int do_loop_check = 1;
3736 int has_valid_label = 0;
7c312383 3737 afi_t nh_afi;
949b0f24 3738 uint8_t pi_type = 0;
3739 uint8_t pi_sub_type = 0;
9146341f 3740 bool force_evpn_import = false;
907707db 3741 safi_t orig_safi = safi;
949b0f24 3742
c7bb4f00 3743 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3744 char pfxprint[PREFIX2STR_BUFFER];
3745
3746 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3747 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3748 afi, safi, attr);
6401252f
QY
3749 }
3750
49e5a4a0 3751#ifdef ENABLE_BGP_VNC
d62a17ae 3752 int vnc_implicit_withdraw = 0;
65efcfce 3753#endif
d62a17ae 3754 int same_attr = 0;
718e3744 3755
907707db
MS
3756 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3757 if (orig_safi == SAFI_LABELED_UNICAST)
3758 safi = SAFI_UNICAST;
3759
d62a17ae 3760 memset(&new_attr, 0, sizeof(struct attr));
3761 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3762 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3763
d62a17ae 3764 bgp = peer->bgp;
9bcb3eef 3765 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3766 /* TODO: Check to see if we can get rid of "is_valid_label" */
3767 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3768 has_valid_label = (num_labels > 0) ? 1 : 0;
3769 else
3770 has_valid_label = bgp_is_valid_label(label);
718e3744 3771
28f66de2
MS
3772 if (has_valid_label)
3773 assert(label != NULL);
3774
66ff6089
AD
3775 /* Update overlay index of the attribute */
3776 if (afi == AFI_L2VPN && evpn)
3777 memcpy(&attr->evpn_overlay, evpn,
3778 sizeof(struct bgp_route_evpn));
3779
d62a17ae 3780 /* When peer's soft reconfiguration enabled. Record input packet in
3781 Adj-RIBs-In. */
3782 if (!soft_reconfig
3783 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3784 && peer != bgp->peer_self)
9bcb3eef 3785 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3786
3787 /* Check previously received route. */
9bcb3eef 3788 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3789 if (pi->peer == peer && pi->type == type
3790 && pi->sub_type == sub_type
3791 && pi->addpath_rx_id == addpath_id)
d62a17ae 3792 break;
3793
3794 /* AS path local-as loop check. */
3795 if (peer->change_local_as) {
c4368918
DW
3796 if (peer->allowas_in[afi][safi])
3797 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3798 else if (!CHECK_FLAG(peer->flags,
3799 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3800 aspath_loop_count = 1;
3801
3802 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3803 > aspath_loop_count) {
b4d46cc9 3804 peer->stat_pfx_aspath_loop++;
692174a1 3805 reason = "as-path contains our own AS;";
d62a17ae 3806 goto filtered;
3807 }
718e3744 3808 }
718e3744 3809
d62a17ae 3810 /* If the peer is configured for "allowas-in origin" and the last ASN in
3811 * the
3812 * as-path is our ASN then we do not need to call aspath_loop_check
3813 */
3814 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3815 if (aspath_get_last_as(attr->aspath) == bgp->as)
3816 do_loop_check = 0;
3817
3818 /* AS path loop check. */
3819 if (do_loop_check) {
3820 if (aspath_loop_check(attr->aspath, bgp->as)
3821 > peer->allowas_in[afi][safi]
3822 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3823 && aspath_loop_check(attr->aspath, bgp->confed_id)
3824 > peer->allowas_in[afi][safi])) {
b4d46cc9 3825 peer->stat_pfx_aspath_loop++;
d62a17ae 3826 reason = "as-path contains our own AS;";
3827 goto filtered;
3828 }
3829 }
aac9ef6c 3830
d62a17ae 3831 /* Route reflector originator ID check. */
3832 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3833 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3834 peer->stat_pfx_originator_loop++;
d62a17ae 3835 reason = "originator is us;";
3836 goto filtered;
3837 }
718e3744 3838
d62a17ae 3839 /* Route reflector cluster ID check. */
3840 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3841 peer->stat_pfx_cluster_loop++;
d62a17ae 3842 reason = "reflected from the same cluster;";
3843 goto filtered;
3844 }
718e3744 3845
d62a17ae 3846 /* Apply incoming filter. */
907707db 3847 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3848 peer->stat_pfx_filter++;
d62a17ae 3849 reason = "filter;";
3850 goto filtered;
3851 }
718e3744 3852
a8b72dc6
DA
3853 /* RFC 8212 to prevent route leaks.
3854 * This specification intends to improve this situation by requiring the
3855 * explicit configuration of both BGP Import and Export Policies for any
3856 * External BGP (EBGP) session such as customers, peers, or
3857 * confederation boundaries for all enabled address families. Through
3858 * codification of the aforementioned requirement, operators will
3859 * benefit from consistent behavior across different BGP
3860 * implementations.
3861 */
1d3fdccf 3862 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3863 if (!bgp_inbound_policy_exists(peer,
3864 &peer->filter[afi][safi])) {
3865 reason = "inbound policy missing";
b17826b7
DS
3866 if (monotime_since(&bgp->ebgprequirespolicywarning,
3867 NULL) > FIFTEENMINUTE2USEC ||
3868 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3869 zlog_warn(
3870 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3871 monotime(&bgp->ebgprequirespolicywarning);
3872 }
a8b72dc6
DA
3873 goto filtered;
3874 }
3875
fb29348a
DA
3876 /* draft-ietf-idr-deprecate-as-set-confed-set
3877 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3878 * Eventually, This document (if approved) updates RFC 4271
3879 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3880 * and obsoletes RFC 6472.
3881 */
7f972cd8 3882 if (peer->bgp->reject_as_sets)
fb29348a
DA
3883 if (aspath_check_as_sets(attr->aspath)) {
3884 reason =
3885 "as-path contains AS_SET or AS_CONFED_SET type;";
3886 goto filtered;
3887 }
3888
6f4f49b2 3889 new_attr = *attr;
d62a17ae 3890
3891 /* Apply incoming route-map.
3892 * NB: new_attr may now contain newly allocated values from route-map
3893 * "set"
3894 * commands, so we need bgp_attr_flush in the error paths, until we
3895 * intern
3896 * the attr (which takes over the memory references) */
907707db 3897 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3898 num_labels, dest)
3899 == RMAP_DENY) {
b4d46cc9 3900 peer->stat_pfx_filter++;
d62a17ae 3901 reason = "route-map;";
3902 bgp_attr_flush(&new_attr);
3903 goto filtered;
3904 }
718e3744 3905
05864da7 3906 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3907 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3908 /* remove from RIB previous entry */
3909 bgp_zebra_withdraw(p, pi, bgp, safi);
3910 }
3911
7f323236
DW
3912 if (peer->sort == BGP_PEER_EBGP) {
3913
2721dd61
DA
3914 /* rfc7999:
3915 * A BGP speaker receiving an announcement tagged with the
3916 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3917 * NO_EXPORT community as defined in RFC1997, or a
3918 * similar community, to prevent propagation of the
3919 * prefix outside the local AS. The community to prevent
3920 * propagation SHOULD be chosen according to the operator's
3921 * routing policy.
3922 */
9a706b42
DA
3923 if (bgp_attr_get_community(&new_attr) &&
3924 community_include(bgp_attr_get_community(&new_attr),
3925 COMMUNITY_BLACKHOLE))
aade37d7 3926 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3927
a4d82a8a
PZ
3928 /* If we receive the graceful-shutdown community from an eBGP
3929 * peer we must lower local-preference */
9a706b42
DA
3930 if (bgp_attr_get_community(&new_attr) &&
3931 community_include(bgp_attr_get_community(&new_attr),
3932 COMMUNITY_GSHUT)) {
7f323236
DW
3933 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3934 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3935
a4d82a8a
PZ
3936 /* If graceful-shutdown is configured then add the GSHUT
3937 * community to all paths received from eBGP peers */
637e5ba4 3938 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3939 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3940 }
3941
949b0f24 3942 if (pi) {
3943 pi_type = pi->type;
3944 pi_sub_type = pi->sub_type;
3945 }
3946
d62a17ae 3947 /* next hop check. */
a4d82a8a 3948 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3949 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3950 &new_attr, dest)) {
b4d46cc9 3951 peer->stat_pfx_nh_invalid++;
d62a17ae 3952 reason = "martian or self next-hop;";
3953 bgp_attr_flush(&new_attr);
3954 goto filtered;
3955 }
718e3744 3956
5c14a191 3957 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3958 peer->stat_pfx_nh_invalid++;
4e802e66 3959 reason = "self mac;";
4dbf2038 3960 bgp_attr_flush(&new_attr);
4e802e66
DS
3961 goto filtered;
3962 }
3963
a1b773e2
DS
3964 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3965 * condition :
3966 * Suppress fib is enabled
3967 * BGP_OPT_NO_FIB is not enabled
3968 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3969 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3970 */
3971 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3972 && (sub_type == BGP_ROUTE_NORMAL)
3973 && (!bgp_option_check(BGP_OPT_NO_FIB))
3974 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3975 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3976
9cbd06e0
DA
3977 /* If maximum prefix count is configured and current prefix
3978 * count exeed it.
3979 */
4dbf2038
IR
3980 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
3981 bgp_attr_flush(&new_attr);
9cbd06e0 3982 return -1;
4dbf2038
IR
3983 }
3984
3985 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 3986
d62a17ae 3987 /* If the update is implicit withdraw. */
40381db7
DS
3988 if (pi) {
3989 pi->uptime = bgp_clock();
3990 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3991
9bcb3eef 3992 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3993
d62a17ae 3994 /* Same attribute comes in. */
40381db7 3995 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3996 && same_attr
d62a17ae 3997 && (!has_valid_label
40381db7 3998 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3999 num_labels * sizeof(mpls_label_t))
66ff6089 4000 == 0)) {
b4f7f45b
IR
4001 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4002 BGP_CONFIG_DAMPENING)
d62a17ae 4003 && peer->sort == BGP_PEER_EBGP
40381db7 4004 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4005 if (bgp_debug_update(peer, p, NULL, 1)) {
4006 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4007 afi, safi, prd, p, label,
4008 num_labels, addpath_id ? 1 : 0,
66ff6089 4009 addpath_id, evpn, pfx_buf,
a4d82a8a 4010 sizeof(pfx_buf));
d62a17ae 4011 zlog_debug("%s rcvd %s", peer->host,
4012 pfx_buf);
4013 }
4014
9bcb3eef 4015 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4016 != BGP_DAMP_SUPPRESSED) {
40381db7 4017 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4018 safi);
9bcb3eef 4019 bgp_process(bgp, dest, afi, safi);
d62a17ae 4020 }
4021 } else /* Duplicate - odd */
4022 {
4023 if (bgp_debug_update(peer, p, NULL, 1)) {
4024 if (!peer->rcvd_attr_printed) {
4025 zlog_debug(
4026 "%s rcvd UPDATE w/ attr: %s",
4027 peer->host,
4028 peer->rcvd_attr_str);
4029 peer->rcvd_attr_printed = 1;
4030 }
4031
4032 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4033 afi, safi, prd, p, label,
4034 num_labels, addpath_id ? 1 : 0,
66ff6089 4035 addpath_id, evpn, pfx_buf,
a4d82a8a 4036 sizeof(pfx_buf));
d62a17ae 4037 zlog_debug(
4038 "%s rcvd %s...duplicate ignored",
4039 peer->host, pfx_buf);
4040 }
4041
4042 /* graceful restart STALE flag unset. */
40381db7 4043 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4044 bgp_path_info_unset_flag(
9bcb3eef
DS
4045 dest, pi, BGP_PATH_STALE);
4046 bgp_dest_set_defer_flag(dest, false);
4047 bgp_process(bgp, dest, afi, safi);
d62a17ae 4048 }
4049 }
4050
9bcb3eef 4051 bgp_dest_unlock_node(dest);
d62a17ae 4052 bgp_attr_unintern(&attr_new);
4053
4054 return 0;
4055 }
718e3744 4056
d62a17ae 4057 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4058 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4059 if (bgp_debug_update(peer, p, NULL, 1)) {
4060 bgp_debug_rdpfxpath2str(
a4d82a8a 4061 afi, safi, prd, p, label, num_labels,
66ff6089 4062 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4063 pfx_buf, sizeof(pfx_buf));
d62a17ae 4064 zlog_debug(
4065 "%s rcvd %s, flapped quicker than processing",
4066 peer->host, pfx_buf);
4067 }
4068
9bcb3eef 4069 bgp_path_info_restore(dest, pi);
9146341f 4070
4071 /*
4072 * If the BGP_PATH_REMOVED flag is set, then EVPN
4073 * routes would have been unimported already when a
4074 * prior BGP withdraw processing happened. Such routes
4075 * need to be imported again, so flag accordingly.
4076 */
4077 force_evpn_import = true;
d62a17ae 4078 }
718e3744 4079
d62a17ae 4080 /* Received Logging. */
4081 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4082 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4083 num_labels, addpath_id ? 1 : 0,
66ff6089 4084 addpath_id, evpn, pfx_buf,
a4d82a8a 4085 sizeof(pfx_buf));
d62a17ae 4086 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4087 }
718e3744 4088
d62a17ae 4089 /* graceful restart STALE flag unset. */
f009ff26 4090 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4091 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4092 bgp_dest_set_defer_flag(dest, false);
f009ff26 4093 }
d62a17ae 4094
4095 /* The attribute is changed. */
9bcb3eef 4096 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4097
4098 /* implicit withdraw, decrement aggregate and pcount here.
4099 * only if update is accepted, they'll increment below.
4100 */
40381db7 4101 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4102
4103 /* Update bgp route dampening information. */
b4f7f45b 4104 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4105 && peer->sort == BGP_PEER_EBGP) {
4106 /* This is implicit withdraw so we should update
b4f7f45b
IR
4107 dampening
4108 information. */
40381db7 4109 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4110 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4111 }
49e5a4a0 4112#ifdef ENABLE_BGP_VNC
d62a17ae 4113 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4114 struct bgp_dest *pdest = NULL;
d62a17ae 4115 struct bgp_table *table = NULL;
4116
9bcb3eef
DS
4117 pdest = bgp_node_get(bgp->rib[afi][safi],
4118 (struct prefix *)prd);
4119 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4120 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4121
4122 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4123 bgp, prd, table, p, pi);
d62a17ae 4124 }
9bcb3eef 4125 bgp_dest_unlock_node(pdest);
d62a17ae 4126 }
4127 if ((afi == AFI_IP || afi == AFI_IP6)
4128 && (safi == SAFI_UNICAST)) {
40381db7 4129 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4130 /*
4131 * Implicit withdraw case.
4132 */
4133 ++vnc_implicit_withdraw;
40381db7
DS
4134 vnc_import_bgp_del_route(bgp, p, pi);
4135 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4136 }
4137 }
65efcfce 4138#endif
128ea8ab 4139
d62a17ae 4140 /* Special handling for EVPN update of an existing route. If the
4141 * extended community attribute has changed, we need to
4142 * un-import
4143 * the route using its existing extended community. It will be
4144 * subsequently processed for import with the new extended
4145 * community.
4146 */
6f8c9c11
PR
4147 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4148 && !same_attr) {
40381db7 4149 if ((pi->attr->flag
d62a17ae 4150 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4151 && (attr_new->flag
4152 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4153 int cmp;
4154
b53e67a3
DA
4155 cmp = ecommunity_cmp(
4156 bgp_attr_get_ecommunity(pi->attr),
4157 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4158 if (!cmp) {
4159 if (bgp_debug_update(peer, p, NULL, 1))
4160 zlog_debug(
4161 "Change in EXT-COMM, existing %s new %s",
4162 ecommunity_str(
b53e67a3
DA
4163 bgp_attr_get_ecommunity(
4164 pi->attr)),
d62a17ae 4165 ecommunity_str(
b53e67a3
DA
4166 bgp_attr_get_ecommunity(
4167 attr_new)));
6f8c9c11
PR
4168 if (safi == SAFI_EVPN)
4169 bgp_evpn_unimport_route(
4170 bgp, afi, safi, p, pi);
4171 else /* SAFI_MPLS_VPN */
4172 vpn_leak_to_vrf_withdraw(bgp,
4173 pi);
d62a17ae 4174 }
4175 }
4176 }
718e3744 4177
d62a17ae 4178 /* Update to new attribute. */
40381db7
DS
4179 bgp_attr_unintern(&pi->attr);
4180 pi->attr = attr_new;
d62a17ae 4181
4182 /* Update MPLS label */
4183 if (has_valid_label) {
40381db7 4184 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4185 if (extra->label != label) {
4186 memcpy(&extra->label, label,
dbd587da 4187 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4188 extra->num_labels = num_labels;
4189 }
b57ba6d2
MK
4190 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4191 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4192 }
718e3744 4193
e496b420
HS
4194 /* Update SRv6 SID */
4195 if (attr->srv6_l3vpn) {
4196 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4197 if (sid_diff(&extra->sid[0].sid,
4198 &attr->srv6_l3vpn->sid)) {
4199 sid_copy(&extra->sid[0].sid,
e496b420
HS
4200 &attr->srv6_l3vpn->sid);
4201 extra->num_sids = 1;
cc8f05df 4202
16f3db2d
RS
4203 extra->sid[0].loc_block_len = 0;
4204 extra->sid[0].loc_node_len = 0;
4205 extra->sid[0].func_len = 0;
4206 extra->sid[0].arg_len = 0;
ea7cd161
RS
4207 extra->sid[0].transposition_len = 0;
4208 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4209
4210 if (attr->srv6_l3vpn->loc_block_len != 0) {
4211 extra->sid[0].loc_block_len =
4212 attr->srv6_l3vpn->loc_block_len;
4213 extra->sid[0].loc_node_len =
4214 attr->srv6_l3vpn->loc_node_len;
4215 extra->sid[0].func_len =
4216 attr->srv6_l3vpn->func_len;
4217 extra->sid[0].arg_len =
4218 attr->srv6_l3vpn->arg_len;
ea7cd161 4219 extra->sid[0].transposition_len =
cc8f05df 4220 attr->srv6_l3vpn
ea7cd161
RS
4221 ->transposition_len;
4222 extra->sid[0].transposition_offset =
cc8f05df 4223 attr->srv6_l3vpn
ea7cd161
RS
4224 ->transposition_offset;
4225 }
e496b420
HS
4226 }
4227 } else if (attr->srv6_vpn) {
4228 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4229 if (sid_diff(&extra->sid[0].sid,
4230 &attr->srv6_vpn->sid)) {
4231 sid_copy(&extra->sid[0].sid,
4232 &attr->srv6_vpn->sid);
e496b420
HS
4233 extra->num_sids = 1;
4234 }
4235 }
4236
49e5a4a0 4237#ifdef ENABLE_BGP_VNC
d62a17ae 4238 if ((afi == AFI_IP || afi == AFI_IP6)
4239 && (safi == SAFI_UNICAST)) {
4240 if (vnc_implicit_withdraw) {
4241 /*
4242 * Add back the route with its new attributes
4243 * (e.g., nexthop).
4244 * The route is still selected, until the route
4245 * selection
4246 * queued by bgp_process actually runs. We have
4247 * to make this
4248 * update to the VNC side immediately to avoid
4249 * racing against
4250 * configuration changes (e.g., route-map
4251 * changes) which
4252 * trigger re-importation of the entire RIB.
4253 */
40381db7
DS
4254 vnc_import_bgp_add_route(bgp, p, pi);
4255 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4256 }
4257 }
65efcfce
LB
4258#endif
4259
d62a17ae 4260 /* Update bgp route dampening information. */
b4f7f45b 4261 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4262 && peer->sort == BGP_PEER_EBGP) {
4263 /* Now we do normal update dampening. */
9bcb3eef 4264 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4265 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4266 bgp_dest_unlock_node(dest);
d62a17ae 4267 return 0;
4268 }
4269 }
128ea8ab 4270
d62a17ae 4271 /* Nexthop reachability check - for unicast and
4272 * labeled-unicast.. */
7c312383
AD
4273 if (((afi == AFI_IP || afi == AFI_IP6)
4274 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4275 || (safi == SAFI_EVPN &&
4276 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4277 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4278 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4279 && !CHECK_FLAG(peer->flags,
4280 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4281 && !CHECK_FLAG(bgp->flags,
4282 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4283 connected = 1;
4284 else
4285 connected = 0;
4286
960035b2
PZ
4287 struct bgp *bgp_nexthop = bgp;
4288
40381db7
DS
4289 if (pi->extra && pi->extra->bgp_orig)
4290 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4291
7c312383
AD
4292 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4293
4294 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4295 safi, pi, NULL, connected,
4296 p)
a4d82a8a 4297 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4298 bgp_path_info_set_flag(dest, pi,
4299 BGP_PATH_VALID);
d62a17ae 4300 else {
4301 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4302 zlog_debug("%s(%pI4): NH unresolved",
4303 __func__,
4304 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4305 }
9bcb3eef 4306 bgp_path_info_unset_flag(dest, pi,
18ee8310 4307 BGP_PATH_VALID);
d62a17ae 4308 }
4309 } else
9bcb3eef 4310 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4311
49e5a4a0 4312#ifdef ENABLE_BGP_VNC
d62a17ae 4313 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4314 struct bgp_dest *pdest = NULL;
d62a17ae 4315 struct bgp_table *table = NULL;
4316
9bcb3eef
DS
4317 pdest = bgp_node_get(bgp->rib[afi][safi],
4318 (struct prefix *)prd);
4319 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4320 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4321
4322 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4323 bgp, prd, table, p, pi);
d62a17ae 4324 }
9bcb3eef 4325 bgp_dest_unlock_node(pdest);
d62a17ae 4326 }
4327#endif
718e3744 4328
d62a17ae 4329 /* If this is an EVPN route and some attribute has changed,
9146341f 4330 * or we are explicitly told to perform a route import, process
d62a17ae 4331 * route for import. If the extended community has changed, we
4332 * would
4333 * have done the un-import earlier and the import would result
4334 * in the
4335 * route getting injected into appropriate L2 VNIs. If it is
4336 * just
4337 * some other attribute change, the import will result in
4338 * updating
4339 * the attributes for the route in the VNI(s).
4340 */
9146341f 4341 if (safi == SAFI_EVPN &&
4342 (!same_attr || force_evpn_import) &&
7c312383 4343 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4344 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4345
4346 /* Process change. */
40381db7 4347 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4348
9bcb3eef
DS
4349 bgp_process(bgp, dest, afi, safi);
4350 bgp_dest_unlock_node(dest);
558d1fec 4351
ddb5b488
PZ
4352 if (SAFI_UNICAST == safi
4353 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4354 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4355
40381db7 4356 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4357 }
4358 if ((SAFI_MPLS_VPN == safi)
4359 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4360
40381db7 4361 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4362 }
4363
49e5a4a0 4364#ifdef ENABLE_BGP_VNC
d62a17ae 4365 if (SAFI_MPLS_VPN == safi) {
4366 mpls_label_t label_decoded = decode_label(label);
28070ee3 4367
d62a17ae 4368 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4369 type, sub_type, &label_decoded);
4370 }
4371 if (SAFI_ENCAP == safi) {
4372 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4373 type, sub_type, NULL);
4374 }
28070ee3
PZ
4375#endif
4376
d62a17ae 4377 return 0;
4378 } // End of implicit withdraw
718e3744 4379
d62a17ae 4380 /* Received Logging. */
4381 if (bgp_debug_update(peer, p, NULL, 1)) {
4382 if (!peer->rcvd_attr_printed) {
4383 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4384 peer->rcvd_attr_str);
4385 peer->rcvd_attr_printed = 1;
4386 }
718e3744 4387
a4d82a8a 4388 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4389 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4390 pfx_buf, sizeof(pfx_buf));
d62a17ae 4391 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4392 }
718e3744 4393
d62a17ae 4394 /* Make new BGP info. */
9bcb3eef 4395 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4396
d62a17ae 4397 /* Update MPLS label */
4398 if (has_valid_label) {
18ee8310 4399 extra = bgp_path_info_extra_get(new);
8ba71050 4400 if (extra->label != label) {
dbd587da
QY
4401 memcpy(&extra->label, label,
4402 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4403 extra->num_labels = num_labels;
4404 }
b57ba6d2
MK
4405 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4406 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4407 }
718e3744 4408
e496b420
HS
4409 /* Update SRv6 SID */
4410 if (safi == SAFI_MPLS_VPN) {
4411 extra = bgp_path_info_extra_get(new);
4412 if (attr->srv6_l3vpn) {
16f3db2d 4413 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4414 extra->num_sids = 1;
cc8f05df 4415
16f3db2d
RS
4416 extra->sid[0].loc_block_len =
4417 attr->srv6_l3vpn->loc_block_len;
4418 extra->sid[0].loc_node_len =
4419 attr->srv6_l3vpn->loc_node_len;
4420 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4421 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4422 extra->sid[0].transposition_len =
4423 attr->srv6_l3vpn->transposition_len;
4424 extra->sid[0].transposition_offset =
4425 attr->srv6_l3vpn->transposition_offset;
e496b420 4426 } else if (attr->srv6_vpn) {
16f3db2d 4427 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4428 extra->num_sids = 1;
4429 }
4430 }
4431
d62a17ae 4432 /* Nexthop reachability check. */
7c312383
AD
4433 if (((afi == AFI_IP || afi == AFI_IP6)
4434 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4435 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4436 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4437 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4438 && !CHECK_FLAG(peer->flags,
4439 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4440 && !CHECK_FLAG(bgp->flags,
4441 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4442 connected = 1;
4443 else
4444 connected = 0;
4445
7c312383
AD
4446 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4447
4053e952 4448 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4449 connected, p)
a4d82a8a 4450 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4451 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4452 else {
4453 if (BGP_DEBUG(nht, NHT)) {
4454 char buf1[INET6_ADDRSTRLEN];
4455 inet_ntop(AF_INET,
4456 (const void *)&attr_new->nexthop,
4457 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4458 zlog_debug("%s(%s): NH unresolved", __func__,
4459 buf1);
d62a17ae 4460 }
9bcb3eef 4461 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4462 }
4463 } else
9bcb3eef 4464 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4465
d62a17ae 4466 /* Addpath ID */
4467 new->addpath_rx_id = addpath_id;
4468
4469 /* Increment prefix */
4470 bgp_aggregate_increment(bgp, p, new, afi, safi);
4471
4472 /* Register new BGP information. */
9bcb3eef 4473 bgp_path_info_add(dest, new);
d62a17ae 4474
4475 /* route_node_get lock */
9bcb3eef 4476 bgp_dest_unlock_node(dest);
558d1fec 4477
49e5a4a0 4478#ifdef ENABLE_BGP_VNC
d62a17ae 4479 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4480 struct bgp_dest *pdest = NULL;
d62a17ae 4481 struct bgp_table *table = NULL;
4482
9bcb3eef
DS
4483 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4484 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4485 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4486
4487 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4488 bgp, prd, table, p, new);
4489 }
9bcb3eef 4490 bgp_dest_unlock_node(pdest);
d62a17ae 4491 }
65efcfce
LB
4492#endif
4493
d62a17ae 4494 /* If this is an EVPN route, process for import. */
7c312383 4495 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4496 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4497
9bcb3eef 4498 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4499
d62a17ae 4500 /* Process change. */
9bcb3eef 4501 bgp_process(bgp, dest, afi, safi);
718e3744 4502
ddb5b488
PZ
4503 if (SAFI_UNICAST == safi
4504 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4505 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4506 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4507 }
4508 if ((SAFI_MPLS_VPN == safi)
4509 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4510
4511 vpn_leak_to_vrf_update(bgp, new);
4512 }
49e5a4a0 4513#ifdef ENABLE_BGP_VNC
d62a17ae 4514 if (SAFI_MPLS_VPN == safi) {
4515 mpls_label_t label_decoded = decode_label(label);
28070ee3 4516
d62a17ae 4517 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4518 sub_type, &label_decoded);
4519 }
4520 if (SAFI_ENCAP == safi) {
4521 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4522 sub_type, NULL);
4523 }
28070ee3
PZ
4524#endif
4525
d62a17ae 4526 return 0;
718e3744 4527
d62a17ae 4528/* This BGP update is filtered. Log the reason then update BGP
4529 entry. */
4530filtered:
9bcb3eef 4531 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4532
d62a17ae 4533 if (bgp_debug_update(peer, p, NULL, 1)) {
4534 if (!peer->rcvd_attr_printed) {
4535 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4536 peer->rcvd_attr_str);
4537 peer->rcvd_attr_printed = 1;
4538 }
718e3744 4539
a4d82a8a 4540 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4541 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4542 pfx_buf, sizeof(pfx_buf));
d62a17ae 4543 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4544 peer->host, pfx_buf, reason);
4545 }
128ea8ab 4546
40381db7 4547 if (pi) {
d62a17ae 4548 /* If this is an EVPN route, un-import it as it is now filtered.
4549 */
4550 if (safi == SAFI_EVPN)
40381db7 4551 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4552
ddb5b488
PZ
4553 if (SAFI_UNICAST == safi
4554 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4555 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4556
40381db7 4557 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4558 }
4559 if ((SAFI_MPLS_VPN == safi)
4560 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4561
40381db7 4562 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4563 }
4564
9bcb3eef 4565 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4566 }
4567
9bcb3eef 4568 bgp_dest_unlock_node(dest);
558d1fec 4569
49e5a4a0 4570#ifdef ENABLE_BGP_VNC
d62a17ae 4571 /*
4572 * Filtered update is treated as an implicit withdrawal (see
4573 * bgp_rib_remove()
4574 * a few lines above)
4575 */
4576 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4577 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4578 0);
4579 }
97736e32
PZ
4580#endif
4581
d62a17ae 4582 return 0;
718e3744 4583}
4584
26a3ffd6 4585int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4586 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4587 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4588 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4589{
d62a17ae 4590 struct bgp *bgp;
4591 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4592 struct bgp_dest *dest;
40381db7 4593 struct bgp_path_info *pi;
718e3744 4594
49e5a4a0 4595#ifdef ENABLE_BGP_VNC
d62a17ae 4596 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4597 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4598 0);
4599 }
28070ee3
PZ
4600#endif
4601
d62a17ae 4602 bgp = peer->bgp;
4603
4604 /* Lookup node. */
9bcb3eef 4605 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4606
4607 /* If peer is soft reconfiguration enabled. Record input packet for
4608 * further calculation.
4609 *
4610 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4611 * routes that are filtered. This tanks out Quagga RS pretty badly due
4612 * to
4613 * the iteration over all RS clients.
4614 * Since we need to remove the entry from adj_in anyway, do that first
4615 * and
4616 * if there was no entry, we don't need to do anything more.
4617 */
4618 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4619 && peer != bgp->peer_self)
9bcb3eef 4620 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4621 peer->stat_pfx_dup_withdraw++;
4622
d62a17ae 4623 if (bgp_debug_update(peer, p, NULL, 1)) {
4624 bgp_debug_rdpfxpath2str(
a4d82a8a 4625 afi, safi, prd, p, label, num_labels,
6c995628
AD
4626 addpath_id ? 1 : 0, addpath_id, NULL,
4627 pfx_buf, sizeof(pfx_buf));
d62a17ae 4628 zlog_debug(
4629 "%s withdrawing route %s not in adj-in",
4630 peer->host, pfx_buf);
4631 }
9bcb3eef 4632 bgp_dest_unlock_node(dest);
d62a17ae 4633 return 0;
4634 }
cd808e74 4635
d62a17ae 4636 /* Lookup withdrawn route. */
9bcb3eef 4637 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4638 if (pi->peer == peer && pi->type == type
4639 && pi->sub_type == sub_type
4640 && pi->addpath_rx_id == addpath_id)
d62a17ae 4641 break;
4642
4643 /* Logging. */
4644 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4645 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4646 addpath_id ? 1 : 0, addpath_id, NULL,
4647 pfx_buf, sizeof(pfx_buf));
d62a17ae 4648 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4649 pfx_buf);
4650 }
718e3744 4651
d62a17ae 4652 /* Withdraw specified route from routing table. */
40381db7 4653 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4654 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4655 if (SAFI_UNICAST == safi
4656 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4657 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4658 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4659 }
4660 if ((SAFI_MPLS_VPN == safi)
4661 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4662
40381db7 4663 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4664 }
4665 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4666 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4667 addpath_id ? 1 : 0, addpath_id, NULL,
4668 pfx_buf, sizeof(pfx_buf));
d62a17ae 4669 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4670 }
718e3744 4671
d62a17ae 4672 /* Unlock bgp_node_get() lock. */
9bcb3eef 4673 bgp_dest_unlock_node(dest);
d62a17ae 4674
4675 return 0;
718e3744 4676}
6b0655a2 4677
d62a17ae 4678void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4679 int withdraw)
718e3744 4680{
d62a17ae 4681 struct update_subgroup *subgrp;
4682 subgrp = peer_subgroup(peer, afi, safi);
4683 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4684}
6182d65b 4685
718e3744 4686
3f9c7369
DS
4687/*
4688 * bgp_stop_announce_route_timer
4689 */
d62a17ae 4690void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4691{
d62a17ae 4692 if (!paf->t_announce_route)
4693 return;
4694
50478845 4695 thread_cancel(&paf->t_announce_route);
718e3744 4696}
6b0655a2 4697
3f9c7369
DS
4698/*
4699 * bgp_announce_route_timer_expired
4700 *
4701 * Callback that is invoked when the route announcement timer for a
4702 * peer_af expires.
4703 */
cc9f21da 4704static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4705{
d62a17ae 4706 struct peer_af *paf;
4707 struct peer *peer;
558d1fec 4708
d62a17ae 4709 paf = THREAD_ARG(t);
4710 peer = paf->peer;
718e3744 4711
feb17238 4712 if (!peer_established(peer))
cc9f21da 4713 return;
3f9c7369 4714
d62a17ae 4715 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4716 return;
3f9c7369 4717
d62a17ae 4718 peer_af_announce_route(paf, 1);
c5aec50b
MK
4719
4720 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4721 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4722}
4723
3f9c7369
DS
4724/*
4725 * bgp_announce_route
4726 *
4727 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4728 *
4729 * if force is true we will force an update even if the update
4730 * limiting code is attempted to kick in.
3f9c7369 4731 */
e1a32ec1 4732void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4733{
4734 struct peer_af *paf;
4735 struct update_subgroup *subgrp;
4736
4737 paf = peer_af_find(peer, afi, safi);
4738 if (!paf)
4739 return;
4740 subgrp = PAF_SUBGRP(paf);
4741
4742 /*
4743 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4744 * or a refresh has already been triggered.
4745 */
4746 if (!subgrp || paf->t_announce_route)
4747 return;
4748
e1a32ec1
DS
4749 if (force)
4750 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4751
d62a17ae 4752 /*
4753 * Start a timer to stagger/delay the announce. This serves
4754 * two purposes - announcement can potentially be combined for
4755 * multiple peers and the announcement doesn't happen in the
4756 * vty context.
4757 */
4758 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4759 (subgrp->peer_count == 1)
4760 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4761 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4762 &paf->t_announce_route);
3f9c7369
DS
4763}
4764
4765/*
4766 * Announce routes from all AF tables to a peer.
4767 *
4768 * This should ONLY be called when there is a need to refresh the
4769 * routes to the peer based on a policy change for this peer alone
4770 * or a route refresh request received from the peer.
4771 * The operation will result in splitting the peer from its existing
4772 * subgroups and putting it in new subgroups.
4773 */
d62a17ae 4774void bgp_announce_route_all(struct peer *peer)
718e3744 4775{
d62a17ae 4776 afi_t afi;
4777 safi_t safi;
4778
05c7a1cc 4779 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4780 bgp_announce_route(peer, afi, safi, false);
718e3744 4781}
6b0655a2 4782
46aeabed
LS
4783/* Flag or unflag bgp_dest to determine whether it should be treated by
4784 * bgp_soft_reconfig_table_task.
4785 * Flag if flag is true. Unflag if flag is false.
4786 */
4787static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4788{
4789 struct bgp_dest *dest;
4790 struct bgp_adj_in *ain;
4791
4792 if (!table)
4793 return;
4794
4795 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4796 for (ain = dest->adj_in; ain; ain = ain->next) {
4797 if (ain->peer != NULL)
4798 break;
4799 }
4800 if (flag && ain != NULL && ain->peer != NULL)
4801 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4802 else
4803 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4804 }
4805}
4806
4807static int bgp_soft_reconfig_table_update(struct peer *peer,
4808 struct bgp_dest *dest,
4809 struct bgp_adj_in *ain, afi_t afi,
4810 safi_t safi, struct prefix_rd *prd)
4811{
4812 struct bgp_path_info *pi;
4813 uint32_t num_labels = 0;
4814 mpls_label_t *label_pnt = NULL;
4815 struct bgp_route_evpn evpn;
4816
4817 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4818 if (pi->peer == peer)
4819 break;
4820
4821 if (pi && pi->extra)
4822 num_labels = pi->extra->num_labels;
4823 if (num_labels)
4824 label_pnt = &pi->extra->label[0];
4825 if (pi)
4826 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4827 sizeof(evpn));
4828 else
4829 memset(&evpn, 0, sizeof(evpn));
4830
4831 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4832 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4833 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4834 &evpn);
4835}
4836
d62a17ae 4837static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4838 struct bgp_table *table,
4839 struct prefix_rd *prd)
718e3744 4840{
d62a17ae 4841 int ret;
9bcb3eef 4842 struct bgp_dest *dest;
d62a17ae 4843 struct bgp_adj_in *ain;
718e3744 4844
d62a17ae 4845 if (!table)
4846 table = peer->bgp->rib[afi][safi];
718e3744 4847
9bcb3eef
DS
4848 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4849 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4850 if (ain->peer != peer)
4851 continue;
8692c506 4852
46aeabed
LS
4853 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4854 afi, safi, prd);
ea47320b
DL
4855
4856 if (ret < 0) {
9bcb3eef 4857 bgp_dest_unlock_node(dest);
ea47320b 4858 return;
d62a17ae 4859 }
4860 }
718e3744 4861}
4862
46aeabed
LS
4863/* Do soft reconfig table per bgp table.
4864 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4865 * when BGP_NODE_SOFT_RECONFIG is set,
4866 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4867 * Schedule a new thread to continue the job.
4868 * Without splitting the full job into several part,
4869 * vtysh waits for the job to finish before responding to a BGP command
4870 */
cc9f21da 4871static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
4872{
4873 uint32_t iter, max_iter;
4874 int ret;
4875 struct bgp_dest *dest;
4876 struct bgp_adj_in *ain;
4877 struct peer *peer;
4878 struct bgp_table *table;
4879 struct prefix_rd *prd;
4880 struct listnode *node, *nnode;
4881
4882 table = THREAD_ARG(thread);
4883 prd = NULL;
4884
4885 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4886 if (table->soft_reconfig_init) {
4887 /* first call of the function with a new srta structure.
4888 * Don't do any treatment this time on nodes
4889 * in order vtysh to respond quickly
4890 */
4891 max_iter = 0;
4892 }
4893
4894 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4895 dest = bgp_route_next(dest)) {
4896 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4897 continue;
4898
4899 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4900
4901 for (ain = dest->adj_in; ain; ain = ain->next) {
4902 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4903 nnode, peer)) {
4904 if (ain->peer != peer)
4905 continue;
4906
4907 ret = bgp_soft_reconfig_table_update(
4908 peer, dest, ain, table->afi,
4909 table->safi, prd);
4910 iter++;
4911
4912 if (ret < 0) {
4913 bgp_dest_unlock_node(dest);
4914 listnode_delete(
4915 table->soft_reconfig_peers,
4916 peer);
4917 bgp_announce_route(peer, table->afi,
e1a32ec1 4918 table->safi, false);
46aeabed
LS
4919 if (list_isempty(
4920 table->soft_reconfig_peers)) {
4921 list_delete(
4922 &table->soft_reconfig_peers);
4923 bgp_soft_reconfig_table_flag(
4924 table, false);
cc9f21da 4925 return;
46aeabed
LS
4926 }
4927 }
4928 }
4929 }
4930 }
4931
4932 /* we're either starting the initial iteration,
4933 * or we're going to continue an ongoing iteration
4934 */
4935 if (dest || table->soft_reconfig_init) {
4936 table->soft_reconfig_init = false;
4937 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4938 table, 0, &table->soft_reconfig_thread);
cc9f21da 4939 return;
46aeabed
LS
4940 }
4941 /* we're done, clean up the background iteration context info and
4942 schedule route annoucement
4943 */
4944 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4945 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 4946 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
4947 }
4948
4949 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
4950}
4951
4952
4953/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4954 * and peer.
4955 * - bgp cannot be NULL
4956 * - if table and peer are NULL, cancel all threads within the bgp instance
4957 * - if table is NULL and peer is not,
4958 * remove peer in all threads within the bgp instance
4959 * - if peer is NULL, cancel all threads matching table within the bgp instance
4960 */
4961void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4962 const struct bgp_table *table,
4963 const struct peer *peer)
4964{
4965 struct peer *npeer;
4966 struct listnode *node, *nnode;
4967 int afi, safi;
4968 struct bgp_table *ntable;
4969
4970 if (!bgp)
4971 return;
4972
4973 FOREACH_AFI_SAFI (afi, safi) {
4974 ntable = bgp->rib[afi][safi];
4975 if (!ntable)
4976 continue;
4977 if (table && table != ntable)
4978 continue;
4979
4980 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4981 npeer)) {
4982 if (peer && peer != npeer)
4983 continue;
4984 listnode_delete(ntable->soft_reconfig_peers, npeer);
4985 }
4986
4987 if (!ntable->soft_reconfig_peers
4988 || !list_isempty(ntable->soft_reconfig_peers))
4989 continue;
4990
4991 list_delete(&ntable->soft_reconfig_peers);
4992 bgp_soft_reconfig_table_flag(ntable, false);
4993 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4994 }
4995}
4996
d62a17ae 4997void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4998{
9bcb3eef 4999 struct bgp_dest *dest;
d62a17ae 5000 struct bgp_table *table;
46aeabed
LS
5001 struct listnode *node, *nnode;
5002 struct peer *npeer;
5003 struct peer_af *paf;
718e3744 5004
feb17238 5005 if (!peer_established(peer))
d62a17ae 5006 return;
718e3744 5007
d62a17ae 5008 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5009 && (safi != SAFI_EVPN)) {
5010 table = peer->bgp->rib[afi][safi];
5011 if (!table)
5012 return;
5013
5014 table->soft_reconfig_init = true;
5015
5016 if (!table->soft_reconfig_peers)
5017 table->soft_reconfig_peers = list_new();
5018 npeer = NULL;
5019 /* add peer to the table soft_reconfig_peers if not already
5020 * there
5021 */
5022 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5023 npeer)) {
5024 if (peer == npeer)
5025 break;
5026 }
5027 if (peer != npeer)
5028 listnode_add(table->soft_reconfig_peers, peer);
5029
5030 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5031 * on table would start back at the beginning.
5032 */
5033 bgp_soft_reconfig_table_flag(table, true);
5034
5035 if (!table->soft_reconfig_thread)
5036 thread_add_event(bm->master,
5037 bgp_soft_reconfig_table_task, table, 0,
5038 &table->soft_reconfig_thread);
5039 /* Cancel bgp_announce_route_timer_expired threads.
5040 * bgp_announce_route_timer_expired threads have been scheduled
5041 * to announce routes as soon as the soft_reconfigure process
5042 * finishes.
5043 * In this case, soft_reconfigure is also scheduled by using
5044 * a thread but is planned after the
5045 * bgp_announce_route_timer_expired threads. It means that,
5046 * without cancelling the threads, the route announcement task
5047 * would run before the soft reconfiguration one. That would
5048 * useless and would block vtysh during several seconds. Route
5049 * announcements are rescheduled as soon as the soft_reconfigure
5050 * process finishes.
5051 */
5052 paf = peer_af_find(peer, afi, safi);
5053 if (paf)
5054 bgp_stop_announce_route_timer(paf);
5055 } else
9bcb3eef
DS
5056 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5057 dest = bgp_route_next(dest)) {
5058 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5059
b54892e0
DS
5060 if (table == NULL)
5061 continue;
8692c506 5062
9bcb3eef 5063 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5064 struct prefix_rd prd;
5065
5066 prd.family = AF_UNSPEC;
5067 prd.prefixlen = 64;
5068 memcpy(&prd.val, p->u.val, 8);
5069
5070 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5071 }
718e3744 5072}
6b0655a2 5073
228da428 5074
d62a17ae 5075struct bgp_clear_node_queue {
9bcb3eef 5076 struct bgp_dest *dest;
228da428
CC
5077};
5078
d62a17ae 5079static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5080{
d62a17ae 5081 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5082 struct bgp_dest *dest = cnq->dest;
d62a17ae 5083 struct peer *peer = wq->spec.data;
40381db7 5084 struct bgp_path_info *pi;
3103e8d2 5085 struct bgp *bgp;
9bcb3eef
DS
5086 afi_t afi = bgp_dest_table(dest)->afi;
5087 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5088
9bcb3eef 5089 assert(dest && peer);
3103e8d2 5090 bgp = peer->bgp;
d62a17ae 5091
5092 /* It is possible that we have multiple paths for a prefix from a peer
5093 * if that peer is using AddPath.
5094 */
9bcb3eef 5095 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5096 if (pi->peer != peer)
ea47320b
DL
5097 continue;
5098
5099 /* graceful restart STALE flag set. */
9af52ccf
DA
5100 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5101 && peer->nsf[afi][safi])
5102 || CHECK_FLAG(peer->af_sflags[afi][safi],
5103 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5104 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5105 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5106 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5107 else {
5108 /* If this is an EVPN route, process for
5109 * un-import. */
5110 if (safi == SAFI_EVPN)
9bcb3eef
DS
5111 bgp_evpn_unimport_route(
5112 bgp, afi, safi,
5113 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5114 /* Handle withdraw for VRF route-leaking and L3VPN */
5115 if (SAFI_UNICAST == safi
5116 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5117 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5118 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5119 bgp, pi);
960035b2 5120 }
3103e8d2 5121 if (SAFI_MPLS_VPN == safi &&
960035b2 5122 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5123 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5124 }
3103e8d2 5125
9bcb3eef 5126 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5127 }
ea47320b 5128 }
d62a17ae 5129 return WQ_SUCCESS;
200df115 5130}
5131
d62a17ae 5132static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5133{
d62a17ae 5134 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5135 struct bgp_dest *dest = cnq->dest;
5136 struct bgp_table *table = bgp_dest_table(dest);
228da428 5137
9bcb3eef 5138 bgp_dest_unlock_node(dest);
d62a17ae 5139 bgp_table_unlock(table);
5140 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5141}
5142
d62a17ae 5143static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5144{
d62a17ae 5145 struct peer *peer = wq->spec.data;
64e580a7 5146
d62a17ae 5147 /* Tickle FSM to start moving again */
5148 BGP_EVENT_ADD(peer, Clearing_Completed);
5149
5150 peer_unlock(peer); /* bgp_clear_route */
200df115 5151}
718e3744 5152
d62a17ae 5153static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5154{
d62a17ae 5155 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5156
5157 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5158#undef CLEAR_QUEUE_NAME_LEN
5159
0ce1ca80 5160 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5161 peer->clear_node_queue->spec.hold = 10;
5162 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5163 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5164 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5165 peer->clear_node_queue->spec.max_retries = 0;
5166
5167 /* we only 'lock' this peer reference when the queue is actually active
5168 */
5169 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5170}
5171
d62a17ae 5172static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5173 struct bgp_table *table)
65ca75e0 5174{
9bcb3eef 5175 struct bgp_dest *dest;
b6c386bb 5176 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5177
d62a17ae 5178 if (!table)
5179 table = peer->bgp->rib[afi][safi];
dc83d712 5180
d62a17ae 5181 /* If still no table => afi/safi isn't configured at all or smth. */
5182 if (!table)
5183 return;
dc83d712 5184
9bcb3eef 5185 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5186 struct bgp_path_info *pi, *next;
d62a17ae 5187 struct bgp_adj_in *ain;
5188 struct bgp_adj_in *ain_next;
5189
5190 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5191 * queued for every clearing peer, regardless of whether it is
5192 * relevant to the peer at hand.
5193 *
5194 * Overview: There are 3 different indices which need to be
5195 * scrubbed, potentially, when a peer is removed:
5196 *
5197 * 1 peer's routes visible via the RIB (ie accepted routes)
5198 * 2 peer's routes visible by the (optional) peer's adj-in index
5199 * 3 other routes visible by the peer's adj-out index
5200 *
5201 * 3 there is no hurry in scrubbing, once the struct peer is
5202 * removed from bgp->peer, we could just GC such deleted peer's
5203 * adj-outs at our leisure.
5204 *
5205 * 1 and 2 must be 'scrubbed' in some way, at least made
5206 * invisible via RIB index before peer session is allowed to be
5207 * brought back up. So one needs to know when such a 'search' is
5208 * complete.
5209 *
5210 * Ideally:
5211 *
5212 * - there'd be a single global queue or a single RIB walker
5213 * - rather than tracking which route_nodes still need to be
5214 * examined on a peer basis, we'd track which peers still
5215 * aren't cleared
5216 *
5217 * Given that our per-peer prefix-counts now should be reliable,
5218 * this may actually be achievable. It doesn't seem to be a huge
5219 * problem at this time,
5220 *
5221 * It is possible that we have multiple paths for a prefix from
5222 * a peer
5223 * if that peer is using AddPath.
5224 */
9bcb3eef 5225 ain = dest->adj_in;
d62a17ae 5226 while (ain) {
5227 ain_next = ain->next;
5228
6a840fd9 5229 if (ain->peer == peer)
9bcb3eef 5230 bgp_adj_in_remove(dest, ain);
d62a17ae 5231
5232 ain = ain_next;
5233 }
5234
9bcb3eef 5235 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5236 next = pi->next;
5237 if (pi->peer != peer)
d62a17ae 5238 continue;
5239
5240 if (force)
9bcb3eef 5241 bgp_path_info_reap(dest, pi);
d62a17ae 5242 else {
5243 struct bgp_clear_node_queue *cnq;
5244
5245 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5246 bgp_table_lock(bgp_dest_table(dest));
5247 bgp_dest_lock_node(dest);
d62a17ae 5248 cnq = XCALLOC(
5249 MTYPE_BGP_CLEAR_NODE_QUEUE,
5250 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5251 cnq->dest = dest;
d62a17ae 5252 work_queue_add(peer->clear_node_queue, cnq);
5253 break;
5254 }
5255 }
5256 }
5257 return;
5258}
5259
5260void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5261{
9bcb3eef 5262 struct bgp_dest *dest;
d62a17ae 5263 struct bgp_table *table;
5264
5265 if (peer->clear_node_queue == NULL)
5266 bgp_clear_node_queue_init(peer);
5267
5268 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5269 * Idle until it receives a Clearing_Completed event. This protects
5270 * against peers which flap faster than we can we clear, which could
5271 * lead to:
5272 *
5273 * a) race with routes from the new session being installed before
5274 * clear_route_node visits the node (to delete the route of that
5275 * peer)
5276 * b) resource exhaustion, clear_route_node likely leads to an entry
5277 * on the process_main queue. Fast-flapping could cause that queue
5278 * to grow and grow.
5279 */
5280
5281 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5282 * the unlock will happen upon work-queue completion; other wise, the
5283 * unlock happens at the end of this function.
5284 */
5285 if (!peer->clear_node_queue->thread)
5286 peer_lock(peer);
5287
5288 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5289 bgp_clear_route_table(peer, afi, safi, NULL);
5290 else
9bcb3eef
DS
5291 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5292 dest = bgp_route_next(dest)) {
5293 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5294 if (!table)
5295 continue;
5296
5297 bgp_clear_route_table(peer, afi, safi, table);
5298 }
d62a17ae 5299
5300 /* unlock if no nodes got added to the clear-node-queue. */
5301 if (!peer->clear_node_queue->thread)
5302 peer_unlock(peer);
718e3744 5303}
d62a17ae 5304
5305void bgp_clear_route_all(struct peer *peer)
718e3744 5306{
d62a17ae 5307 afi_t afi;
5308 safi_t safi;
718e3744 5309
05c7a1cc
QY
5310 FOREACH_AFI_SAFI (afi, safi)
5311 bgp_clear_route(peer, afi, safi);
65efcfce 5312
49e5a4a0 5313#ifdef ENABLE_BGP_VNC
d62a17ae 5314 rfapiProcessPeerDown(peer);
65efcfce 5315#endif
718e3744 5316}
5317
d62a17ae 5318void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5319{
d62a17ae 5320 struct bgp_table *table;
9bcb3eef 5321 struct bgp_dest *dest;
d62a17ae 5322 struct bgp_adj_in *ain;
5323 struct bgp_adj_in *ain_next;
718e3744 5324
d62a17ae 5325 table = peer->bgp->rib[afi][safi];
718e3744 5326
d62a17ae 5327 /* It is possible that we have multiple paths for a prefix from a peer
5328 * if that peer is using AddPath.
5329 */
9bcb3eef
DS
5330 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5331 ain = dest->adj_in;
43143c8f 5332
d62a17ae 5333 while (ain) {
5334 ain_next = ain->next;
43143c8f 5335
6a840fd9 5336 if (ain->peer == peer)
9bcb3eef 5337 bgp_adj_in_remove(dest, ain);
43143c8f 5338
d62a17ae 5339 ain = ain_next;
5340 }
5341 }
718e3744 5342}
93406d87 5343
1479ed2f
DA
5344/* If any of the routes from the peer have been marked with the NO_LLGR
5345 * community, either as sent by the peer, or as the result of a configured
5346 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5347 * operation of [RFC4271].
5348 */
d62a17ae 5349void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5350{
9bcb3eef 5351 struct bgp_dest *dest;
40381db7 5352 struct bgp_path_info *pi;
d62a17ae 5353 struct bgp_table *table;
5354
9af52ccf 5355 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5356 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5357 dest = bgp_route_next(dest)) {
5358 struct bgp_dest *rm;
d62a17ae 5359
5360 /* look for neighbor in tables */
9bcb3eef 5361 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5362 if (!table)
ea47320b
DL
5363 continue;
5364
5365 for (rm = bgp_table_top(table); rm;
5366 rm = bgp_route_next(rm))
9bcb3eef 5367 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5368 pi = pi->next) {
40381db7 5369 if (pi->peer != peer)
ea47320b 5370 continue;
1479ed2f
DA
5371 if (CHECK_FLAG(
5372 peer->af_sflags[afi][safi],
5373 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5374 bgp_attr_get_community(pi->attr) &&
1479ed2f 5375 !community_include(
9a706b42
DA
5376 bgp_attr_get_community(
5377 pi->attr),
1479ed2f 5378 COMMUNITY_NO_LLGR))
e3015d91 5379 continue;
40381db7 5380 if (!CHECK_FLAG(pi->flags,
1defdda8 5381 BGP_PATH_STALE))
e3015d91 5382 continue;
ea47320b 5383
641065d4
KM
5384 /*
5385 * If this is VRF leaked route
5386 * process for withdraw.
5387 */
5388 if (pi->sub_type ==
5389 BGP_ROUTE_IMPORTED &&
5390 peer->bgp->inst_type ==
5391 BGP_INSTANCE_TYPE_DEFAULT)
5392 vpn_leak_to_vrf_withdraw(
5393 peer->bgp, pi);
5394
40381db7 5395 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5396 break;
5397 }
d62a17ae 5398 }
5399 } else {
9bcb3eef
DS
5400 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5401 dest = bgp_route_next(dest))
5402 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5403 pi = pi->next) {
40381db7 5404 if (pi->peer != peer)
ea47320b 5405 continue;
1479ed2f
DA
5406 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5407 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5408 bgp_attr_get_community(pi->attr) &&
5409 !community_include(
5410 bgp_attr_get_community(pi->attr),
5411 COMMUNITY_NO_LLGR))
e3015d91 5412 continue;
40381db7 5413 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5414 continue;
641065d4
KM
5415 if (safi == SAFI_UNICAST &&
5416 (peer->bgp->inst_type ==
5417 BGP_INSTANCE_TYPE_VRF ||
5418 peer->bgp->inst_type ==
5419 BGP_INSTANCE_TYPE_DEFAULT))
5420 vpn_leak_from_vrf_withdraw(
5421 bgp_get_default(), peer->bgp,
5422 pi);
5423
9bcb3eef 5424 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5425 break;
5426 }
d62a17ae 5427 }
93406d87 5428}
6b0655a2 5429
9af52ccf
DA
5430void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5431{
5432 struct bgp_dest *dest, *ndest;
5433 struct bgp_path_info *pi;
5434 struct bgp_table *table;
5435
5436 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5437 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5438 dest = bgp_route_next(dest)) {
5439 table = bgp_dest_get_bgp_table_info(dest);
5440 if (!table)
5441 continue;
5442
5443 for (ndest = bgp_table_top(table); ndest;
5444 ndest = bgp_route_next(ndest)) {
5445 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5446 pi = pi->next) {
5447 if (pi->peer != peer)
5448 continue;
5449
5450 if ((CHECK_FLAG(
5451 peer->af_sflags[afi][safi],
5452 PEER_STATUS_ENHANCED_REFRESH))
5453 && !CHECK_FLAG(pi->flags,
5454 BGP_PATH_STALE)
5455 && !CHECK_FLAG(
5456 pi->flags,
5457 BGP_PATH_UNUSEABLE)) {
5458 if (bgp_debug_neighbor_events(
5459 peer))
5460 zlog_debug(
5461 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5462 peer->host,
5463 afi2str(afi),
5464 safi2str(safi),
5465 bgp_dest_get_prefix(
5466 ndest));
5467
5468 bgp_path_info_set_flag(
5469 ndest, pi,
5470 BGP_PATH_STALE);
5471 }
5472 }
5473 }
5474 }
5475 } else {
5476 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5477 dest = bgp_route_next(dest)) {
5478 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5479 pi = pi->next) {
5480 if (pi->peer != peer)
5481 continue;
5482
5483 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5484 PEER_STATUS_ENHANCED_REFRESH))
5485 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5486 && !CHECK_FLAG(pi->flags,
5487 BGP_PATH_UNUSEABLE)) {
5488 if (bgp_debug_neighbor_events(peer))
5489 zlog_debug(
5490 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5491 peer->host,
5492 afi2str(afi),
5493 safi2str(safi),
5494 bgp_dest_get_prefix(
5495 dest));
5496
5497 bgp_path_info_set_flag(dest, pi,
5498 BGP_PATH_STALE);
5499 }
5500 }
5501 }
5502 }
5503}
5504
3dc339cd 5505bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5506{
e0df4c04 5507 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5508 return true;
e0df4c04 5509
9dac9fc8
DA
5510 if (peer->sort == BGP_PEER_EBGP
5511 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5512 || FILTER_LIST_OUT_NAME(filter)
5513 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5514 return true;
5515 return false;
9dac9fc8
DA
5516}
5517
3dc339cd 5518bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5519{
e0df4c04 5520 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5521 return true;
e0df4c04 5522
9dac9fc8
DA
5523 if (peer->sort == BGP_PEER_EBGP
5524 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5525 || FILTER_LIST_IN_NAME(filter)
5526 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5527 return true;
5528 return false;
9dac9fc8
DA
5529}
5530
568e10ca 5531static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5532 safi_t safi)
bb86c601 5533{
9bcb3eef 5534 struct bgp_dest *dest;
40381db7 5535 struct bgp_path_info *pi;
4b7e6066 5536 struct bgp_path_info *next;
bb86c601 5537
9bcb3eef
DS
5538 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5539 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5540 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5541
40381db7 5542 next = pi->next;
1b7bb747
CS
5543
5544 /* Unimport EVPN routes from VRFs */
5545 if (safi == SAFI_EVPN)
5546 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5547 SAFI_EVPN, p, pi);
1b7bb747 5548
40381db7
DS
5549 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5550 && pi->type == ZEBRA_ROUTE_BGP
5551 && (pi->sub_type == BGP_ROUTE_NORMAL
5552 || pi->sub_type == BGP_ROUTE_AGGREGATE
5553 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5554
d62a17ae 5555 if (bgp_fibupd_safi(safi))
b54892e0 5556 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5557 }
9514b37d 5558
9bcb3eef 5559 bgp_path_info_reap(dest, pi);
d62a17ae 5560 }
bb86c601
LB
5561}
5562
718e3744 5563/* Delete all kernel routes. */
d62a17ae 5564void bgp_cleanup_routes(struct bgp *bgp)
5565{
5566 afi_t afi;
9bcb3eef 5567 struct bgp_dest *dest;
67009e22 5568 struct bgp_table *table;
d62a17ae 5569
5570 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5571 if (afi == AFI_L2VPN)
5572 continue;
568e10ca 5573 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5574 SAFI_UNICAST);
d62a17ae 5575 /*
5576 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5577 */
5578 if (afi != AFI_L2VPN) {
5579 safi_t safi;
5580 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5581 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5582 dest = bgp_route_next(dest)) {
5583 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5584 if (table != NULL) {
5585 bgp_cleanup_table(bgp, table, safi);
5586 bgp_table_finish(&table);
9bcb3eef
DS
5587 bgp_dest_set_bgp_table_info(dest, NULL);
5588 bgp_dest_unlock_node(dest);
d62a17ae 5589 }
5590 }
5591 safi = SAFI_ENCAP;
9bcb3eef
DS
5592 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5593 dest = bgp_route_next(dest)) {
5594 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5595 if (table != NULL) {
5596 bgp_cleanup_table(bgp, table, safi);
5597 bgp_table_finish(&table);
9bcb3eef
DS
5598 bgp_dest_set_bgp_table_info(dest, NULL);
5599 bgp_dest_unlock_node(dest);
d62a17ae 5600 }
5601 }
5602 }
5603 }
9bcb3eef
DS
5604 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5605 dest = bgp_route_next(dest)) {
5606 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5607 if (table != NULL) {
5608 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5609 bgp_table_finish(&table);
9bcb3eef
DS
5610 bgp_dest_set_bgp_table_info(dest, NULL);
5611 bgp_dest_unlock_node(dest);
d62a17ae 5612 }
bb86c601 5613 }
718e3744 5614}
5615
d62a17ae 5616void bgp_reset(void)
718e3744 5617{
d62a17ae 5618 vty_reset();
5619 bgp_zclient_reset();
5620 access_list_reset();
5621 prefix_list_reset();
718e3744 5622}
6b0655a2 5623
be92fc9f 5624bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5625{
d62a17ae 5626 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5627 && CHECK_FLAG(peer->af_cap[afi][safi],
5628 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5629}
5630
718e3744 5631/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5632 value. */
d62a17ae 5633int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5634 struct bgp_nlri *packet)
5635{
d7c0a89a
QY
5636 uint8_t *pnt;
5637 uint8_t *lim;
d62a17ae 5638 struct prefix p;
5639 int psize;
5640 int ret;
5641 afi_t afi;
5642 safi_t safi;
be92fc9f 5643 bool addpath_capable;
d7c0a89a 5644 uint32_t addpath_id;
d62a17ae 5645
d62a17ae 5646 pnt = packet->nlri;
5647 lim = pnt + packet->length;
5648 afi = packet->afi;
5649 safi = packet->safi;
5650 addpath_id = 0;
be92fc9f 5651 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5652
5653 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5654 syntactic validity. If the field is syntactically incorrect,
5655 then the Error Subcode is set to Invalid Network Field. */
5656 for (; pnt < lim; pnt += psize) {
5657 /* Clear prefix structure. */
5658 memset(&p, 0, sizeof(struct prefix));
5659
be92fc9f 5660 if (addpath_capable) {
d62a17ae 5661
5662 /* When packet overflow occurs return immediately. */
761ed665 5663 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5664 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5665
a3a850a1 5666 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5667 addpath_id = ntohl(addpath_id);
d62a17ae 5668 pnt += BGP_ADDPATH_ID_LEN;
5669 }
718e3744 5670
d62a17ae 5671 /* Fetch prefix length. */
5672 p.prefixlen = *pnt++;
5673 /* afi/safi validity already verified by caller,
5674 * bgp_update_receive */
5675 p.family = afi2family(afi);
5676
5677 /* Prefix length check. */
5678 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5679 flog_err(
e50f7cfd 5680 EC_BGP_UPDATE_RCV,
14454c9f 5681 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5682 peer->host, p.prefixlen, packet->afi);
513386b5 5683 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5684 }
6b0655a2 5685
d62a17ae 5686 /* Packet size overflow check. */
5687 psize = PSIZE(p.prefixlen);
5688
5689 /* When packet overflow occur return immediately. */
5690 if (pnt + psize > lim) {
af4c2728 5691 flog_err(
e50f7cfd 5692 EC_BGP_UPDATE_RCV,
d62a17ae 5693 "%s [Error] Update packet error (prefix length %d overflows packet)",
5694 peer->host, p.prefixlen);
513386b5 5695 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5696 }
5697
5698 /* Defensive coding, double-check the psize fits in a struct
5699 * prefix */
5700 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5701 flog_err(
e50f7cfd 5702 EC_BGP_UPDATE_RCV,
d62a17ae 5703 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5704 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5705 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5706 }
5707
5708 /* Fetch prefix from NLRI packet. */
a85297a7 5709 memcpy(p.u.val, pnt, psize);
d62a17ae 5710
5711 /* Check address. */
5712 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5713 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5714 /* From RFC4271 Section 6.3:
5715 *
5716 * If a prefix in the NLRI field is semantically
5717 * incorrect
5718 * (e.g., an unexpected multicast IP address),
5719 * an error SHOULD
5720 * be logged locally, and the prefix SHOULD be
5721 * ignored.
a4d82a8a 5722 */
af4c2728 5723 flog_err(
e50f7cfd 5724 EC_BGP_UPDATE_RCV,
23d0a753
DA
5725 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5726 peer->host, &p.u.prefix4);
d62a17ae 5727 continue;
5728 }
5729 }
5730
5731 /* Check address. */
5732 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5733 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5734 flog_err(
e50f7cfd 5735 EC_BGP_UPDATE_RCV,
c0d72166
DS
5736 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5737 peer->host, &p.u.prefix6);
d62a17ae 5738
5739 continue;
5740 }
5741 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5742 flog_err(
e50f7cfd 5743 EC_BGP_UPDATE_RCV,
c0d72166
DS
5744 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5745 peer->host, &p.u.prefix6);
d62a17ae 5746
5747 continue;
5748 }
5749 }
5750
5751 /* Normal process. */
5752 if (attr)
5753 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5754 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5755 NULL, NULL, 0, 0, NULL);
d62a17ae 5756 else
5757 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5758 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5759 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5760 NULL);
d62a17ae 5761
513386b5
DA
5762 /* Do not send BGP notification twice when maximum-prefix count
5763 * overflow. */
5764 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5765 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5766
5767 /* Address family configuration mismatch. */
d62a17ae 5768 if (ret < 0)
513386b5 5769 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5770 }
5771
5772 /* Packet length consistency check. */
5773 if (pnt != lim) {
af4c2728 5774 flog_err(
e50f7cfd 5775 EC_BGP_UPDATE_RCV,
d62a17ae 5776 "%s [Error] Update packet error (prefix length mismatch with total length)",
5777 peer->host);
513386b5 5778 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5779 }
6b0655a2 5780
513386b5 5781 return BGP_NLRI_PARSE_OK;
718e3744 5782}
5783
d62a17ae 5784static struct bgp_static *bgp_static_new(void)
718e3744 5785{
d62a17ae 5786 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5787}
5788
d62a17ae 5789static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5790{
0a22ddfb 5791 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5792 route_map_counter_decrement(bgp_static->rmap.map);
5793
0a22ddfb 5794 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5795 XFREE(MTYPE_BGP_STATIC, bgp_static);
5796}
5797
5f040085 5798void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5799 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5800{
9bcb3eef 5801 struct bgp_dest *dest;
40381db7 5802 struct bgp_path_info *pi;
4b7e6066 5803 struct bgp_path_info *new;
40381db7 5804 struct bgp_path_info rmap_path;
d62a17ae 5805 struct attr attr;
5806 struct attr *attr_new;
b68885f9 5807 route_map_result_t ret;
49e5a4a0 5808#ifdef ENABLE_BGP_VNC
d62a17ae 5809 int vnc_implicit_withdraw = 0;
65efcfce 5810#endif
fee0f4c6 5811
d62a17ae 5812 assert(bgp_static);
dd8103a9 5813
9bcb3eef 5814 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5815
d62a17ae 5816 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5817
d62a17ae 5818 attr.nexthop = bgp_static->igpnexthop;
5819 attr.med = bgp_static->igpmetric;
5820 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5821
d62a17ae 5822 if (bgp_static->atomic)
5823 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5824
d62a17ae 5825 /* Store label index, if required. */
5826 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5827 attr.label_index = bgp_static->label_index;
5828 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5829 }
718e3744 5830
d62a17ae 5831 /* Apply route-map. */
5832 if (bgp_static->rmap.name) {
5833 struct attr attr_tmp = attr;
80ced710 5834
40381db7
DS
5835 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5836 rmap_path.peer = bgp->peer_self;
5837 rmap_path.attr = &attr_tmp;
fee0f4c6 5838
d62a17ae 5839 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5840
1782514f 5841 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5842
d62a17ae 5843 bgp->peer_self->rmap_type = 0;
718e3744 5844
d62a17ae 5845 if (ret == RMAP_DENYMATCH) {
5846 /* Free uninterned attribute. */
5847 bgp_attr_flush(&attr_tmp);
718e3744 5848
d62a17ae 5849 /* Unintern original. */
5850 aspath_unintern(&attr.aspath);
5851 bgp_static_withdraw(bgp, p, afi, safi);
5852 return;
5853 }
7f323236 5854
637e5ba4 5855 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5856 bgp_attr_add_gshut_community(&attr_tmp);
5857
d62a17ae 5858 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5859 } else {
5860
637e5ba4 5861 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5862 bgp_attr_add_gshut_community(&attr);
5863
d62a17ae 5864 attr_new = bgp_attr_intern(&attr);
7f323236 5865 }
718e3744 5866
9bcb3eef 5867 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5868 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5869 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5870 break;
5871
40381db7
DS
5872 if (pi) {
5873 if (attrhash_cmp(pi->attr, attr_new)
5874 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5875 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5876 bgp_dest_unlock_node(dest);
d62a17ae 5877 bgp_attr_unintern(&attr_new);
5878 aspath_unintern(&attr.aspath);
5879 return;
5880 } else {
5881 /* The attribute is changed. */
9bcb3eef 5882 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5883
5884 /* Rewrite BGP route information. */
40381db7 5885 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5886 bgp_path_info_restore(dest, pi);
d62a17ae 5887 else
40381db7 5888 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5889#ifdef ENABLE_BGP_VNC
d62a17ae 5890 if ((afi == AFI_IP || afi == AFI_IP6)
5891 && (safi == SAFI_UNICAST)) {
40381db7 5892 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5893 /*
5894 * Implicit withdraw case.
40381db7 5895 * We have to do this before pi is
d62a17ae 5896 * changed
5897 */
5898 ++vnc_implicit_withdraw;
40381db7 5899 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5900 vnc_import_bgp_exterior_del_route(
40381db7 5901 bgp, p, pi);
d62a17ae 5902 }
5903 }
65efcfce 5904#endif
40381db7
DS
5905 bgp_attr_unintern(&pi->attr);
5906 pi->attr = attr_new;
5907 pi->uptime = bgp_clock();
49e5a4a0 5908#ifdef ENABLE_BGP_VNC
d62a17ae 5909 if ((afi == AFI_IP || afi == AFI_IP6)
5910 && (safi == SAFI_UNICAST)) {
5911 if (vnc_implicit_withdraw) {
40381db7 5912 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5913 vnc_import_bgp_exterior_add_route(
40381db7 5914 bgp, p, pi);
d62a17ae 5915 }
5916 }
65efcfce 5917#endif
718e3744 5918
d62a17ae 5919 /* Nexthop reachability check. */
892fedb6 5920 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5921 && (safi == SAFI_UNICAST
5922 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5923
5924 struct bgp *bgp_nexthop = bgp;
5925
40381db7
DS
5926 if (pi->extra && pi->extra->bgp_orig)
5927 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5928
5929 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5930 afi, safi, pi, NULL,
654a5978 5931 0, p))
9bcb3eef 5932 bgp_path_info_set_flag(dest, pi,
18ee8310 5933 BGP_PATH_VALID);
d62a17ae 5934 else {
5935 if (BGP_DEBUG(nht, NHT)) {
5936 char buf1[INET6_ADDRSTRLEN];
5937 inet_ntop(p->family,
5938 &p->u.prefix, buf1,
5939 INET6_ADDRSTRLEN);
5940 zlog_debug(
5941 "%s(%s): Route not in table, not advertising",
15569c58 5942 __func__, buf1);
d62a17ae 5943 }
18ee8310 5944 bgp_path_info_unset_flag(
9bcb3eef 5945 dest, pi, BGP_PATH_VALID);
d62a17ae 5946 }
5947 } else {
5948 /* Delete the NHT structure if any, if we're
5949 * toggling between
5950 * enabling/disabling import check. We
5951 * deregister the route
5952 * from NHT to avoid overloading NHT and the
5953 * process interaction
5954 */
40381db7 5955 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5956 bgp_path_info_set_flag(dest, pi,
5957 BGP_PATH_VALID);
d62a17ae 5958 }
5959 /* Process change. */
40381db7 5960 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5961 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5962
5963 if (SAFI_UNICAST == safi
5964 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5965 || bgp->inst_type
5966 == BGP_INSTANCE_TYPE_DEFAULT)) {
5967 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5968 pi);
ddb5b488
PZ
5969 }
5970
9bcb3eef 5971 bgp_dest_unlock_node(dest);
d62a17ae 5972 aspath_unintern(&attr.aspath);
5973 return;
5974 }
718e3744 5975 }
718e3744 5976
d62a17ae 5977 /* Make new BGP info. */
5978 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5979 attr_new, dest);
d62a17ae 5980 /* Nexthop reachability check. */
892fedb6 5981 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5982 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5983 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5984 p))
9bcb3eef 5985 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5986 else {
5987 if (BGP_DEBUG(nht, NHT)) {
5988 char buf1[INET6_ADDRSTRLEN];
5989 inet_ntop(p->family, &p->u.prefix, buf1,
5990 INET6_ADDRSTRLEN);
5991 zlog_debug(
5992 "%s(%s): Route not in table, not advertising",
15569c58 5993 __func__, buf1);
d62a17ae 5994 }
9bcb3eef 5995 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5996 }
5997 } else {
5998 /* Delete the NHT structure if any, if we're toggling between
5999 * enabling/disabling import check. We deregister the route
6000 * from NHT to avoid overloading NHT and the process interaction
6001 */
6002 bgp_unlink_nexthop(new);
6003
9bcb3eef 6004 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6005 }
078430f6 6006
d62a17ae 6007 /* Aggregate address increment. */
6008 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6009
d62a17ae 6010 /* Register new BGP information. */
9bcb3eef 6011 bgp_path_info_add(dest, new);
718e3744 6012
d62a17ae 6013 /* route_node_get lock */
9bcb3eef 6014 bgp_dest_unlock_node(dest);
d62a17ae 6015
6016 /* Process change. */
9bcb3eef 6017 bgp_process(bgp, dest, afi, safi);
d62a17ae 6018
ddb5b488
PZ
6019 if (SAFI_UNICAST == safi
6020 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6021 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6022 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6023 }
6024
d62a17ae 6025 /* Unintern original. */
6026 aspath_unintern(&attr.aspath);
718e3744 6027}
6028
5f040085 6029void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6030 safi_t safi)
718e3744 6031{
9bcb3eef 6032 struct bgp_dest *dest;
40381db7 6033 struct bgp_path_info *pi;
718e3744 6034
9bcb3eef 6035 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6036
d62a17ae 6037 /* Check selected route and self inserted route. */
9bcb3eef 6038 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6039 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6040 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6041 break;
6042
6043 /* Withdraw static BGP route from routing table. */
40381db7 6044 if (pi) {
ddb5b488
PZ
6045 if (SAFI_UNICAST == safi
6046 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6047 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6048 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6049 }
40381db7
DS
6050 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6051 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6052 bgp_path_info_delete(dest, pi);
6053 bgp_process(bgp, dest, afi, safi);
d62a17ae 6054 }
718e3744 6055
d62a17ae 6056 /* Unlock bgp_node_lookup. */
9bcb3eef 6057 bgp_dest_unlock_node(dest);
718e3744 6058}
6059
137446f9
LB
6060/*
6061 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6062 */
5f040085 6063static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6064 afi_t afi, safi_t safi,
6065 struct prefix_rd *prd)
718e3744 6066{
9bcb3eef 6067 struct bgp_dest *dest;
40381db7 6068 struct bgp_path_info *pi;
718e3744 6069
9bcb3eef 6070 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6071
d62a17ae 6072 /* Check selected route and self inserted route. */
9bcb3eef 6073 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6074 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6075 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6076 break;
718e3744 6077
d62a17ae 6078 /* Withdraw static BGP route from routing table. */
40381db7 6079 if (pi) {
49e5a4a0 6080#ifdef ENABLE_BGP_VNC
d62a17ae 6081 rfapiProcessWithdraw(
40381db7 6082 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6083 1); /* Kill, since it is an administrative change */
65efcfce 6084#endif
ddb5b488
PZ
6085 if (SAFI_MPLS_VPN == safi
6086 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6087 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6088 }
40381db7 6089 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6090 bgp_path_info_delete(dest, pi);
6091 bgp_process(bgp, dest, afi, safi);
d62a17ae 6092 }
718e3744 6093
d62a17ae 6094 /* Unlock bgp_node_lookup. */
9bcb3eef 6095 bgp_dest_unlock_node(dest);
718e3744 6096}
6097
5f040085 6098static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6099 struct bgp_static *bgp_static, afi_t afi,
6100 safi_t safi)
137446f9 6101{
9bcb3eef 6102 struct bgp_dest *dest;
4b7e6066 6103 struct bgp_path_info *new;
d62a17ae 6104 struct attr *attr_new;
6105 struct attr attr = {0};
40381db7 6106 struct bgp_path_info *pi;
49e5a4a0 6107#ifdef ENABLE_BGP_VNC
d62a17ae 6108 mpls_label_t label = 0;
65efcfce 6109#endif
d7c0a89a 6110 uint32_t num_labels = 0;
137446f9 6111
d62a17ae 6112 assert(bgp_static);
137446f9 6113
b57ba6d2
MK
6114 if (bgp_static->label != MPLS_INVALID_LABEL)
6115 num_labels = 1;
9bcb3eef
DS
6116 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6117 &bgp_static->prd);
137446f9 6118
d62a17ae 6119 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 6120
d62a17ae 6121 attr.nexthop = bgp_static->igpnexthop;
6122 attr.med = bgp_static->igpmetric;
6123 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6124
d62a17ae 6125 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6126 || (safi == SAFI_ENCAP)) {
6127 if (afi == AFI_IP) {
6128 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6129 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6130 }
6131 }
6132 if (afi == AFI_L2VPN) {
b04c1e99
IR
6133 if (bgp_static->gatewayIp.family == AF_INET) {
6134 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6135 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6136 &bgp_static->gatewayIp.u.prefix4,
6137 IPV4_MAX_BYTELEN);
b04c1e99
IR
6138 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6139 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6140 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6141 &bgp_static->gatewayIp.u.prefix6,
6142 IPV6_MAX_BYTELEN);
b04c1e99 6143 }
0a50c248 6144 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6145 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6146 struct bgp_encap_type_vxlan bet;
6147 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 6148 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6149 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6150 }
6151 if (bgp_static->router_mac) {
6152 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6153 }
6154 }
6155 /* Apply route-map. */
6156 if (bgp_static->rmap.name) {
6157 struct attr attr_tmp = attr;
40381db7 6158 struct bgp_path_info rmap_path;
b68885f9 6159 route_map_result_t ret;
137446f9 6160
40381db7
DS
6161 rmap_path.peer = bgp->peer_self;
6162 rmap_path.attr = &attr_tmp;
137446f9 6163
d62a17ae 6164 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6165
1782514f 6166 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6167
d62a17ae 6168 bgp->peer_self->rmap_type = 0;
137446f9 6169
d62a17ae 6170 if (ret == RMAP_DENYMATCH) {
6171 /* Free uninterned attribute. */
6172 bgp_attr_flush(&attr_tmp);
137446f9 6173
d62a17ae 6174 /* Unintern original. */
6175 aspath_unintern(&attr.aspath);
6176 bgp_static_withdraw_safi(bgp, p, afi, safi,
6177 &bgp_static->prd);
6178 return;
6179 }
137446f9 6180
d62a17ae 6181 attr_new = bgp_attr_intern(&attr_tmp);
6182 } else {
6183 attr_new = bgp_attr_intern(&attr);
6184 }
137446f9 6185
9bcb3eef 6186 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6187 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6188 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6189 break;
6190
40381db7 6191 if (pi) {
40381db7 6192 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6193 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6194 bgp_dest_unlock_node(dest);
d62a17ae 6195 bgp_attr_unintern(&attr_new);
6196 aspath_unintern(&attr.aspath);
6197 return;
6198 } else {
6199 /* The attribute is changed. */
9bcb3eef 6200 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6201
6202 /* Rewrite BGP route information. */
40381db7 6203 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6204 bgp_path_info_restore(dest, pi);
d62a17ae 6205 else
40381db7
DS
6206 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6207 bgp_attr_unintern(&pi->attr);
6208 pi->attr = attr_new;
6209 pi->uptime = bgp_clock();
49e5a4a0 6210#ifdef ENABLE_BGP_VNC
40381db7
DS
6211 if (pi->extra)
6212 label = decode_label(&pi->extra->label[0]);
65efcfce 6213#endif
137446f9 6214
d62a17ae 6215 /* Process change. */
40381db7 6216 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6217 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6218
6219 if (SAFI_MPLS_VPN == safi
6220 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6221 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6222 }
49e5a4a0 6223#ifdef ENABLE_BGP_VNC
40381db7
DS
6224 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6225 pi->attr, afi, safi, pi->type,
6226 pi->sub_type, &label);
65efcfce 6227#endif
9bcb3eef 6228 bgp_dest_unlock_node(dest);
d62a17ae 6229 aspath_unintern(&attr.aspath);
6230 return;
6231 }
6232 }
137446f9
LB
6233
6234
d62a17ae 6235 /* Make new BGP info. */
6236 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6237 attr_new, dest);
1defdda8 6238 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6239 bgp_path_info_extra_get(new);
b57ba6d2
MK
6240 if (num_labels) {
6241 new->extra->label[0] = bgp_static->label;
6242 new->extra->num_labels = num_labels;
6243 }
49e5a4a0 6244#ifdef ENABLE_BGP_VNC
d62a17ae 6245 label = decode_label(&bgp_static->label);
65efcfce 6246#endif
137446f9 6247
d62a17ae 6248 /* Aggregate address increment. */
6249 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6250
d62a17ae 6251 /* Register new BGP information. */
9bcb3eef 6252 bgp_path_info_add(dest, new);
d62a17ae 6253 /* route_node_get lock */
9bcb3eef 6254 bgp_dest_unlock_node(dest);
137446f9 6255
d62a17ae 6256 /* Process change. */
9bcb3eef 6257 bgp_process(bgp, dest, afi, safi);
137446f9 6258
ddb5b488
PZ
6259 if (SAFI_MPLS_VPN == safi
6260 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6261 vpn_leak_to_vrf_update(bgp, new);
6262 }
49e5a4a0 6263#ifdef ENABLE_BGP_VNC
d62a17ae 6264 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6265 safi, new->type, new->sub_type, &label);
65efcfce
LB
6266#endif
6267
d62a17ae 6268 /* Unintern original. */
6269 aspath_unintern(&attr.aspath);
137446f9
LB
6270}
6271
718e3744 6272/* Configure static BGP network. When user don't run zebra, static
6273 route should be installed as valid. */
585f1adc
IR
6274static int bgp_static_set(struct vty *vty, const char *negate,
6275 const char *ip_str, afi_t afi, safi_t safi,
6276 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6277{
585f1adc
IR
6278 VTY_DECLVAR_CONTEXT(bgp, bgp);
6279 int ret;
d62a17ae 6280 struct prefix p;
6281 struct bgp_static *bgp_static;
9bcb3eef 6282 struct bgp_dest *dest;
d7c0a89a 6283 uint8_t need_update = 0;
d62a17ae 6284
585f1adc
IR
6285 /* Convert IP prefix string to struct prefix. */
6286 ret = str2prefix(ip_str, &p);
6287 if (!ret) {
6288 vty_out(vty, "%% Malformed prefix\n");
6289 return CMD_WARNING_CONFIG_FAILED;
6290 }
6291 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6292 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6293 return CMD_WARNING_CONFIG_FAILED;
6294 }
6295
d62a17ae 6296 apply_mask(&p);
718e3744 6297
e2a86ad9 6298 if (negate) {
718e3744 6299
e2a86ad9 6300 /* Set BGP static route configuration. */
9bcb3eef 6301 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6302
9bcb3eef 6303 if (!dest) {
585f1adc
IR
6304 vty_out(vty, "%% Can't find static route specified\n");
6305 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6306 }
6307
9bcb3eef 6308 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6309
e2a86ad9
DS
6310 if ((label_index != BGP_INVALID_LABEL_INDEX)
6311 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6312 vty_out(vty,
6313 "%% label-index doesn't match static route\n");
70d9b134 6314 bgp_dest_unlock_node(dest);
585f1adc 6315 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6316 }
d62a17ae 6317
e2a86ad9
DS
6318 if ((rmap && bgp_static->rmap.name)
6319 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6320 vty_out(vty,
6321 "%% route-map name doesn't match static route\n");
70d9b134 6322 bgp_dest_unlock_node(dest);
585f1adc 6323 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6324 }
718e3744 6325
e2a86ad9
DS
6326 /* Update BGP RIB. */
6327 if (!bgp_static->backdoor)
6328 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6329
e2a86ad9
DS
6330 /* Clear configuration. */
6331 bgp_static_free(bgp_static);
9bcb3eef
DS
6332 bgp_dest_set_bgp_static_info(dest, NULL);
6333 bgp_dest_unlock_node(dest);
6334 bgp_dest_unlock_node(dest);
e2a86ad9 6335 } else {
718e3744 6336
e2a86ad9 6337 /* Set BGP static route configuration. */
9bcb3eef
DS
6338 dest = bgp_node_get(bgp->route[afi][safi], &p);
6339 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6340 if (bgp_static) {
e2a86ad9 6341 /* Configuration change. */
e2a86ad9
DS
6342 /* Label index cannot be changed. */
6343 if (bgp_static->label_index != label_index) {
585f1adc
IR
6344 vty_out(vty, "%% cannot change label-index\n");
6345 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6346 }
d62a17ae 6347
e2a86ad9 6348 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6349 if (bgp_static->valid
6350 && bgp_static->backdoor != backdoor)
e2a86ad9 6351 need_update = 1;
718e3744 6352
e2a86ad9 6353 bgp_static->backdoor = backdoor;
718e3744 6354
e2a86ad9 6355 if (rmap) {
0a22ddfb
QY
6356 XFREE(MTYPE_ROUTE_MAP_NAME,
6357 bgp_static->rmap.name);
b4897fa5 6358 route_map_counter_decrement(
6359 bgp_static->rmap.map);
e2a86ad9
DS
6360 bgp_static->rmap.name =
6361 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6362 bgp_static->rmap.map =
6363 route_map_lookup_by_name(rmap);
b4897fa5 6364 route_map_counter_increment(
6365 bgp_static->rmap.map);
e2a86ad9 6366 } else {
0a22ddfb
QY
6367 XFREE(MTYPE_ROUTE_MAP_NAME,
6368 bgp_static->rmap.name);
b4897fa5 6369 route_map_counter_decrement(
6370 bgp_static->rmap.map);
e2a86ad9
DS
6371 bgp_static->rmap.map = NULL;
6372 bgp_static->valid = 0;
6373 }
9bcb3eef 6374 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6375 } else {
6376 /* New configuration. */
6377 bgp_static = bgp_static_new();
6378 bgp_static->backdoor = backdoor;
6379 bgp_static->valid = 0;
6380 bgp_static->igpmetric = 0;
975a328e 6381 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6382 bgp_static->label_index = label_index;
718e3744 6383
e2a86ad9 6384 if (rmap) {
0a22ddfb
QY
6385 XFREE(MTYPE_ROUTE_MAP_NAME,
6386 bgp_static->rmap.name);
b4897fa5 6387 route_map_counter_decrement(
6388 bgp_static->rmap.map);
e2a86ad9
DS
6389 bgp_static->rmap.name =
6390 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6391 bgp_static->rmap.map =
6392 route_map_lookup_by_name(rmap);
b4897fa5 6393 route_map_counter_increment(
6394 bgp_static->rmap.map);
e2a86ad9 6395 }
9bcb3eef 6396 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6397 }
d62a17ae 6398
e2a86ad9
DS
6399 bgp_static->valid = 1;
6400 if (need_update)
6401 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6402
e2a86ad9
DS
6403 if (!bgp_static->backdoor)
6404 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6405 }
d62a17ae 6406
585f1adc 6407 return CMD_SUCCESS;
d62a17ae 6408}
6409
6410void bgp_static_add(struct bgp *bgp)
6411{
6412 afi_t afi;
6413 safi_t safi;
9bcb3eef
DS
6414 struct bgp_dest *dest;
6415 struct bgp_dest *rm;
d62a17ae 6416 struct bgp_table *table;
6417 struct bgp_static *bgp_static;
6418
47fc6261 6419 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6420 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6421 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6422 dest = bgp_route_next(dest)) {
6423 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6424 continue;
ea47320b 6425
05c7a1cc
QY
6426 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6427 || (safi == SAFI_EVPN)) {
9bcb3eef 6428 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6429
6430 for (rm = bgp_table_top(table); rm;
6431 rm = bgp_route_next(rm)) {
a78beeb5 6432 bgp_static =
9bcb3eef 6433 bgp_dest_get_bgp_static_info(
5a8ba9fc 6434 rm);
9bcb3eef
DS
6435 bgp_static_update_safi(
6436 bgp, bgp_dest_get_prefix(rm),
6437 bgp_static, afi, safi);
d62a17ae 6438 }
05c7a1cc 6439 } else {
5a8ba9fc 6440 bgp_static_update(
9bcb3eef
DS
6441 bgp, bgp_dest_get_prefix(dest),
6442 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6443 safi);
ea47320b 6444 }
05c7a1cc 6445 }
47fc6261 6446 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6447}
6448
718e3744 6449/* Called from bgp_delete(). Delete all static routes from the BGP
6450 instance. */
d62a17ae 6451void bgp_static_delete(struct bgp *bgp)
6452{
6453 afi_t afi;
6454 safi_t safi;
9bcb3eef
DS
6455 struct bgp_dest *dest;
6456 struct bgp_dest *rm;
d62a17ae 6457 struct bgp_table *table;
6458 struct bgp_static *bgp_static;
6459
05c7a1cc 6460 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6461 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6462 dest = bgp_route_next(dest)) {
6463 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6464 continue;
ea47320b 6465
05c7a1cc
QY
6466 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6467 || (safi == SAFI_EVPN)) {
9bcb3eef 6468 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6469
6470 for (rm = bgp_table_top(table); rm;
6471 rm = bgp_route_next(rm)) {
a78beeb5 6472 bgp_static =
9bcb3eef 6473 bgp_dest_get_bgp_static_info(
5a8ba9fc 6474 rm);
c7d14ba6
PG
6475 if (!bgp_static)
6476 continue;
6477
05c7a1cc 6478 bgp_static_withdraw_safi(
9bcb3eef 6479 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6480 AFI_IP, safi,
6481 (struct prefix_rd *)
9bcb3eef
DS
6482 bgp_dest_get_prefix(
6483 dest));
ea47320b 6484 bgp_static_free(bgp_static);
811c6797 6485 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6486 NULL);
811c6797 6487 bgp_dest_unlock_node(rm);
d62a17ae 6488 }
05c7a1cc 6489 } else {
9bcb3eef 6490 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6491 bgp_static_withdraw(bgp,
9bcb3eef 6492 bgp_dest_get_prefix(dest),
b54892e0 6493 afi, safi);
05c7a1cc 6494 bgp_static_free(bgp_static);
9bcb3eef
DS
6495 bgp_dest_set_bgp_static_info(dest, NULL);
6496 bgp_dest_unlock_node(dest);
ea47320b 6497 }
05c7a1cc 6498 }
d62a17ae 6499}
6500
6501void bgp_static_redo_import_check(struct bgp *bgp)
6502{
6503 afi_t afi;
6504 safi_t safi;
9bcb3eef
DS
6505 struct bgp_dest *dest;
6506 struct bgp_dest *rm;
d62a17ae 6507 struct bgp_table *table;
6508 struct bgp_static *bgp_static;
6509
6510 /* Use this flag to force reprocessing of the route */
892fedb6 6511 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6512 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6513 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6514 dest = bgp_route_next(dest)) {
6515 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6516 continue;
ea47320b 6517
05c7a1cc
QY
6518 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6519 || (safi == SAFI_EVPN)) {
9bcb3eef 6520 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6521
6522 for (rm = bgp_table_top(table); rm;
6523 rm = bgp_route_next(rm)) {
a78beeb5 6524 bgp_static =
9bcb3eef 6525 bgp_dest_get_bgp_static_info(
5a8ba9fc 6526 rm);
9bcb3eef
DS
6527 bgp_static_update_safi(
6528 bgp, bgp_dest_get_prefix(rm),
6529 bgp_static, afi, safi);
d62a17ae 6530 }
05c7a1cc 6531 } else {
9bcb3eef
DS
6532 bgp_static = bgp_dest_get_bgp_static_info(dest);
6533 bgp_static_update(bgp,
6534 bgp_dest_get_prefix(dest),
6535 bgp_static, afi, safi);
ea47320b 6536 }
05c7a1cc
QY
6537 }
6538 }
892fedb6 6539 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6540}
6541
6542static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6543 safi_t safi)
6544{
6545 struct bgp_table *table;
9bcb3eef 6546 struct bgp_dest *dest;
40381db7 6547 struct bgp_path_info *pi;
d62a17ae 6548
dfb6fd1d
NT
6549 /* Do not install the aggregate route if BGP is in the
6550 * process of termination.
6551 */
892fedb6
DA
6552 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6553 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6554 return;
6555
d62a17ae 6556 table = bgp->rib[afi][safi];
9bcb3eef
DS
6557 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6558 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6559 if (pi->peer == bgp->peer_self
6560 && ((pi->type == ZEBRA_ROUTE_BGP
6561 && pi->sub_type == BGP_ROUTE_STATIC)
6562 || (pi->type != ZEBRA_ROUTE_BGP
6563 && pi->sub_type
d62a17ae 6564 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6565 bgp_aggregate_decrement(
6566 bgp, bgp_dest_get_prefix(dest), pi, afi,
6567 safi);
40381db7 6568 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6569 bgp_path_info_delete(dest, pi);
6570 bgp_process(bgp, dest, afi, safi);
d62a17ae 6571 }
6572 }
6573 }
ad4cbda1 6574}
6575
6576/*
6577 * Purge all networks and redistributed routes from routing table.
6578 * Invoked upon the instance going down.
6579 */
d62a17ae 6580void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6581{
d62a17ae 6582 afi_t afi;
6583 safi_t safi;
ad4cbda1 6584
05c7a1cc
QY
6585 FOREACH_AFI_SAFI (afi, safi)
6586 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6587}
6588
137446f9
LB
6589/*
6590 * gpz 110624
6591 * Currently this is used to set static routes for VPN and ENCAP.
6592 * I think it can probably be factored with bgp_static_set.
6593 */
d62a17ae 6594int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6595 const char *ip_str, const char *rd_str,
6596 const char *label_str, const char *rmap_str,
6597 int evpn_type, const char *esi, const char *gwip,
6598 const char *ethtag, const char *routermac)
6599{
6600 VTY_DECLVAR_CONTEXT(bgp, bgp);
6601 int ret;
6602 struct prefix p;
6603 struct prefix_rd prd;
9bcb3eef
DS
6604 struct bgp_dest *pdest;
6605 struct bgp_dest *dest;
d62a17ae 6606 struct bgp_table *table;
6607 struct bgp_static *bgp_static;
6608 mpls_label_t label = MPLS_INVALID_LABEL;
6609 struct prefix gw_ip;
6610
6611 /* validate ip prefix */
6612 ret = str2prefix(ip_str, &p);
6613 if (!ret) {
6614 vty_out(vty, "%% Malformed prefix\n");
6615 return CMD_WARNING_CONFIG_FAILED;
6616 }
6617 apply_mask(&p);
6618 if ((afi == AFI_L2VPN)
6619 && (bgp_build_evpn_prefix(evpn_type,
6620 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6621 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6622 return CMD_WARNING_CONFIG_FAILED;
6623 }
718e3744 6624
d62a17ae 6625 ret = str2prefix_rd(rd_str, &prd);
6626 if (!ret) {
6627 vty_out(vty, "%% Malformed rd\n");
6628 return CMD_WARNING_CONFIG_FAILED;
6629 }
718e3744 6630
d62a17ae 6631 if (label_str) {
6632 unsigned long label_val;
6633 label_val = strtoul(label_str, NULL, 10);
6634 encode_label(label_val, &label);
6635 }
9bedbb1e 6636
d62a17ae 6637 if (safi == SAFI_EVPN) {
6638 if (esi && str2esi(esi, NULL) == 0) {
6639 vty_out(vty, "%% Malformed ESI\n");
6640 return CMD_WARNING_CONFIG_FAILED;
6641 }
6642 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6643 vty_out(vty, "%% Malformed Router MAC\n");
6644 return CMD_WARNING_CONFIG_FAILED;
6645 }
6646 if (gwip) {
6647 memset(&gw_ip, 0, sizeof(struct prefix));
6648 ret = str2prefix(gwip, &gw_ip);
6649 if (!ret) {
6650 vty_out(vty, "%% Malformed GatewayIp\n");
6651 return CMD_WARNING_CONFIG_FAILED;
6652 }
6653 if ((gw_ip.family == AF_INET
3714a385 6654 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6655 (struct prefix_evpn *)&p))
6656 || (gw_ip.family == AF_INET6
3714a385 6657 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6658 (struct prefix_evpn *)&p))) {
6659 vty_out(vty,
6660 "%% GatewayIp family differs with IP prefix\n");
6661 return CMD_WARNING_CONFIG_FAILED;
6662 }
6663 }
6664 }
9bcb3eef
DS
6665 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6666 if (!bgp_dest_has_bgp_path_info_data(pdest))
6667 bgp_dest_set_bgp_table_info(pdest,
67009e22 6668 bgp_table_init(bgp, afi, safi));
9bcb3eef 6669 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6670
9bcb3eef 6671 dest = bgp_node_get(table, &p);
d62a17ae 6672
9bcb3eef 6673 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6674 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6675 bgp_dest_unlock_node(dest);
d62a17ae 6676 } else {
6677 /* New configuration. */
6678 bgp_static = bgp_static_new();
6679 bgp_static->backdoor = 0;
6680 bgp_static->valid = 0;
6681 bgp_static->igpmetric = 0;
975a328e 6682 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6683 bgp_static->label = label;
6684 bgp_static->prd = prd;
6685
6686 if (rmap_str) {
0a22ddfb 6687 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6688 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6689 bgp_static->rmap.name =
6690 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6691 bgp_static->rmap.map =
6692 route_map_lookup_by_name(rmap_str);
b4897fa5 6693 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6694 }
718e3744 6695
d62a17ae 6696 if (safi == SAFI_EVPN) {
6697 if (esi) {
6698 bgp_static->eth_s_id =
6699 XCALLOC(MTYPE_ATTR,
0a50c248 6700 sizeof(esi_t));
d62a17ae 6701 str2esi(esi, bgp_static->eth_s_id);
6702 }
6703 if (routermac) {
6704 bgp_static->router_mac =
28328ea9 6705 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6706 (void)prefix_str2mac(routermac,
6707 bgp_static->router_mac);
d62a17ae 6708 }
6709 if (gwip)
6710 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6711 }
9bcb3eef 6712 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6713
d62a17ae 6714 bgp_static->valid = 1;
6715 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6716 }
718e3744 6717
d62a17ae 6718 return CMD_SUCCESS;
718e3744 6719}
6720
6721/* Configure static BGP network. */
d62a17ae 6722int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6723 const char *ip_str, const char *rd_str,
6724 const char *label_str, int evpn_type, const char *esi,
6725 const char *gwip, const char *ethtag)
6726{
6727 VTY_DECLVAR_CONTEXT(bgp, bgp);
6728 int ret;
6729 struct prefix p;
6730 struct prefix_rd prd;
9bcb3eef
DS
6731 struct bgp_dest *pdest;
6732 struct bgp_dest *dest;
d62a17ae 6733 struct bgp_table *table;
6734 struct bgp_static *bgp_static;
6735 mpls_label_t label = MPLS_INVALID_LABEL;
6736
6737 /* Convert IP prefix string to struct prefix. */
6738 ret = str2prefix(ip_str, &p);
6739 if (!ret) {
6740 vty_out(vty, "%% Malformed prefix\n");
6741 return CMD_WARNING_CONFIG_FAILED;
6742 }
6743 apply_mask(&p);
6744 if ((afi == AFI_L2VPN)
6745 && (bgp_build_evpn_prefix(evpn_type,
6746 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6747 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6748 return CMD_WARNING_CONFIG_FAILED;
6749 }
6750 ret = str2prefix_rd(rd_str, &prd);
6751 if (!ret) {
6752 vty_out(vty, "%% Malformed rd\n");
6753 return CMD_WARNING_CONFIG_FAILED;
6754 }
718e3744 6755
d62a17ae 6756 if (label_str) {
6757 unsigned long label_val;
6758 label_val = strtoul(label_str, NULL, 10);
6759 encode_label(label_val, &label);
6760 }
718e3744 6761
9bcb3eef
DS
6762 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6763 if (!bgp_dest_has_bgp_path_info_data(pdest))
6764 bgp_dest_set_bgp_table_info(pdest,
67009e22 6765 bgp_table_init(bgp, afi, safi));
d62a17ae 6766 else
9bcb3eef
DS
6767 bgp_dest_unlock_node(pdest);
6768 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6769
9bcb3eef 6770 dest = bgp_node_lookup(table, &p);
6b0655a2 6771
9bcb3eef 6772 if (dest) {
d62a17ae 6773 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6774
9bcb3eef 6775 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6776 bgp_static_free(bgp_static);
9bcb3eef
DS
6777 bgp_dest_set_bgp_static_info(dest, NULL);
6778 bgp_dest_unlock_node(dest);
6779 bgp_dest_unlock_node(dest);
d62a17ae 6780 } else
6781 vty_out(vty, "%% Can't find the route\n");
6782
6783 return CMD_SUCCESS;
6784}
6785
6786static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6787 const char *rmap_name)
6788{
6789 VTY_DECLVAR_CONTEXT(bgp, bgp);
6790 struct bgp_rmap *rmap;
6791
6792 rmap = &bgp->table_map[afi][safi];
6793 if (rmap_name) {
0a22ddfb 6794 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6795 route_map_counter_decrement(rmap->map);
d62a17ae 6796 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6797 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6798 route_map_counter_increment(rmap->map);
d62a17ae 6799 } else {
0a22ddfb 6800 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6801 route_map_counter_decrement(rmap->map);
d62a17ae 6802 rmap->map = NULL;
6803 }
73ac8160 6804
d62a17ae 6805 if (bgp_fibupd_safi(safi))
6806 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6807
d62a17ae 6808 return CMD_SUCCESS;
73ac8160
DS
6809}
6810
d62a17ae 6811static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6812 const char *rmap_name)
73ac8160 6813{
d62a17ae 6814 VTY_DECLVAR_CONTEXT(bgp, bgp);
6815 struct bgp_rmap *rmap;
73ac8160 6816
d62a17ae 6817 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6818 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6819 route_map_counter_decrement(rmap->map);
d62a17ae 6820 rmap->map = NULL;
73ac8160 6821
d62a17ae 6822 if (bgp_fibupd_safi(safi))
6823 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6824
d62a17ae 6825 return CMD_SUCCESS;
73ac8160
DS
6826}
6827
2b791107 6828void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6829 safi_t safi)
73ac8160 6830{
d62a17ae 6831 if (bgp->table_map[afi][safi].name) {
d62a17ae 6832 vty_out(vty, " table-map %s\n",
6833 bgp->table_map[afi][safi].name);
6834 }
73ac8160
DS
6835}
6836
73ac8160
DS
6837DEFUN (bgp_table_map,
6838 bgp_table_map_cmd,
6839 "table-map WORD",
6840 "BGP table to RIB route download filter\n"
6841 "Name of the route map\n")
6842{
d62a17ae 6843 int idx_word = 1;
6844 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6845 argv[idx_word]->arg);
73ac8160
DS
6846}
6847DEFUN (no_bgp_table_map,
6848 no_bgp_table_map_cmd,
6849 "no table-map WORD",
3a2d747c 6850 NO_STR
73ac8160
DS
6851 "BGP table to RIB route download filter\n"
6852 "Name of the route map\n")
6853{
d62a17ae 6854 int idx_word = 2;
6855 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6856 argv[idx_word]->arg);
73ac8160
DS
6857}
6858
585f1adc
IR
6859DEFPY(bgp_network,
6860 bgp_network_cmd,
6861 "[no] network \
6862 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6863 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6864 backdoor$backdoor}]",
6865 NO_STR
6866 "Specify a network to announce via BGP\n"
6867 "IPv4 prefix\n"
6868 "Network number\n"
6869 "Network mask\n"
6870 "Network mask\n"
6871 "Route-map to modify the attributes\n"
6872 "Name of the route map\n"
6873 "Label index to associate with the prefix\n"
6874 "Label index value\n"
6875 "Specify a BGP backdoor route\n")
6876{
6877 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6878
6879 if (address_str) {
6880 int ret;
718e3744 6881
e2a86ad9 6882 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6883 addr_prefix_str,
6884 sizeof(addr_prefix_str));
e2a86ad9
DS
6885 if (!ret) {
6886 vty_out(vty, "%% Inconsistent address and mask\n");
6887 return CMD_WARNING_CONFIG_FAILED;
6888 }
d62a17ae 6889 }
718e3744 6890
585f1adc
IR
6891 return bgp_static_set(
6892 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6893 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6894 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6895}
6896
585f1adc
IR
6897DEFPY(ipv6_bgp_network,
6898 ipv6_bgp_network_cmd,
6899 "[no] network X:X::X:X/M$prefix \
6900 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6901 NO_STR
6902 "Specify a network to announce via BGP\n"
6903 "IPv6 prefix\n"
6904 "Route-map to modify the attributes\n"
6905 "Name of the route map\n"
6906 "Label index to associate with the prefix\n"
6907 "Label index value\n")
37a87b8f 6908{
585f1adc
IR
6909 return bgp_static_set(
6910 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6911 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6912}
6913
d62a17ae 6914static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6915{
d62a17ae 6916 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6917}
6918
d62a17ae 6919static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6920{
365ab2e7
RZ
6921 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6922 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6923 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6924 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6925 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6926}
718e3744 6927
365ab2e7
RZ
6928/**
6929 * Helper function to avoid repeated code: prepare variables for a
6930 * `route_map_apply` call.
6931 *
6932 * \returns `true` on route map match, otherwise `false`.
6933 */
6934static bool aggr_suppress_map_test(struct bgp *bgp,
6935 struct bgp_aggregate *aggregate,
6936 struct bgp_path_info *pi)
6937{
6938 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6939 route_map_result_t rmr = RMAP_DENYMATCH;
6940 struct bgp_path_info rmap_path = {};
6941 struct attr attr = {};
6942
6943 /* No route map entries created, just don't match. */
6944 if (aggregate->suppress_map == NULL)
6945 return false;
6946
6947 /* Call route map matching and return result. */
6948 attr.aspath = aspath_empty();
6949 rmap_path.peer = bgp->peer_self;
6950 rmap_path.attr = &attr;
6951
6952 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6953 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6954 bgp->peer_self->rmap_type = 0;
6955
6956 bgp_attr_flush(&attr);
afb254d7 6957 aspath_unintern(&attr.aspath);
365ab2e7
RZ
6958
6959 return rmr == RMAP_PERMITMATCH;
6960}
6961
4056a5f6
RZ
6962/** Test whether the aggregation has suppressed this path or not. */
6963static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6964 struct bgp_path_info *pi)
6965{
6966 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6967 return false;
6968
6969 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6970}
6971
6972/**
6973 * Suppress this path and keep the reference.
6974 *
6975 * \returns `true` if needs processing otherwise `false`.
6976 */
6977static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6978 struct bgp_path_info *pi)
6979{
6980 struct bgp_path_info_extra *pie;
6981
6982 /* Path is already suppressed by this aggregation. */
6983 if (aggr_suppress_exists(aggregate, pi))
6984 return false;
6985
6986 pie = bgp_path_info_extra_get(pi);
6987
6988 /* This is the first suppression, allocate memory and list it. */
6989 if (pie->aggr_suppressors == NULL)
6990 pie->aggr_suppressors = list_new();
6991
6992 listnode_add(pie->aggr_suppressors, aggregate);
6993
6994 /* Only mark for processing if suppressed. */
6995 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6996 if (BGP_DEBUG(update, UPDATE_OUT))
6997 zlog_debug("aggregate-address suppressing: %pFX",
6998 bgp_dest_get_prefix(pi->net));
6999
4056a5f6
RZ
7000 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7001 return true;
7002 }
7003
7004 return false;
7005}
7006
7007/**
7008 * Unsuppress this path and remove the reference.
7009 *
7010 * \returns `true` if needs processing otherwise `false`.
7011 */
7012static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7013 struct bgp_path_info *pi)
7014{
7015 /* Path wasn't suppressed. */
7016 if (!aggr_suppress_exists(aggregate, pi))
7017 return false;
7018
7019 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7020
7021 /* Unsuppress and free extra memory if last item. */
7022 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7023 if (BGP_DEBUG(update, UPDATE_OUT))
7024 zlog_debug("aggregate-address unsuppressing: %pFX",
7025 bgp_dest_get_prefix(pi->net));
7026
4056a5f6
RZ
7027 list_delete(&pi->extra->aggr_suppressors);
7028 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7029 return true;
7030 }
7031
7032 return false;
7033}
7034
3dc339cd
DA
7035static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7036 struct aspath *aspath,
7037 struct community *comm,
7038 struct ecommunity *ecomm,
7039 struct lcommunity *lcomm)
eaaf8adb
DS
7040{
7041 static struct aspath *ae = NULL;
7042
7043 if (!ae)
7044 ae = aspath_empty();
7045
40381db7 7046 if (!pi)
3dc339cd 7047 return false;
eaaf8adb 7048
40381db7 7049 if (origin != pi->attr->origin)
3dc339cd 7050 return false;
eaaf8adb 7051
40381db7 7052 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7053 return false;
29f7d023 7054
9a706b42 7055 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7056 return false;
eaaf8adb 7057
b53e67a3 7058 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7059 return false;
eaaf8adb 7060
1bcf3a96 7061 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7062 return false;
dd18c5a9 7063
40381db7 7064 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7065 return false;
7ce8a8e0 7066
3dc339cd 7067 return true;
eaaf8adb
DS
7068}
7069
5f040085
DS
7070static void bgp_aggregate_install(
7071 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7072 uint8_t origin, struct aspath *aspath, struct community *community,
7073 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7074 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7075{
9bcb3eef 7076 struct bgp_dest *dest;
c701010e 7077 struct bgp_table *table;
6f94b685 7078 struct bgp_path_info *pi, *orig, *new;
20894f50 7079 struct attr *attr;
c701010e
DS
7080
7081 table = bgp->rib[afi][safi];
7082
9bcb3eef 7083 dest = bgp_node_get(table, p);
eaaf8adb 7084
9bcb3eef 7085 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7086 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7087 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7088 break;
7089
6aabb15d
RZ
7090 /*
7091 * If we have paths with different MEDs, then don't install
7092 * (or uninstall) the aggregate route.
7093 */
7094 if (aggregate->match_med && aggregate->med_mismatched)
7095 goto uninstall_aggregate_route;
7096
c701010e 7097 if (aggregate->count > 0) {
eaaf8adb
DS
7098 /*
7099 * If the aggregate information has not changed
7100 * no need to re-install it again.
7101 */
6f94b685 7102 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7103 ecommunity, lcommunity)) {
9bcb3eef 7104 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7105
7106 if (aspath)
7107 aspath_free(aspath);
7108 if (community)
3c1f53de 7109 community_free(&community);
3da2cc32
DS
7110 if (ecommunity)
7111 ecommunity_free(&ecommunity);
dd18c5a9
DS
7112 if (lcommunity)
7113 lcommunity_free(&lcommunity);
eaaf8adb
DS
7114
7115 return;
7116 }
7117
7118 /*
7119 * Mark the old as unusable
7120 */
40381db7 7121 if (pi)
9bcb3eef 7122 bgp_path_info_delete(dest, pi);
eaaf8adb 7123
20894f50
DA
7124 attr = bgp_attr_aggregate_intern(
7125 bgp, origin, aspath, community, ecommunity, lcommunity,
7126 aggregate, atomic_aggregate, p);
7127
7128 if (!attr) {
7129 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7130 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7131 zlog_debug("%s: %pFX null attribute", __func__,
7132 p);
20894f50
DA
7133 return;
7134 }
7135
3da2cc32 7136 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7137 bgp->peer_self, attr, dest);
20894f50 7138
1defdda8 7139 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7140
9bcb3eef
DS
7141 bgp_path_info_add(dest, new);
7142 bgp_process(bgp, dest, afi, safi);
c701010e 7143 } else {
6aabb15d 7144 uninstall_aggregate_route:
6f94b685 7145 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7146 if (pi->peer == bgp->peer_self
7147 && pi->type == ZEBRA_ROUTE_BGP
7148 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7149 break;
7150
7151 /* Withdraw static BGP route from routing table. */
40381db7 7152 if (pi) {
9bcb3eef
DS
7153 bgp_path_info_delete(dest, pi);
7154 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7155 }
7156 }
7157
9bcb3eef 7158 bgp_dest_unlock_node(dest);
c701010e
DS
7159}
7160
6aabb15d
RZ
7161/**
7162 * Check if the current path has different MED than other known paths.
7163 *
7164 * \returns `true` if the MED matched the others else `false`.
7165 */
7166static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7167 struct bgp *bgp, struct bgp_path_info *pi)
7168{
7169 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7170
7171 /* This is the first route being analyzed. */
7172 if (!aggregate->med_initialized) {
7173 aggregate->med_initialized = true;
7174 aggregate->med_mismatched = false;
7175 aggregate->med_matched_value = cur_med;
7176 } else {
7177 /* Check if routes with different MED showed up. */
7178 if (cur_med != aggregate->med_matched_value)
7179 aggregate->med_mismatched = true;
7180 }
7181
7182 return !aggregate->med_mismatched;
7183}
7184
7185/**
7186 * Initializes and tests all routes in the aggregate address path for MED
7187 * values.
7188 *
7189 * \returns `true` if all MEDs are the same otherwise `false`.
7190 */
7191static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7192 struct bgp *bgp, const struct prefix *p,
7193 afi_t afi, safi_t safi)
7194{
7195 struct bgp_table *table = bgp->rib[afi][safi];
7196 const struct prefix *dest_p;
7197 struct bgp_dest *dest, *top;
7198 struct bgp_path_info *pi;
7199 bool med_matched = true;
7200
7201 aggregate->med_initialized = false;
7202
7203 top = bgp_node_get(table, p);
7204 for (dest = bgp_node_get(table, p); dest;
7205 dest = bgp_route_next_until(dest, top)) {
7206 dest_p = bgp_dest_get_prefix(dest);
7207 if (dest_p->prefixlen <= p->prefixlen)
7208 continue;
7209
7210 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7211 if (BGP_PATH_HOLDDOWN(pi))
7212 continue;
7213 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7214 continue;
7215 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7216 med_matched = false;
7217 break;
7218 }
7219 }
7220 if (!med_matched)
7221 break;
7222 }
7223 bgp_dest_unlock_node(top);
7224
7225 return med_matched;
7226}
7227
7228/**
7229 * Toggles the route suppression status for this aggregate address
7230 * configuration.
7231 */
4056a5f6
RZ
7232void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7233 struct bgp *bgp, const struct prefix *p,
7234 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7235{
7236 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7237 const struct prefix *dest_p;
7238 struct bgp_dest *dest, *top;
7239 struct bgp_path_info *pi;
7240 bool toggle_suppression;
7241
7242 /* We've found a different MED we must revert any suppressed routes. */
7243 top = bgp_node_get(table, p);
7244 for (dest = bgp_node_get(table, p); dest;
7245 dest = bgp_route_next_until(dest, top)) {
7246 dest_p = bgp_dest_get_prefix(dest);
7247 if (dest_p->prefixlen <= p->prefixlen)
7248 continue;
7249
7250 toggle_suppression = false;
7251 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7252 if (BGP_PATH_HOLDDOWN(pi))
7253 continue;
7254 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7255 continue;
7256
6aabb15d
RZ
7257 /* We are toggling suppression back. */
7258 if (suppress) {
6aabb15d 7259 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7260 if (aggr_suppress_path(aggregate, pi))
7261 toggle_suppression = true;
6aabb15d
RZ
7262 continue;
7263 }
7264
6aabb15d 7265 /* Install route if there is no more suppression. */
4056a5f6 7266 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7267 toggle_suppression = true;
6aabb15d
RZ
7268 }
7269
7270 if (toggle_suppression)
7271 bgp_process(bgp, dest, afi, safi);
7272 }
7273 bgp_dest_unlock_node(top);
7274}
7275
7276/**
7277 * Aggregate address MED matching incremental test: this function is called
7278 * when the initial aggregation occurred and we are only testing a single
7279 * new path.
7280 *
7281 * In addition to testing and setting the MED validity it also installs back
7282 * suppressed routes (if summary is configured).
7283 *
7284 * Must not be called in `bgp_aggregate_route`.
7285 */
7286static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7287 struct bgp *bgp, const struct prefix *p,
7288 afi_t afi, safi_t safi,
7289 struct bgp_path_info *pi, bool is_adding)
7290{
7291 /* MED matching disabled. */
7292 if (!aggregate->match_med)
7293 return;
7294
7295 /* Aggregation with different MED, nothing to do. */
7296 if (aggregate->med_mismatched)
7297 return;
7298
7299 /*
7300 * Test the current entry:
7301 *
7302 * is_adding == true: if the new entry doesn't match then we must
7303 * install all suppressed routes.
7304 *
7305 * is_adding == false: if the entry being removed was the last
7306 * unmatching entry then we can suppress all routes.
7307 */
7308 if (!is_adding) {
7309 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7310 && aggregate->summary_only)
7311 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7312 safi, true);
7313 } else
7314 bgp_aggregate_med_match(aggregate, bgp, pi);
7315
7316 /* No mismatches, just quit. */
7317 if (!aggregate->med_mismatched)
7318 return;
7319
7320 /* Route summarization is disabled. */
7321 if (!aggregate->summary_only)
7322 return;
7323
7324 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7325}
7326
b5d58c32 7327/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7328void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7329 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7330{
7331 struct bgp_table *table;
9bcb3eef
DS
7332 struct bgp_dest *top;
7333 struct bgp_dest *dest;
d7c0a89a 7334 uint8_t origin;
d62a17ae 7335 struct aspath *aspath = NULL;
d62a17ae 7336 struct community *community = NULL;
3da2cc32 7337 struct ecommunity *ecommunity = NULL;
dd18c5a9 7338 struct lcommunity *lcommunity = NULL;
40381db7 7339 struct bgp_path_info *pi;
d62a17ae 7340 unsigned long match = 0;
d7c0a89a 7341 uint8_t atomic_aggregate = 0;
d62a17ae 7342
9f822fa2
S
7343 /* If the bgp instance is being deleted or self peer is deleted
7344 * then do not create aggregate route
7345 */
892fedb6
DA
7346 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7347 || (bgp->peer_self == NULL))
9f822fa2
S
7348 return;
7349
6aabb15d
RZ
7350 /* Initialize and test routes for MED difference. */
7351 if (aggregate->match_med)
7352 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7353
4056a5f6
RZ
7354 /*
7355 * Reset aggregate count: we might've been called from route map
7356 * update so in that case we must retest all more specific routes.
7357 *
7358 * \see `bgp_route_map_process_update`.
7359 */
7360 aggregate->count = 0;
7361 aggregate->incomplete_origin_count = 0;
7362 aggregate->incomplete_origin_count = 0;
7363 aggregate->egp_origin_count = 0;
7364
d62a17ae 7365 /* ORIGIN attribute: If at least one route among routes that are
7366 aggregated has ORIGIN with the value INCOMPLETE, then the
7367 aggregated route must have the ORIGIN attribute with the value
7368 INCOMPLETE. Otherwise, if at least one route among routes that
7369 are aggregated has ORIGIN with the value EGP, then the aggregated
7370 route must have the origin attribute with the value EGP. In all
7371 other case the value of the ORIGIN attribute of the aggregated
7372 route is INTERNAL. */
7373 origin = BGP_ORIGIN_IGP;
718e3744 7374
d62a17ae 7375 table = bgp->rib[afi][safi];
718e3744 7376
d62a17ae 7377 top = bgp_node_get(table, p);
9bcb3eef
DS
7378 for (dest = bgp_node_get(table, p); dest;
7379 dest = bgp_route_next_until(dest, top)) {
7380 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7381
9bcb3eef 7382 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7383 continue;
d62a17ae 7384
a77e2f4b
S
7385 /* If suppress fib is enabled and route not installed
7386 * in FIB, skip the route
7387 */
7388 if (!bgp_check_advertise(bgp, dest))
7389 continue;
7390
c2ff8b3e 7391 match = 0;
d62a17ae 7392
9bcb3eef 7393 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7394 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7395 continue;
718e3744 7396
40381db7 7397 if (pi->attr->flag
c2ff8b3e
DS
7398 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7399 atomic_aggregate = 1;
d62a17ae 7400
40381db7 7401 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7402 continue;
d62a17ae 7403
f273fef1
DS
7404 /*
7405 * summary-only aggregate route suppress
7406 * aggregated route announcements.
6aabb15d
RZ
7407 *
7408 * MED matching:
7409 * Don't create summaries if MED didn't match
7410 * otherwise neither the specific routes and the
7411 * aggregation will be announced.
f273fef1 7412 */
6aabb15d
RZ
7413 if (aggregate->summary_only
7414 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7415 if (aggr_suppress_path(aggregate, pi))
7416 match++;
d62a17ae 7417 }
c2ff8b3e 7418
365ab2e7
RZ
7419 /*
7420 * Suppress more specific routes that match the route
7421 * map results.
7422 *
7423 * MED matching:
7424 * Don't suppress routes if MED matching is enabled and
7425 * it mismatched otherwise we might end up with no
7426 * routes for this path.
7427 */
7428 if (aggregate->suppress_map_name
7429 && AGGREGATE_MED_VALID(aggregate)
7430 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7431 if (aggr_suppress_path(aggregate, pi))
7432 match++;
d62a17ae 7433 }
c2ff8b3e
DS
7434
7435 aggregate->count++;
7436
f273fef1
DS
7437 /*
7438 * If at least one route among routes that are
7439 * aggregated has ORIGIN with the value INCOMPLETE,
7440 * then the aggregated route MUST have the ORIGIN
7441 * attribute with the value INCOMPLETE. Otherwise, if
7442 * at least one route among routes that are aggregated
7443 * has ORIGIN with the value EGP, then the aggregated
7444 * route MUST have the ORIGIN attribute with the value
7445 * EGP.
7446 */
fc968841
NT
7447 switch (pi->attr->origin) {
7448 case BGP_ORIGIN_INCOMPLETE:
7449 aggregate->incomplete_origin_count++;
7450 break;
7451 case BGP_ORIGIN_EGP:
7452 aggregate->egp_origin_count++;
7453 break;
7454 default:
7455 /*Do nothing.
7456 */
7457 break;
7458 }
c2ff8b3e
DS
7459
7460 if (!aggregate->as_set)
7461 continue;
7462
f273fef1
DS
7463 /*
7464 * as-set aggregate route generate origin, as path,
7465 * and community aggregation.
7466 */
fc968841
NT
7467 /* Compute aggregate route's as-path.
7468 */
ef51a7d8 7469 bgp_compute_aggregate_aspath_hash(aggregate,
7470 pi->attr->aspath);
c2ff8b3e 7471
fc968841
NT
7472 /* Compute aggregate route's community.
7473 */
9a706b42 7474 if (bgp_attr_get_community(pi->attr))
21fec674 7475 bgp_compute_aggregate_community_hash(
9a706b42
DA
7476 aggregate,
7477 bgp_attr_get_community(pi->attr));
dd18c5a9 7478
fc968841
NT
7479 /* Compute aggregate route's extended community.
7480 */
b53e67a3 7481 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7482 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7483 aggregate,
7484 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7485
7486 /* Compute aggregate route's large community.
7487 */
1bcf3a96 7488 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7489 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7490 aggregate,
7491 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7492 }
c2ff8b3e 7493 if (match)
9bcb3eef 7494 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7495 }
21fec674 7496 if (aggregate->as_set) {
ef51a7d8 7497 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7498 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7499 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7500 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7501 }
7502
f1eb1f05 7503
9bcb3eef 7504 bgp_dest_unlock_node(top);
718e3744 7505
718e3744 7506
fc968841
NT
7507 if (aggregate->incomplete_origin_count > 0)
7508 origin = BGP_ORIGIN_INCOMPLETE;
7509 else if (aggregate->egp_origin_count > 0)
7510 origin = BGP_ORIGIN_EGP;
d62a17ae 7511
229757f1
DA
7512 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7513 origin = aggregate->origin;
7514
fc968841
NT
7515 if (aggregate->as_set) {
7516 if (aggregate->aspath)
7517 /* Retrieve aggregate route's as-path.
7518 */
7519 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7520
fc968841
NT
7521 if (aggregate->community)
7522 /* Retrieve aggregate route's community.
7523 */
7524 community = community_dup(aggregate->community);
3da2cc32 7525
fc968841
NT
7526 if (aggregate->ecommunity)
7527 /* Retrieve aggregate route's ecommunity.
7528 */
7529 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7530
fc968841
NT
7531 if (aggregate->lcommunity)
7532 /* Retrieve aggregate route's lcommunity.
7533 */
7534 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7535 }
718e3744 7536
c701010e 7537 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7538 ecommunity, lcommunity, atomic_aggregate,
7539 aggregate);
718e3744 7540}
7541
5f040085
DS
7542void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7543 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7544{
7545 struct bgp_table *table;
9bcb3eef
DS
7546 struct bgp_dest *top;
7547 struct bgp_dest *dest;
40381db7 7548 struct bgp_path_info *pi;
3b7db173
DS
7549 unsigned long match;
7550
7551 table = bgp->rib[afi][safi];
7552
7553 /* If routes exists below this node, generate aggregate routes. */
7554 top = bgp_node_get(table, p);
9bcb3eef
DS
7555 for (dest = bgp_node_get(table, p); dest;
7556 dest = bgp_route_next_until(dest, top)) {
7557 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7558
9bcb3eef 7559 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7560 continue;
7561 match = 0;
7562
9bcb3eef 7563 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7564 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7565 continue;
7566
40381db7 7567 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7568 continue;
7569
92b175bd
RZ
7570 /*
7571 * This route is suppressed: attempt to unsuppress it.
7572 *
7573 * `aggr_unsuppress_path` will fail if this particular
7574 * aggregate route was not the suppressor.
7575 */
7576 if (pi->extra && pi->extra->aggr_suppressors &&
7577 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7578 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7579 match++;
3b7db173 7580 }
365ab2e7 7581
3b7db173 7582 aggregate->count--;
fc968841
NT
7583
7584 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7585 aggregate->incomplete_origin_count--;
7586 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7587 aggregate->egp_origin_count--;
7588
7589 if (aggregate->as_set) {
7590 /* Remove as-path from aggregate.
7591 */
ef51a7d8 7592 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7593 aggregate,
7594 pi->attr->aspath);
7595
9a706b42 7596 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7597 /* Remove community from aggregate.
7598 */
21fec674 7599 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7600 aggregate,
7601 bgp_attr_get_community(
7602 pi->attr));
fc968841 7603
b53e67a3 7604 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7605 /* Remove ecommunity from aggregate.
7606 */
4edd83f9 7607 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7608 aggregate,
7609 bgp_attr_get_ecommunity(
7610 pi->attr));
fc968841 7611
1bcf3a96 7612 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7613 /* Remove lcommunity from aggregate.
7614 */
f1eb1f05 7615 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7616 aggregate,
7617 bgp_attr_get_lcommunity(
7618 pi->attr));
fc968841 7619 }
3b7db173
DS
7620 }
7621
7622 /* If this node was suppressed, process the change. */
7623 if (match)
9bcb3eef 7624 bgp_process(bgp, dest, afi, safi);
3b7db173 7625 }
f1eb1f05 7626 if (aggregate->as_set) {
ef51a7d8 7627 aspath_free(aggregate->aspath);
7628 aggregate->aspath = NULL;
21fec674 7629 if (aggregate->community)
7630 community_free(&aggregate->community);
4edd83f9 7631 if (aggregate->ecommunity)
7632 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7633 if (aggregate->lcommunity)
7634 lcommunity_free(&aggregate->lcommunity);
7635 }
7636
9bcb3eef 7637 bgp_dest_unlock_node(top);
3b7db173 7638}
718e3744 7639
5f040085
DS
7640static void bgp_add_route_to_aggregate(struct bgp *bgp,
7641 const struct prefix *aggr_p,
fc968841
NT
7642 struct bgp_path_info *pinew, afi_t afi,
7643 safi_t safi,
7644 struct bgp_aggregate *aggregate)
7645{
7646 uint8_t origin;
7647 struct aspath *aspath = NULL;
7648 uint8_t atomic_aggregate = 0;
7649 struct community *community = NULL;
7650 struct ecommunity *ecommunity = NULL;
7651 struct lcommunity *lcommunity = NULL;
7652
a4559740 7653 /* If the bgp instance is being deleted or self peer is deleted
7654 * then do not create aggregate route
7655 */
7656 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7657 || (bgp->peer_self == NULL))
7658 return;
7659
fc968841
NT
7660 /* ORIGIN attribute: If at least one route among routes that are
7661 * aggregated has ORIGIN with the value INCOMPLETE, then the
7662 * aggregated route must have the ORIGIN attribute with the value
7663 * INCOMPLETE. Otherwise, if at least one route among routes that
7664 * are aggregated has ORIGIN with the value EGP, then the aggregated
7665 * route must have the origin attribute with the value EGP. In all
7666 * other case the value of the ORIGIN attribute of the aggregated
7667 * route is INTERNAL.
7668 */
7669 origin = BGP_ORIGIN_IGP;
7670
7671 aggregate->count++;
7672
6aabb15d
RZ
7673 /*
7674 * This must be called before `summary` check to avoid
7675 * "suppressing" twice.
7676 */
7677 if (aggregate->match_med)
7678 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7679 pinew, true);
7680
7681 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7682 aggr_suppress_path(aggregate, pinew);
fc968841 7683
365ab2e7
RZ
7684 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7685 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7686 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7687
7688 switch (pinew->attr->origin) {
7689 case BGP_ORIGIN_INCOMPLETE:
7690 aggregate->incomplete_origin_count++;
7691 break;
7692 case BGP_ORIGIN_EGP:
7693 aggregate->egp_origin_count++;
7694 break;
7695 default:
7696 /* Do nothing.
7697 */
7698 break;
7699 }
7700
7701 if (aggregate->incomplete_origin_count > 0)
7702 origin = BGP_ORIGIN_INCOMPLETE;
7703 else if (aggregate->egp_origin_count > 0)
7704 origin = BGP_ORIGIN_EGP;
7705
229757f1
DA
7706 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7707 origin = aggregate->origin;
7708
fc968841
NT
7709 if (aggregate->as_set) {
7710 /* Compute aggregate route's as-path.
7711 */
7712 bgp_compute_aggregate_aspath(aggregate,
7713 pinew->attr->aspath);
7714
7715 /* Compute aggregate route's community.
7716 */
9a706b42 7717 if (bgp_attr_get_community(pinew->attr))
fc968841 7718 bgp_compute_aggregate_community(
9a706b42 7719 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7720
7721 /* Compute aggregate route's extended community.
7722 */
b53e67a3 7723 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7724 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7725 aggregate,
7726 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7727
7728 /* Compute aggregate route's large community.
7729 */
1bcf3a96 7730 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7731 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7732 aggregate,
7733 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7734
7735 /* Retrieve aggregate route's as-path.
7736 */
7737 if (aggregate->aspath)
7738 aspath = aspath_dup(aggregate->aspath);
7739
7740 /* Retrieve aggregate route's community.
7741 */
7742 if (aggregate->community)
7743 community = community_dup(aggregate->community);
7744
7745 /* Retrieve aggregate route's ecommunity.
7746 */
7747 if (aggregate->ecommunity)
7748 ecommunity = ecommunity_dup(aggregate->ecommunity);
7749
7750 /* Retrieve aggregate route's lcommunity.
7751 */
7752 if (aggregate->lcommunity)
7753 lcommunity = lcommunity_dup(aggregate->lcommunity);
7754 }
7755
7756 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7757 aspath, community, ecommunity,
7758 lcommunity, atomic_aggregate, aggregate);
7759}
7760
7761static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7762 safi_t safi,
7763 struct bgp_path_info *pi,
7764 struct bgp_aggregate *aggregate,
5f040085 7765 const struct prefix *aggr_p)
fc968841
NT
7766{
7767 uint8_t origin;
7768 struct aspath *aspath = NULL;
7769 uint8_t atomic_aggregate = 0;
7770 struct community *community = NULL;
7771 struct ecommunity *ecommunity = NULL;
7772 struct lcommunity *lcommunity = NULL;
7773 unsigned long match = 0;
7774
a4559740 7775 /* If the bgp instance is being deleted or self peer is deleted
7776 * then do not create aggregate route
7777 */
7778 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7779 || (bgp->peer_self == NULL))
7780 return;
7781
fc968841
NT
7782 if (BGP_PATH_HOLDDOWN(pi))
7783 return;
7784
7785 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7786 return;
7787
4056a5f6
RZ
7788 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7789 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7790 match++;
fc968841 7791
365ab2e7 7792 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7793 && aggr_suppress_map_test(bgp, aggregate, pi))
7794 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7795 match++;
fc968841 7796
6aabb15d 7797 /*
365ab2e7 7798 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7799 * "unsuppressing" twice.
7800 */
7801 if (aggregate->match_med)
7802 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7803 true);
7804
fc968841
NT
7805 if (aggregate->count > 0)
7806 aggregate->count--;
7807
7808 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7809 aggregate->incomplete_origin_count--;
7810 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7811 aggregate->egp_origin_count--;
7812
7813 if (aggregate->as_set) {
7814 /* Remove as-path from aggregate.
7815 */
7816 bgp_remove_aspath_from_aggregate(aggregate,
7817 pi->attr->aspath);
7818
9a706b42 7819 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7820 /* Remove community from aggregate.
7821 */
7822 bgp_remove_community_from_aggregate(
9a706b42 7823 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7824
b53e67a3 7825 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7826 /* Remove ecommunity from aggregate.
7827 */
7828 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7829 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7830
1bcf3a96 7831 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7832 /* Remove lcommunity from aggregate.
7833 */
7834 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7835 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7836 }
7837
7838 /* If this node was suppressed, process the change. */
7839 if (match)
7840 bgp_process(bgp, pi->net, afi, safi);
7841
7842 origin = BGP_ORIGIN_IGP;
7843 if (aggregate->incomplete_origin_count > 0)
7844 origin = BGP_ORIGIN_INCOMPLETE;
7845 else if (aggregate->egp_origin_count > 0)
7846 origin = BGP_ORIGIN_EGP;
7847
229757f1
DA
7848 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7849 origin = aggregate->origin;
7850
fc968841
NT
7851 if (aggregate->as_set) {
7852 /* Retrieve aggregate route's as-path.
7853 */
7854 if (aggregate->aspath)
7855 aspath = aspath_dup(aggregate->aspath);
7856
7857 /* Retrieve aggregate route's community.
7858 */
7859 if (aggregate->community)
7860 community = community_dup(aggregate->community);
7861
7862 /* Retrieve aggregate route's ecommunity.
7863 */
7864 if (aggregate->ecommunity)
7865 ecommunity = ecommunity_dup(aggregate->ecommunity);
7866
7867 /* Retrieve aggregate route's lcommunity.
7868 */
7869 if (aggregate->lcommunity)
7870 lcommunity = lcommunity_dup(aggregate->lcommunity);
7871 }
7872
7873 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7874 aspath, community, ecommunity,
7875 lcommunity, atomic_aggregate, aggregate);
7876}
7877
5a1ae2c2 7878void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7879 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7880{
9bcb3eef
DS
7881 struct bgp_dest *child;
7882 struct bgp_dest *dest;
d62a17ae 7883 struct bgp_aggregate *aggregate;
7884 struct bgp_table *table;
718e3744 7885
d62a17ae 7886 table = bgp->aggregate[afi][safi];
f018db83 7887
d62a17ae 7888 /* No aggregates configured. */
7889 if (bgp_table_top_nolock(table) == NULL)
7890 return;
f018db83 7891
d62a17ae 7892 if (p->prefixlen == 0)
7893 return;
718e3744 7894
40381db7 7895 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7896 return;
718e3744 7897
a77e2f4b
S
7898 /* If suppress fib is enabled and route not installed
7899 * in FIB, do not update the aggregate route
7900 */
7901 if (!bgp_check_advertise(bgp, pi->net))
7902 return;
7903
d62a17ae 7904 child = bgp_node_get(table, p);
718e3744 7905
d62a17ae 7906 /* Aggregate address configuration check. */
9bcb3eef
DS
7907 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7908 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7909
9bcb3eef
DS
7910 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7911 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7912 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7913 aggregate);
d62a17ae 7914 }
b1e62edd 7915 }
9bcb3eef 7916 bgp_dest_unlock_node(child);
718e3744 7917}
7918
5a1ae2c2 7919void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7920 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7921{
9bcb3eef
DS
7922 struct bgp_dest *child;
7923 struct bgp_dest *dest;
d62a17ae 7924 struct bgp_aggregate *aggregate;
7925 struct bgp_table *table;
718e3744 7926
d62a17ae 7927 table = bgp->aggregate[afi][safi];
718e3744 7928
d62a17ae 7929 /* No aggregates configured. */
7930 if (bgp_table_top_nolock(table) == NULL)
7931 return;
718e3744 7932
d62a17ae 7933 if (p->prefixlen == 0)
7934 return;
718e3744 7935
d62a17ae 7936 child = bgp_node_get(table, p);
718e3744 7937
d62a17ae 7938 /* Aggregate address configuration check. */
9bcb3eef
DS
7939 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7940 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7941
9bcb3eef
DS
7942 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7943 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7944 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7945 aggregate, dest_p);
d62a17ae 7946 }
b1e62edd 7947 }
9bcb3eef 7948 bgp_dest_unlock_node(child);
d62a17ae 7949}
718e3744 7950
718e3744 7951/* Aggregate route attribute. */
7952#define AGGREGATE_SUMMARY_ONLY 1
7953#define AGGREGATE_AS_SET 1
fb29348a 7954#define AGGREGATE_AS_UNSET 0
718e3744 7955
229757f1
DA
7956static const char *bgp_origin2str(uint8_t origin)
7957{
7958 switch (origin) {
7959 case BGP_ORIGIN_IGP:
7960 return "igp";
7961 case BGP_ORIGIN_EGP:
7962 return "egp";
7963 case BGP_ORIGIN_INCOMPLETE:
7964 return "incomplete";
7965 }
7966 return "n/a";
7967}
7968
fdeb5a81 7969static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7970{
7971 switch (v_state) {
fdeb5a81
DS
7972 case RPKI_NOT_BEING_USED:
7973 return "not used";
7974 case RPKI_VALID:
b5b99af8 7975 return "valid";
fdeb5a81 7976 case RPKI_NOTFOUND:
b5b99af8 7977 return "not found";
fdeb5a81 7978 case RPKI_INVALID:
b5b99af8 7979 return "invalid";
b5b99af8 7980 }
fdeb5a81
DS
7981
7982 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7983 return "ERROR";
7984}
7985
585f1adc
IR
7986static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7987 afi_t afi, safi_t safi)
718e3744 7988{
585f1adc
IR
7989 VTY_DECLVAR_CONTEXT(bgp, bgp);
7990 int ret;
7991 struct prefix p;
9bcb3eef 7992 struct bgp_dest *dest;
d62a17ae 7993 struct bgp_aggregate *aggregate;
718e3744 7994
585f1adc
IR
7995 /* Convert string to prefix structure. */
7996 ret = str2prefix(prefix_str, &p);
7997 if (!ret) {
7998 vty_out(vty, "Malformed prefix\n");
7999 return CMD_WARNING_CONFIG_FAILED;
8000 }
8001 apply_mask(&p);
a4559740 8002
d62a17ae 8003 /* Old configuration check. */
585f1adc 8004 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8005 if (!dest) {
585f1adc
IR
8006 vty_out(vty,
8007 "%% There is no aggregate-address configuration.\n");
8008 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8009 }
f6269b4f 8010
9bcb3eef 8011 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8012 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8013 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8014 NULL, NULL, 0, aggregate);
d62a17ae 8015
8016 /* Unlock aggregate address configuration. */
9bcb3eef 8017 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8018
8019 if (aggregate->community)
8020 community_free(&aggregate->community);
8021
8022 if (aggregate->community_hash) {
8023 /* Delete all communities in the hash.
8024 */
8025 hash_clean(aggregate->community_hash,
8026 bgp_aggr_community_remove);
8027 /* Free up the community_hash.
8028 */
8029 hash_free(aggregate->community_hash);
8030 }
8031
8032 if (aggregate->ecommunity)
8033 ecommunity_free(&aggregate->ecommunity);
8034
8035 if (aggregate->ecommunity_hash) {
8036 /* Delete all ecommunities in the hash.
8037 */
8038 hash_clean(aggregate->ecommunity_hash,
8039 bgp_aggr_ecommunity_remove);
8040 /* Free up the ecommunity_hash.
8041 */
8042 hash_free(aggregate->ecommunity_hash);
8043 }
8044
8045 if (aggregate->lcommunity)
8046 lcommunity_free(&aggregate->lcommunity);
8047
8048 if (aggregate->lcommunity_hash) {
8049 /* Delete all lcommunities in the hash.
8050 */
8051 hash_clean(aggregate->lcommunity_hash,
8052 bgp_aggr_lcommunity_remove);
8053 /* Free up the lcommunity_hash.
8054 */
8055 hash_free(aggregate->lcommunity_hash);
8056 }
8057
8058 if (aggregate->aspath)
8059 aspath_free(aggregate->aspath);
8060
8061 if (aggregate->aspath_hash) {
8062 /* Delete all as-paths in the hash.
8063 */
8064 hash_clean(aggregate->aspath_hash,
8065 bgp_aggr_aspath_remove);
8066 /* Free up the aspath_hash.
8067 */
8068 hash_free(aggregate->aspath_hash);
8069 }
8070
d62a17ae 8071 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8072 bgp_dest_unlock_node(dest);
8073 bgp_dest_unlock_node(dest);
d62a17ae 8074
585f1adc 8075 return CMD_SUCCESS;
d62a17ae 8076}
8077
585f1adc
IR
8078static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8079 safi_t safi, const char *rmap,
8080 uint8_t summary_only, uint8_t as_set,
8081 uint8_t origin, bool match_med,
8082 const char *suppress_map)
d62a17ae 8083{
585f1adc 8084 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8085 int ret;
585f1adc 8086 struct prefix p;
9bcb3eef 8087 struct bgp_dest *dest;
d62a17ae 8088 struct bgp_aggregate *aggregate;
fb29348a 8089 uint8_t as_set_new = as_set;
d62a17ae 8090
365ab2e7 8091 if (suppress_map && summary_only) {
585f1adc 8092 vty_out(vty,
365ab2e7 8093 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8094 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8095 }
8096
585f1adc
IR
8097 /* Convert string to prefix structure. */
8098 ret = str2prefix(prefix_str, &p);
8099 if (!ret) {
8100 vty_out(vty, "Malformed prefix\n");
8101 return CMD_WARNING_CONFIG_FAILED;
8102 }
8103 apply_mask(&p);
d62a17ae 8104
585f1adc
IR
8105 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8106 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8107 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8108 prefix_str);
8109 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8110 }
8111
d62a17ae 8112 /* Old configuration check. */
585f1adc 8113 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8114 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8115
20894f50 8116 if (aggregate) {
585f1adc 8117 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8118 /* try to remove the old entry */
585f1adc 8119 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8120 if (ret) {
585f1adc 8121 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8122 bgp_dest_unlock_node(dest);
585f1adc 8123 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8124 }
8125 }
718e3744 8126
d62a17ae 8127 /* Make aggregate address structure. */
8128 aggregate = bgp_aggregate_new();
8129 aggregate->summary_only = summary_only;
6aabb15d 8130 aggregate->match_med = match_med;
fb29348a
DA
8131
8132 /* Network operators MUST NOT locally generate any new
8133 * announcements containing AS_SET or AS_CONFED_SET. If they have
8134 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8135 * SHOULD withdraw those routes and re-announce routes for the
8136 * aggregate or component prefixes (i.e., the more-specific routes
8137 * subsumed by the previously aggregated route) without AS_SET
8138 * or AS_CONFED_SET in the updates.
8139 */
7f972cd8 8140 if (bgp->reject_as_sets) {
fb29348a
DA
8141 if (as_set == AGGREGATE_AS_SET) {
8142 as_set_new = AGGREGATE_AS_UNSET;
8143 zlog_warn(
63efca0e 8144 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8145 __func__);
585f1adc 8146 vty_out(vty,
fb29348a
DA
8147 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8148 }
8149 }
8150
8151 aggregate->as_set = as_set_new;
d62a17ae 8152 aggregate->safi = safi;
229757f1
DA
8153 /* Override ORIGIN attribute if defined.
8154 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8155 * to IGP which is not what rfc4271 says.
8156 * This enables the same behavior, optionally.
8157 */
8158 aggregate->origin = origin;
20894f50
DA
8159
8160 if (rmap) {
8161 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8162 route_map_counter_decrement(aggregate->rmap.map);
8163 aggregate->rmap.name =
8164 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8165 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8166 route_map_counter_increment(aggregate->rmap.map);
8167 }
365ab2e7
RZ
8168
8169 if (suppress_map) {
8170 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8171 route_map_counter_decrement(aggregate->suppress_map);
8172
8173 aggregate->suppress_map_name =
8174 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8175 aggregate->suppress_map =
8176 route_map_lookup_by_name(aggregate->suppress_map_name);
8177 route_map_counter_increment(aggregate->suppress_map);
8178 }
8179
9bcb3eef 8180 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8181
d62a17ae 8182 /* Aggregate address insert into BGP routing table. */
585f1adc 8183 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8184
585f1adc 8185 return CMD_SUCCESS;
718e3744 8186}
8187
585f1adc
IR
8188DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8189 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8190 "as-set$as_set_s"
8191 "|summary-only$summary_only"
8192 "|route-map WORD$rmap_name"
8193 "|origin <egp|igp|incomplete>$origin_s"
8194 "|matching-MED-only$match_med"
8195 "|suppress-map WORD$suppress_map"
8196 "}]",
8197 NO_STR
8198 "Configure BGP aggregate entries\n"
8199 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
8200 "Generate AS set path information\n"
8201 "Filter more specific routes from updates\n"
8202 "Apply route map to aggregate network\n"
8203 "Route map name\n"
8204 "BGP origin code\n"
8205 "Remote EGP\n"
8206 "Local IGP\n"
8207 "Unknown heritage\n"
8208 "Only aggregate routes with matching MED\n"
8209 "Suppress the selected more specific routes\n"
8210 "Route map with the route selectors\n")
8211{
8212 const char *prefix_s = NULL;
554b3b10 8213 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8214 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8215 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8216 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8217
554b3b10 8218 if (addr_str) {
7533cad7
QY
8219 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8220 sizeof(prefix_buf))
554b3b10
RZ
8221 == 0) {
8222 vty_out(vty, "%% Inconsistent address and mask\n");
8223 return CMD_WARNING_CONFIG_FAILED;
8224 }
585f1adc
IR
8225 prefix_s = prefix_buf;
8226 } else
8227 prefix_s = prefix_str;
37a87b8f 8228
585f1adc
IR
8229 if (origin_s) {
8230 if (strcmp(origin_s, "egp") == 0)
8231 origin = BGP_ORIGIN_EGP;
8232 else if (strcmp(origin_s, "igp") == 0)
8233 origin = BGP_ORIGIN_IGP;
8234 else if (strcmp(origin_s, "incomplete") == 0)
8235 origin = BGP_ORIGIN_INCOMPLETE;
8236 }
90e21f35 8237
585f1adc
IR
8238 if (as_set_s)
8239 as_set = AGGREGATE_AS_SET;
554b3b10 8240
585f1adc 8241 /* Handle configuration removal, otherwise installation. */
554b3b10 8242 if (no)
585f1adc
IR
8243 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8244
8245 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8246 summary_only != NULL, as_set, origin,
8247 match_med != NULL, suppress_map);
8248}
8249
8250DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8251 "[no] aggregate-address X:X::X:X/M$prefix [{"
8252 "as-set$as_set_s"
8253 "|summary-only$summary_only"
8254 "|route-map WORD$rmap_name"
8255 "|origin <egp|igp|incomplete>$origin_s"
8256 "|matching-MED-only$match_med"
8257 "|suppress-map WORD$suppress_map"
8258 "}]",
8259 NO_STR
8260 "Configure BGP aggregate entries\n"
8261 "Aggregate prefix\n"
8262 "Generate AS set path information\n"
8263 "Filter more specific routes from updates\n"
8264 "Apply route map to aggregate network\n"
8265 "Route map name\n"
8266 "BGP origin code\n"
8267 "Remote EGP\n"
8268 "Local IGP\n"
8269 "Unknown heritage\n"
8270 "Only aggregate routes with matching MED\n"
8271 "Suppress the selected more specific routes\n"
8272 "Route map with the route selectors\n")
8273{
8274 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8275 int as_set = AGGREGATE_AS_UNSET;
8276
8277 if (origin_s) {
8278 if (strcmp(origin_s, "egp") == 0)
8279 origin = BGP_ORIGIN_EGP;
8280 else if (strcmp(origin_s, "igp") == 0)
8281 origin = BGP_ORIGIN_IGP;
8282 else if (strcmp(origin_s, "incomplete") == 0)
8283 origin = BGP_ORIGIN_INCOMPLETE;
8284 }
8285
8286 if (as_set_s)
8287 as_set = AGGREGATE_AS_SET;
8288
8289 /* Handle configuration removal, otherwise installation. */
554b3b10 8290 if (no)
585f1adc
IR
8291 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8292 SAFI_UNICAST);
554b3b10 8293
585f1adc
IR
8294 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8295 rmap_name, summary_only != NULL, as_set,
8296 origin, match_med != NULL, suppress_map);
718e3744 8297}
8298
718e3744 8299/* Redistribute route treatment. */
d62a17ae 8300void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8301 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8302 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8303 enum blackhole_type bhtype, uint32_t metric,
8304 uint8_t type, unsigned short instance,
8305 route_tag_t tag)
d62a17ae 8306{
4b7e6066 8307 struct bgp_path_info *new;
40381db7
DS
8308 struct bgp_path_info *bpi;
8309 struct bgp_path_info rmap_path;
9bcb3eef 8310 struct bgp_dest *bn;
d62a17ae 8311 struct attr attr;
8312 struct attr *new_attr;
8313 afi_t afi;
b68885f9 8314 route_map_result_t ret;
d62a17ae 8315 struct bgp_redist *red;
8316
8317 /* Make default attribute. */
8318 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8319 /*
8320 * This must not be NULL to satisfy Coverity SA
8321 */
8322 assert(attr.aspath);
9de1f7ff 8323
a4d82a8a 8324 switch (nhtype) {
9de1f7ff
DS
8325 case NEXTHOP_TYPE_IFINDEX:
8326 break;
8327 case NEXTHOP_TYPE_IPV4:
8328 case NEXTHOP_TYPE_IPV4_IFINDEX:
8329 attr.nexthop = nexthop->ipv4;
8330 break;
8331 case NEXTHOP_TYPE_IPV6:
8332 case NEXTHOP_TYPE_IPV6_IFINDEX:
8333 attr.mp_nexthop_global = nexthop->ipv6;
8334 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8335 break;
8336 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8337 switch (p->family) {
8338 case AF_INET:
9de1f7ff 8339 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8340 break;
8341 case AF_INET6:
9de1f7ff
DS
8342 memset(&attr.mp_nexthop_global, 0,
8343 sizeof(attr.mp_nexthop_global));
74489921 8344 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8345 break;
74489921 8346 }
0789eb69 8347 attr.bh_type = bhtype;
9de1f7ff 8348 break;
d62a17ae 8349 }
0789eb69 8350 attr.nh_type = nhtype;
74489921 8351 attr.nh_ifindex = ifindex;
f04a80a5 8352
d62a17ae 8353 attr.med = metric;
957f74c3 8354 attr.distance = distance;
d62a17ae 8355 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8356 attr.tag = tag;
718e3744 8357
d62a17ae 8358 afi = family2afi(p->family);
6aeb9e78 8359
d62a17ae 8360 red = bgp_redist_lookup(bgp, afi, type, instance);
8361 if (red) {
8362 struct attr attr_new;
718e3744 8363
d62a17ae 8364 /* Copy attribute for modification. */
6f4f49b2 8365 attr_new = attr;
718e3744 8366
d62a17ae 8367 if (red->redist_metric_flag)
8368 attr_new.med = red->redist_metric;
718e3744 8369
d62a17ae 8370 /* Apply route-map. */
8371 if (red->rmap.name) {
40381db7
DS
8372 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8373 rmap_path.peer = bgp->peer_self;
8374 rmap_path.attr = &attr_new;
718e3744 8375
d62a17ae 8376 SET_FLAG(bgp->peer_self->rmap_type,
8377 PEER_RMAP_TYPE_REDISTRIBUTE);
8378
1782514f 8379 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8380
8381 bgp->peer_self->rmap_type = 0;
8382
8383 if (ret == RMAP_DENYMATCH) {
8384 /* Free uninterned attribute. */
8385 bgp_attr_flush(&attr_new);
8386
8387 /* Unintern original. */
8388 aspath_unintern(&attr.aspath);
8389 bgp_redistribute_delete(bgp, p, type, instance);
8390 return;
8391 }
8392 }
8393
637e5ba4 8394 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8395 bgp_attr_add_gshut_community(&attr_new);
8396
d62a17ae 8397 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8398 SAFI_UNICAST, p, NULL);
8399
8400 new_attr = bgp_attr_intern(&attr_new);
8401
9bcb3eef 8402 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8403 if (bpi->peer == bgp->peer_self
8404 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8405 break;
8406
40381db7 8407 if (bpi) {
d62a17ae 8408 /* Ensure the (source route) type is updated. */
40381db7
DS
8409 bpi->type = type;
8410 if (attrhash_cmp(bpi->attr, new_attr)
8411 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8412 bgp_attr_unintern(&new_attr);
8413 aspath_unintern(&attr.aspath);
9bcb3eef 8414 bgp_dest_unlock_node(bn);
d62a17ae 8415 return;
8416 } else {
8417 /* The attribute is changed. */
40381db7 8418 bgp_path_info_set_flag(bn, bpi,
18ee8310 8419 BGP_PATH_ATTR_CHANGED);
d62a17ae 8420
8421 /* Rewrite BGP route information. */
40381db7
DS
8422 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8423 bgp_path_info_restore(bn, bpi);
d62a17ae 8424 else
40381db7
DS
8425 bgp_aggregate_decrement(
8426 bgp, p, bpi, afi, SAFI_UNICAST);
8427 bgp_attr_unintern(&bpi->attr);
8428 bpi->attr = new_attr;
8429 bpi->uptime = bgp_clock();
d62a17ae 8430
8431 /* Process change. */
40381db7 8432 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8433 SAFI_UNICAST);
8434 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8435 bgp_dest_unlock_node(bn);
d62a17ae 8436 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8437
8438 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8439 || (bgp->inst_type
8440 == BGP_INSTANCE_TYPE_DEFAULT)) {
8441
8442 vpn_leak_from_vrf_update(
40381db7 8443 bgp_get_default(), bgp, bpi);
ddb5b488 8444 }
d62a17ae 8445 return;
8446 }
8447 }
8448
8449 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8450 bgp->peer_self, new_attr, bn);
1defdda8 8451 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8452
8453 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8454 bgp_path_info_add(bn, new);
9bcb3eef 8455 bgp_dest_unlock_node(bn);
be785e35 8456 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8457 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8458
8459 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8460 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8461
8462 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8463 }
d62a17ae 8464 }
8465
8466 /* Unintern original. */
8467 aspath_unintern(&attr.aspath);
718e3744 8468}
8469
d7c0a89a
QY
8470void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8471 unsigned short instance)
718e3744 8472{
d62a17ae 8473 afi_t afi;
9bcb3eef 8474 struct bgp_dest *dest;
40381db7 8475 struct bgp_path_info *pi;
d62a17ae 8476 struct bgp_redist *red;
718e3744 8477
d62a17ae 8478 afi = family2afi(p->family);
718e3744 8479
d62a17ae 8480 red = bgp_redist_lookup(bgp, afi, type, instance);
8481 if (red) {
9bcb3eef
DS
8482 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8483 SAFI_UNICAST, p, NULL);
d62a17ae 8484
9bcb3eef 8485 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8486 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8487 break;
8488
40381db7 8489 if (pi) {
ddb5b488
PZ
8490 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8491 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8492
8493 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8494 bgp, pi);
ddb5b488 8495 }
40381db7 8496 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8497 bgp_path_info_delete(dest, pi);
8498 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8499 }
9bcb3eef 8500 bgp_dest_unlock_node(dest);
d62a17ae 8501 }
8502}
8503
8504/* Withdraw specified route type's route. */
8505void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8506 unsigned short instance)
d62a17ae 8507{
9bcb3eef 8508 struct bgp_dest *dest;
40381db7 8509 struct bgp_path_info *pi;
d62a17ae 8510 struct bgp_table *table;
8511
8512 table = bgp->rib[afi][SAFI_UNICAST];
8513
9bcb3eef
DS
8514 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8515 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8516 if (pi->peer == bgp->peer_self && pi->type == type
8517 && pi->instance == instance)
d62a17ae 8518 break;
8519
40381db7 8520 if (pi) {
ddb5b488
PZ
8521 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8522 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8523
8524 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8525 bgp, pi);
ddb5b488 8526 }
9bcb3eef 8527 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8528 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8529 bgp_path_info_delete(dest, pi);
8530 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8531 }
718e3744 8532 }
718e3744 8533}
6b0655a2 8534
718e3744 8535/* Static function to display route. */
7d3cae70
DA
8536static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8537 struct vty *vty, json_object *json, bool wide)
718e3744 8538{
be054588 8539 int len = 0;
d62a17ae 8540 char buf[BUFSIZ];
718e3744 8541
d62a17ae 8542 if (p->family == AF_INET) {
c6462ff4 8543 if (!json) {
8228a9a7 8544 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8545 } else {
8546 json_object_string_add(json, "prefix",
8547 inet_ntop(p->family,
8548 &p->u.prefix, buf,
8549 BUFSIZ));
8550 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8551 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8552 json_object_int_add(json, "version", dest->version);
c6462ff4 8553 }
d62a17ae 8554 } else if (p->family == AF_ETHERNET) {
8228a9a7 8555 len = vty_out(vty, "%pFX", p);
b03b8898 8556 } else if (p->family == AF_EVPN) {
57f7feb6 8557 if (!json)
2dbe669b 8558 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8559 else
60466a63 8560 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8561 } else if (p->family == AF_FLOWSPEC) {
8562 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8563 json ?
8564 NLRI_STRING_FORMAT_JSON_SIMPLE :
8565 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8566 } else {
c6462ff4 8567 if (!json)
8228a9a7 8568 len = vty_out(vty, "%pFX", p);
50e05855
AD
8569 else {
8570 json_object_string_add(json, "prefix",
8571 inet_ntop(p->family,
8572 &p->u.prefix, buf,
8573 BUFSIZ));
8574 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8575 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8576 json_object_int_add(json, "version", dest->version);
37d4e0df 8577 }
9c92b5f7 8578 }
d62a17ae 8579
9c92b5f7 8580 if (!json) {
ae248832 8581 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8582 if (len < 1)
8583 vty_out(vty, "\n%*s", 20, " ");
8584 else
8585 vty_out(vty, "%*s", len, " ");
8586 }
718e3744 8587}
8588
d62a17ae 8589enum bgp_display_type {
8590 normal_list,
718e3744 8591};
8592
1d7260a1 8593const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8594{
8595 switch (reason) {
8596 case bgp_path_selection_none:
8597 return "Nothing to Select";
8598 case bgp_path_selection_first:
8599 return "First path received";
8600 case bgp_path_selection_evpn_sticky_mac:
8601 return "EVPN Sticky Mac";
8602 case bgp_path_selection_evpn_seq:
8603 return "EVPN sequence number";
8604 case bgp_path_selection_evpn_lower_ip:
8605 return "EVPN lower IP";
8606 case bgp_path_selection_evpn_local_path:
8607 return "EVPN local ES path";
8608 case bgp_path_selection_evpn_non_proxy:
8609 return "EVPN non proxy";
8610 case bgp_path_selection_weight:
8611 return "Weight";
8612 case bgp_path_selection_local_pref:
8613 return "Local Pref";
8614 case bgp_path_selection_local_route:
8615 return "Local Route";
8616 case bgp_path_selection_confed_as_path:
8617 return "Confederation based AS Path";
8618 case bgp_path_selection_as_path:
8619 return "AS Path";
8620 case bgp_path_selection_origin:
8621 return "Origin";
8622 case bgp_path_selection_med:
8623 return "MED";
8624 case bgp_path_selection_peer:
8625 return "Peer Type";
8626 case bgp_path_selection_confed:
8627 return "Confed Peer Type";
8628 case bgp_path_selection_igp_metric:
8629 return "IGP Metric";
8630 case bgp_path_selection_older:
8631 return "Older Path";
8632 case bgp_path_selection_router_id:
8633 return "Router ID";
8634 case bgp_path_selection_cluster_length:
bcab253c 8635 return "Cluster length";
bbb46eb5
DA
8636 case bgp_path_selection_stale:
8637 return "Path Staleness";
8638 case bgp_path_selection_local_configured:
8639 return "Locally configured route";
8640 case bgp_path_selection_neighbor_ip:
8641 return "Neighbor IP";
8642 case bgp_path_selection_default:
8643 return "Nothing left to compare";
8644 }
8645 return "Invalid (internal error)";
8646}
8647
18ee8310 8648/* Print the short form route status for a bgp_path_info */
4b7e6066 8649static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8650 struct bgp_path_info *path,
82c298be 8651 const struct prefix *p,
d62a17ae 8652 json_object *json_path)
718e3744 8653{
82c298be
DA
8654 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8655
d62a17ae 8656 if (json_path) {
b05a1c8b 8657
d62a17ae 8658 /* Route status display. */
9b6d8fcf 8659 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8660 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8661
9b6d8fcf 8662 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8663 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8664
4056a5f6 8665 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8666 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8667
9b6d8fcf
DS
8668 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8669 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8670 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8671
d62a17ae 8672 /* Selected */
9b6d8fcf 8673 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8674 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8675
9b6d8fcf 8676 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8677 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8678
bbb46eb5 8679 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8680 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8681 json_object_string_add(json_path, "selectionReason",
8682 bgp_path_selection_reason2str(
8683 path->net->reason));
8684 }
b05a1c8b 8685
9b6d8fcf 8686 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8687 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8688
d62a17ae 8689 /* Internal route. */
9b6d8fcf
DS
8690 if ((path->peer->as)
8691 && (path->peer->as == path->peer->local_as))
d62a17ae 8692 json_object_string_add(json_path, "pathFrom",
8693 "internal");
8694 else
8695 json_object_string_add(json_path, "pathFrom",
8696 "external");
b05a1c8b 8697
d62a17ae 8698 return;
8699 }
b05a1c8b 8700
82c298be
DA
8701 /* RPKI validation state */
8702 rpki_state =
8703 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8704
8705 if (rpki_state == RPKI_VALID)
8706 vty_out(vty, "V");
8707 else if (rpki_state == RPKI_INVALID)
8708 vty_out(vty, "I");
8709 else if (rpki_state == RPKI_NOTFOUND)
8710 vty_out(vty, "N");
8711
d62a17ae 8712 /* Route status display. */
9b6d8fcf 8713 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8714 vty_out(vty, "R");
9b6d8fcf 8715 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8716 vty_out(vty, "S");
4056a5f6 8717 else if (bgp_path_suppressed(path))
d62a17ae 8718 vty_out(vty, "s");
9b6d8fcf
DS
8719 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8720 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8721 vty_out(vty, "*");
8722 else
8723 vty_out(vty, " ");
8724
8725 /* Selected */
9b6d8fcf 8726 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8727 vty_out(vty, "h");
9b6d8fcf 8728 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8729 vty_out(vty, "d");
9b6d8fcf 8730 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8731 vty_out(vty, ">");
9b6d8fcf 8732 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8733 vty_out(vty, "=");
8734 else
8735 vty_out(vty, " ");
718e3744 8736
d62a17ae 8737 /* Internal route. */
9b6d8fcf
DS
8738 if (path->peer && (path->peer->as)
8739 && (path->peer->as == path->peer->local_as))
d62a17ae 8740 vty_out(vty, "i");
8741 else
8742 vty_out(vty, " ");
b40d939b 8743}
8744
2ba93fd6
DA
8745static char *bgp_nexthop_hostname(struct peer *peer,
8746 struct bgp_nexthop_cache *bnc)
25b5da8d 8747{
892fedb6 8748 if (peer->hostname
aef999a2 8749 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8750 return peer->hostname;
8751 return NULL;
8752}
8753
b40d939b 8754/* called from terminal list command */
bd494ec5 8755void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8756 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8757 json_object *json_paths, bool wide)
d62a17ae 8758{
aef999a2 8759 int len;
515c2602 8760 struct attr *attr = path->attr;
d62a17ae 8761 json_object *json_path = NULL;
8762 json_object *json_nexthops = NULL;
8763 json_object *json_nexthop_global = NULL;
8764 json_object *json_nexthop_ll = NULL;
6f214dd3 8765 json_object *json_ext_community = NULL;
9df8b37c 8766 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8767 bool nexthop_self =
9b6d8fcf 8768 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8769 bool nexthop_othervrf = false;
43089216 8770 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8771 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8772 char *nexthop_hostname =
8773 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8774 char esi_buf[ESI_STR_LEN];
d62a17ae 8775
8776 if (json_paths)
8777 json_path = json_object_new_object();
8778
8779 /* short status lead text */
82c298be 8780 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8781
8782 if (!json_paths) {
8783 /* print prefix and mask */
8784 if (!display)
7d3cae70 8785 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8786 else
ae248832 8787 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8788 } else {
7d3cae70 8789 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8790 }
47fc97cc 8791
9df8b37c
PZ
8792 /*
8793 * If vrf id of nexthop is different from that of prefix,
8794 * set up printable string to append
8795 */
9b6d8fcf 8796 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8797 const char *self = "";
8798
8799 if (nexthop_self)
8800 self = "<";
8801
8802 nexthop_othervrf = true;
9b6d8fcf 8803 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8804
9b6d8fcf 8805 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8806 snprintf(vrf_id_str, sizeof(vrf_id_str),
8807 "@%s%s", VRFID_NONE_STR, self);
8808 else
8809 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8810 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8811
9b6d8fcf
DS
8812 if (path->extra->bgp_orig->inst_type
8813 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8814
9b6d8fcf 8815 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8816 } else {
8817 const char *self = "";
8818
8819 if (nexthop_self)
8820 self = "<";
8821
8822 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8823 }
8824
445c2480
DS
8825 /*
8826 * For ENCAP and EVPN routes, nexthop address family is not
8827 * neccessarily the same as the prefix address family.
8828 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8829 * EVPN routes are also exchanged with a MP nexthop. Currently,
8830 * this
8831 * is only IPv4, the value will be present in either
8832 * attr->nexthop or
8833 * attr->mp_nexthop_global_in
8834 */
8835 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8836 char buf[BUFSIZ];
8837 char nexthop[128];
8838 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8839
8840 switch (af) {
8841 case AF_INET:
772270f3
QY
8842 snprintf(nexthop, sizeof(nexthop), "%s",
8843 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8844 BUFSIZ));
445c2480
DS
8845 break;
8846 case AF_INET6:
772270f3
QY
8847 snprintf(nexthop, sizeof(nexthop), "%s",
8848 inet_ntop(af, &attr->mp_nexthop_global, buf,
8849 BUFSIZ));
445c2480
DS
8850 break;
8851 default:
772270f3 8852 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8853 break;
d62a17ae 8854 }
d62a17ae 8855
445c2480
DS
8856 if (json_paths) {
8857 json_nexthop_global = json_object_new_object();
8858
515c2602
DA
8859 json_object_string_add(json_nexthop_global, "ip",
8860 nexthop);
8861
939a97f4 8862 if (path->peer->hostname)
515c2602
DA
8863 json_object_string_add(json_nexthop_global,
8864 "hostname",
939a97f4 8865 path->peer->hostname);
515c2602
DA
8866
8867 json_object_string_add(json_nexthop_global, "afi",
8868 (af == AF_INET) ? "ipv4"
8869 : "ipv6");
445c2480
DS
8870 json_object_boolean_true_add(json_nexthop_global,
8871 "used");
aef999a2
DA
8872 } else {
8873 if (nexthop_hostname)
8874 len = vty_out(vty, "%s(%s)%s", nexthop,
8875 nexthop_hostname, vrf_id_str);
8876 else
8877 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8878
ae248832 8879 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8880 if (len < 1)
8881 vty_out(vty, "\n%*s", 36, " ");
8882 else
8883 vty_out(vty, "%*s", len, " ");
8884 }
445c2480
DS
8885 } else if (safi == SAFI_EVPN) {
8886 if (json_paths) {
8887 json_nexthop_global = json_object_new_object();
8888
c949c771
DA
8889 json_object_string_addf(json_nexthop_global, "ip",
8890 "%pI4", &attr->nexthop);
515c2602 8891
939a97f4 8892 if (path->peer->hostname)
515c2602
DA
8893 json_object_string_add(json_nexthop_global,
8894 "hostname",
939a97f4 8895 path->peer->hostname);
515c2602 8896
a4d82a8a
PZ
8897 json_object_string_add(json_nexthop_global, "afi",
8898 "ipv4");
445c2480
DS
8899 json_object_boolean_true_add(json_nexthop_global,
8900 "used");
aef999a2
DA
8901 } else {
8902 if (nexthop_hostname)
8903 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8904 nexthop_hostname, vrf_id_str);
8905 else
8906 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8907 vrf_id_str);
8908
ae248832 8909 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8910 if (len < 1)
8911 vty_out(vty, "\n%*s", 36, " ");
8912 else
8913 vty_out(vty, "%*s", len, " ");
8914 }
d33fc23b 8915 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8916 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8917 if (json_paths) {
8918 json_nexthop_global = json_object_new_object();
515c2602 8919
026b914a
PG
8920 json_object_string_add(json_nexthop_global,
8921 "afi", "ipv4");
c949c771
DA
8922 json_object_string_addf(json_nexthop_global,
8923 "ip", "%pI4",
8924 &attr->nexthop);
515c2602 8925
939a97f4 8926 if (path->peer->hostname)
515c2602
DA
8927 json_object_string_add(
8928 json_nexthop_global, "hostname",
939a97f4 8929 path->peer->hostname);
515c2602 8930
50e05855
AD
8931 json_object_boolean_true_add(
8932 json_nexthop_global,
026b914a
PG
8933 "used");
8934 } else {
aef999a2
DA
8935 if (nexthop_hostname)
8936 len = vty_out(vty, "%pI4(%s)%s",
8937 &attr->nexthop,
8938 nexthop_hostname,
8939 vrf_id_str);
8940 else
8941 len = vty_out(vty, "%pI4%s",
8942 &attr->nexthop,
8943 vrf_id_str);
8944
ae248832 8945 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8946 if (len < 1)
8947 vty_out(vty, "\n%*s", 36, " ");
8948 else
8949 vty_out(vty, "%*s", len, " ");
026b914a
PG
8950 }
8951 }
d33fc23b 8952 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8953 if (json_paths) {
8954 json_nexthop_global = json_object_new_object();
d62a17ae 8955
c949c771
DA
8956 json_object_string_addf(json_nexthop_global, "ip",
8957 "%pI4", &attr->nexthop);
515c2602 8958
939a97f4 8959 if (path->peer->hostname)
515c2602
DA
8960 json_object_string_add(json_nexthop_global,
8961 "hostname",
939a97f4 8962 path->peer->hostname);
445c2480 8963
a4d82a8a
PZ
8964 json_object_string_add(json_nexthop_global, "afi",
8965 "ipv4");
445c2480
DS
8966 json_object_boolean_true_add(json_nexthop_global,
8967 "used");
8968 } else {
aef999a2
DA
8969 if (nexthop_hostname)
8970 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8971 nexthop_hostname, vrf_id_str);
8972 else
8973 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8974 vrf_id_str);
9df8b37c 8975
ae248832 8976 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8977 if (len < 1)
8978 vty_out(vty, "\n%*s", 36, " ");
8979 else
8980 vty_out(vty, "%*s", len, " ");
d62a17ae 8981 }
445c2480 8982 }
b05a1c8b 8983
445c2480 8984 /* IPv6 Next Hop */
a4d82a8a 8985 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8986 if (json_paths) {
8987 json_nexthop_global = json_object_new_object();
c949c771
DA
8988 json_object_string_addf(json_nexthop_global, "ip",
8989 "%pI6",
8990 &attr->mp_nexthop_global);
515c2602 8991
939a97f4 8992 if (path->peer->hostname)
515c2602
DA
8993 json_object_string_add(json_nexthop_global,
8994 "hostname",
939a97f4 8995 path->peer->hostname);
515c2602 8996
a4d82a8a
PZ
8997 json_object_string_add(json_nexthop_global, "afi",
8998 "ipv6");
8999 json_object_string_add(json_nexthop_global, "scope",
9000 "global");
445c2480
DS
9001
9002 /* We display both LL & GL if both have been
9003 * received */
0606039c
DA
9004 if ((attr->mp_nexthop_len
9005 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9006 || (path->peer->conf_if)) {
a4d82a8a 9007 json_nexthop_ll = json_object_new_object();
c949c771
DA
9008 json_object_string_addf(
9009 json_nexthop_ll, "ip", "%pI6",
9010 &attr->mp_nexthop_local);
515c2602 9011
939a97f4 9012 if (path->peer->hostname)
515c2602
DA
9013 json_object_string_add(
9014 json_nexthop_ll, "hostname",
939a97f4 9015 path->peer->hostname);
515c2602 9016
a4d82a8a
PZ
9017 json_object_string_add(json_nexthop_ll, "afi",
9018 "ipv6");
9019 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9020 "link-local");
d62a17ae 9021
a4d82a8a
PZ
9022 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9023 &attr->mp_nexthop_local)
445c2480
DS
9024 != 0)
9025 && !attr->mp_nexthop_prefer_global)
d62a17ae 9026 json_object_boolean_true_add(
a4d82a8a 9027 json_nexthop_ll, "used");
445c2480
DS
9028 else
9029 json_object_boolean_true_add(
a4d82a8a 9030 json_nexthop_global, "used");
445c2480
DS
9031 } else
9032 json_object_boolean_true_add(
9033 json_nexthop_global, "used");
9034 } else {
9035 /* Display LL if LL/Global both in table unless
9036 * prefer-global is set */
0606039c
DA
9037 if (((attr->mp_nexthop_len
9038 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9039 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9040 || (path->peer->conf_if)) {
9041 if (path->peer->conf_if) {
a4d82a8a 9042 len = vty_out(vty, "%s",
9b6d8fcf 9043 path->peer->conf_if);
ae248832
MK
9044 /* len of IPv6 addr + max len of def
9045 * ifname */
9046 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9047
9048 if (len < 1)
a4d82a8a 9049 vty_out(vty, "\n%*s", 36, " ");
445c2480 9050 else
a4d82a8a 9051 vty_out(vty, "%*s", len, " ");
d62a17ae 9052 } else {
aef999a2
DA
9053 if (nexthop_hostname)
9054 len = vty_out(
9055 vty, "%pI6(%s)%s",
9056 &attr->mp_nexthop_local,
9057 nexthop_hostname,
9058 vrf_id_str);
9059 else
9060 len = vty_out(
9061 vty, "%pI6%s",
9062 &attr->mp_nexthop_local,
9063 vrf_id_str);
9064
ae248832 9065 len = wide ? (41 - len) : (16 - len);
d62a17ae 9066
9067 if (len < 1)
a4d82a8a 9068 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9069 else
a4d82a8a 9070 vty_out(vty, "%*s", len, " ");
d62a17ae 9071 }
445c2480 9072 } else {
aef999a2
DA
9073 if (nexthop_hostname)
9074 len = vty_out(vty, "%pI6(%s)%s",
9075 &attr->mp_nexthop_global,
9076 nexthop_hostname,
9077 vrf_id_str);
9078 else
9079 len = vty_out(vty, "%pI6%s",
9080 &attr->mp_nexthop_global,
9081 vrf_id_str);
9082
ae248832 9083 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9084
9085 if (len < 1)
9086 vty_out(vty, "\n%*s", 36, " ");
9087 else
9088 vty_out(vty, "%*s", len, " ");
d62a17ae 9089 }
9090 }
445c2480 9091 }
718e3744 9092
445c2480
DS
9093 /* MED/Metric */
9094 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9095 if (json_paths)
50e05855 9096 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9097 else if (wide)
9098 vty_out(vty, "%7u", attr->med);
0fbac0b4 9099 else
445c2480 9100 vty_out(vty, "%10u", attr->med);
ae248832
MK
9101 else if (!json_paths) {
9102 if (wide)
9103 vty_out(vty, "%*s", 7, " ");
9104 else
9105 vty_out(vty, "%*s", 10, " ");
9106 }
d62a17ae 9107
445c2480
DS
9108 /* Local Pref */
9109 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9110 if (json_paths)
50e05855 9111 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9112 attr->local_pref);
9113 else
445c2480
DS
9114 vty_out(vty, "%7u", attr->local_pref);
9115 else if (!json_paths)
9116 vty_out(vty, " ");
d62a17ae 9117
445c2480
DS
9118 if (json_paths)
9119 json_object_int_add(json_path, "weight", attr->weight);
9120 else
9121 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9122
445c2480
DS
9123 if (json_paths) {
9124 char buf[BUFSIZ];
a4d82a8a
PZ
9125 json_object_string_add(
9126 json_path, "peerId",
9b6d8fcf 9127 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 9128 }
b05a1c8b 9129
445c2480
DS
9130 /* Print aspath */
9131 if (attr->aspath) {
0fbac0b4 9132 if (json_paths)
50e05855 9133 json_object_string_add(json_path, "path",
0fbac0b4
DA
9134 attr->aspath->str);
9135 else
445c2480 9136 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9137 }
f1aa5d8a 9138
445c2480
DS
9139 /* Print origin */
9140 if (json_paths)
a4d82a8a
PZ
9141 json_object_string_add(json_path, "origin",
9142 bgp_origin_long_str[attr->origin]);
445c2480
DS
9143 else
9144 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9145
9df8b37c 9146 if (json_paths) {
d071f237 9147 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9148 json_object_string_add(json_path, "esi",
9149 esi_to_str(&attr->esi,
9150 esi_buf, sizeof(esi_buf)));
9151 }
6f214dd3
CS
9152 if (safi == SAFI_EVPN &&
9153 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9154 json_ext_community = json_object_new_object();
b53e67a3
DA
9155 json_object_string_add(
9156 json_ext_community, "string",
9157 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9158 json_object_object_add(json_path,
9159 "extendedCommunity",
9160 json_ext_community);
9161 }
9162
9df8b37c
PZ
9163 if (nexthop_self)
9164 json_object_boolean_true_add(json_path,
9165 "announceNexthopSelf");
9166 if (nexthop_othervrf) {
9167 json_object_string_add(json_path, "nhVrfName",
9168 nexthop_vrfname);
9169
9170 json_object_int_add(json_path, "nhVrfId",
9171 ((nexthop_vrfid == VRF_UNKNOWN)
9172 ? -1
9173 : (int)nexthop_vrfid));
9174 }
9175 }
9176
d62a17ae 9177 if (json_paths) {
9178 if (json_nexthop_global || json_nexthop_ll) {
9179 json_nexthops = json_object_new_array();
f1aa5d8a 9180
d62a17ae 9181 if (json_nexthop_global)
9182 json_object_array_add(json_nexthops,
9183 json_nexthop_global);
f1aa5d8a 9184
d62a17ae 9185 if (json_nexthop_ll)
9186 json_object_array_add(json_nexthops,
9187 json_nexthop_ll);
f1aa5d8a 9188
d62a17ae 9189 json_object_object_add(json_path, "nexthops",
9190 json_nexthops);
9191 }
9192
9193 json_object_array_add(json_paths, json_path);
9194 } else {
9195 vty_out(vty, "\n");
6f214dd3 9196
b5e140c8 9197 if (safi == SAFI_EVPN) {
d071f237 9198 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9199 /* XXX - add these params to the json out */
b5e140c8 9200 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9201 vty_out(vty, "ESI:%s",
9202 esi_to_str(&attr->esi, esi_buf,
9203 sizeof(esi_buf)));
60605cbc 9204
229587fb 9205 vty_out(vty, "\n");
b5e140c8
AK
9206 }
9207 if (attr->flag &
9208 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9209 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9210 vty_out(vty, "%s\n",
9211 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9212 }
6f214dd3
CS
9213 }
9214
49e5a4a0 9215#ifdef ENABLE_BGP_VNC
d62a17ae 9216 /* prints an additional line, indented, with VNC info, if
9217 * present */
9218 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9219 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9220#endif
d62a17ae 9221 }
9222}
718e3744 9223
9224/* called from terminal list command */
7d3cae70
DA
9225void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9226 const struct prefix *p, struct attr *attr, safi_t safi,
9227 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9228{
9229 json_object *json_status = NULL;
9230 json_object *json_net = NULL;
aef999a2 9231 int len;
d62a17ae 9232 char buff[BUFSIZ];
dc387b0f 9233
d62a17ae 9234 /* Route status display. */
9235 if (use_json) {
9236 json_status = json_object_new_object();
9237 json_net = json_object_new_object();
9238 } else {
9239 vty_out(vty, "*");
9240 vty_out(vty, ">");
9241 vty_out(vty, " ");
9242 }
718e3744 9243
d62a17ae 9244 /* print prefix and mask */
50e05855 9245 if (use_json) {
dc387b0f
LK
9246 if (safi == SAFI_EVPN)
9247 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9248 else if (p->family == AF_INET || p->family == AF_INET6) {
9249 json_object_string_add(
9250 json_net, "addrPrefix",
9251 inet_ntop(p->family, &p->u.prefix, buff,
9252 BUFSIZ));
9253 json_object_int_add(json_net, "prefixLen",
9254 p->prefixlen);
67d7e256 9255 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9256 }
50e05855 9257 } else
7d3cae70 9258 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9259
9260 /* Print attribute */
9261 if (attr) {
9262 if (use_json) {
9263 if (p->family == AF_INET
9264 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9265 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9266 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9267 json_object_string_addf(
9268 json_net, "nextHop", "%pI4",
9269 &attr->mp_nexthop_global_in);
d62a17ae 9270 else
c949c771
DA
9271 json_object_string_addf(
9272 json_net, "nextHop", "%pI4",
9273 &attr->nexthop);
d62a17ae 9274 } else if (p->family == AF_INET6
9275 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9276 json_object_string_addf(
9277 json_net, "nextHopGlobal", "%pI6",
9278 &attr->mp_nexthop_global);
23d0a753
DA
9279 } else if (p->family == AF_EVPN
9280 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9281 json_object_string_addf(
9282 json_net, "nextHop", "%pI4",
9283 &attr->mp_nexthop_global_in);
23d0a753 9284 }
d62a17ae 9285
9286 if (attr->flag
9287 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9288 json_object_int_add(json_net, "metric",
9289 attr->med);
9290
0fbac0b4 9291 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9292 json_object_int_add(json_net, "locPrf",
0fbac0b4 9293 attr->local_pref);
d62a17ae 9294
9295 json_object_int_add(json_net, "weight", attr->weight);
9296
9297 /* Print aspath */
0fbac0b4 9298 if (attr->aspath)
50e05855 9299 json_object_string_add(json_net, "path",
0fbac0b4 9300 attr->aspath->str);
d62a17ae 9301
9302 /* Print origin */
9303 json_object_string_add(json_net, "bgpOriginCode",
9304 bgp_origin_str[attr->origin]);
9305 } else {
9306 if (p->family == AF_INET
9307 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9308 || safi == SAFI_EVPN
9309 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9310 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9311 || safi == SAFI_EVPN)
23d0a753
DA
9312 vty_out(vty, "%-16pI4",
9313 &attr->mp_nexthop_global_in);
ae248832 9314 else if (wide)
23d0a753 9315 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9316 else
23d0a753 9317 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9318 } else if (p->family == AF_INET6
9319 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9320 char buf[BUFSIZ];
9321
9322 len = vty_out(
9323 vty, "%s",
9324 inet_ntop(AF_INET6,
9325 &attr->mp_nexthop_global, buf,
9326 BUFSIZ));
ae248832 9327 len = wide ? (41 - len) : (16 - len);
d62a17ae 9328 if (len < 1)
9329 vty_out(vty, "\n%*s", 36, " ");
9330 else
9331 vty_out(vty, "%*s", len, " ");
9332 }
9333 if (attr->flag
9334 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9335 if (wide)
9336 vty_out(vty, "%7u", attr->med);
9337 else
9338 vty_out(vty, "%10u", attr->med);
9339 else if (wide)
9340 vty_out(vty, " ");
d62a17ae 9341 else
9342 vty_out(vty, " ");
718e3744 9343
d62a17ae 9344 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9345 vty_out(vty, "%7u", attr->local_pref);
9346 else
9347 vty_out(vty, " ");
9348
9349 vty_out(vty, "%7u ", attr->weight);
9350
9351 /* Print aspath */
9352 if (attr->aspath)
9353 aspath_print_vty(vty, "%s", attr->aspath, " ");
9354
9355 /* Print origin */
9356 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9357 }
9358 }
9359 if (use_json) {
9360 json_object_boolean_true_add(json_status, "*");
9361 json_object_boolean_true_add(json_status, ">");
9362 json_object_object_add(json_net, "appliedStatusSymbols",
9363 json_status);
1608ff77 9364
dc387b0f
LK
9365 prefix2str(p, buff, PREFIX_STRLEN);
9366 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9367 } else
9368 vty_out(vty, "\n");
9369}
9370
bd494ec5 9371void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9372 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9373 json_object *json)
9374{
9375 json_object *json_out = NULL;
9376 struct attr *attr;
9377 mpls_label_t label = MPLS_INVALID_LABEL;
9378
9b6d8fcf 9379 if (!path->extra)
d62a17ae 9380 return;
9381
9382 if (json)
9383 json_out = json_object_new_object();
9384
9385 /* short status lead text */
82c298be 9386 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9387
9388 /* print prefix and mask */
9389 if (json == NULL) {
9390 if (!display)
7d3cae70 9391 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9392 else
9393 vty_out(vty, "%*s", 17, " ");
9394 }
9395
9396 /* Print attribute */
9b6d8fcf 9397 attr = path->attr;
05864da7
DS
9398 if (((p->family == AF_INET)
9399 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9400 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9401 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9402 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9403 || safi == SAFI_EVPN) {
9404 if (json)
c949c771
DA
9405 json_object_string_addf(
9406 json_out, "mpNexthopGlobalIn", "%pI4",
9407 &attr->mp_nexthop_global_in);
05864da7 9408 else
23d0a753
DA
9409 vty_out(vty, "%-16pI4",
9410 &attr->mp_nexthop_global_in);
05864da7
DS
9411 } else {
9412 if (json)
c949c771
DA
9413 json_object_string_addf(json_out, "nexthop",
9414 "%pI4", &attr->nexthop);
05864da7 9415 else
23d0a753 9416 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9417 }
9418 } else if (((p->family == AF_INET6)
9419 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9420 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9421 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9422 char buf_a[512];
9423
9424 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9425 if (json)
c949c771
DA
9426 json_object_string_addf(
9427 json_out, "mpNexthopGlobalIn", "%pI6",
9428 &attr->mp_nexthop_global);
05864da7
DS
9429 else
9430 vty_out(vty, "%s",
9431 inet_ntop(AF_INET6,
9432 &attr->mp_nexthop_global,
9433 buf_a, sizeof(buf_a)));
9434 } else if (attr->mp_nexthop_len
9435 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9436 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9437 &attr->mp_nexthop_global,
9438 &attr->mp_nexthop_local);
9439 if (json)
9440 json_object_string_add(json_out,
9441 "mpNexthopGlobalLocal",
9442 buf_a);
9443 else
9444 vty_out(vty, "%s", buf_a);
d62a17ae 9445 }
9446 }
9447
9b6d8fcf 9448 label = decode_label(&path->extra->label[0]);
d62a17ae 9449
9450 if (bgp_is_valid_label(&label)) {
9451 if (json) {
9452 json_object_int_add(json_out, "notag", label);
9453 json_object_array_add(json, json_out);
9454 } else {
9455 vty_out(vty, "notag/%d", label);
9456 vty_out(vty, "\n");
9457 }
700ddfed
PG
9458 } else if (!json)
9459 vty_out(vty, "\n");
d62a17ae 9460}
718e3744 9461
bd494ec5 9462void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9463 struct bgp_path_info *path, int display,
d62a17ae 9464 json_object *json_paths)
718e3744 9465{
d62a17ae 9466 struct attr *attr;
14f51eba 9467 char buf[BUFSIZ] = {0};
d62a17ae 9468 json_object *json_path = NULL;
14f51eba
LK
9469 json_object *json_nexthop = NULL;
9470 json_object *json_overlay = NULL;
856ca177 9471
9b6d8fcf 9472 if (!path->extra)
d62a17ae 9473 return;
718e3744 9474
14f51eba
LK
9475 if (json_paths) {
9476 json_path = json_object_new_object();
9477 json_overlay = json_object_new_object();
9478 json_nexthop = json_object_new_object();
9479 }
9480
d62a17ae 9481 /* short status lead text */
82c298be 9482 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9483
d62a17ae 9484 /* print prefix and mask */
9485 if (!display)
7d3cae70 9486 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9487 else
9488 vty_out(vty, "%*s", 17, " ");
9489
9490 /* Print attribute */
9b6d8fcf 9491 attr = path->attr;
05864da7
DS
9492 char buf1[BUFSIZ];
9493 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9494
05864da7
DS
9495 switch (af) {
9496 case AF_INET:
9497 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9498 if (!json_path) {
9499 vty_out(vty, "%-16s", buf);
9500 } else {
9501 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9502
05864da7 9503 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9504
05864da7
DS
9505 json_object_object_add(json_path, "nexthop",
9506 json_nexthop);
9507 }
9508 break;
9509 case AF_INET6:
9510 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9511 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9512 if (!json_path) {
9513 vty_out(vty, "%s(%s)", buf, buf1);
9514 } else {
9515 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9516
05864da7
DS
9517 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9518 buf1);
14f51eba 9519
05864da7 9520 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9521
05864da7
DS
9522 json_object_object_add(json_path, "nexthop",
9523 json_nexthop);
9524 }
9525 break;
9526 default:
9527 if (!json_path) {
9528 vty_out(vty, "?");
9529 } else {
9530 json_object_string_add(json_nexthop, "Error",
9531 "Unsupported address-family");
77a2f8e5
DA
9532 json_object_string_add(json_nexthop, "error",
9533 "Unsupported address-family");
d62a17ae 9534 }
05864da7 9535 }
988258b4 9536
6c924775
DS
9537 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9538
860e740b 9539 ipaddr2str(&eo->gw_ip, buf, BUFSIZ);
14f51eba 9540
05864da7
DS
9541 if (!json_path)
9542 vty_out(vty, "/%s", buf);
9543 else
9544 json_object_string_add(json_overlay, "gw", buf);
9545
b53e67a3 9546 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9547 char *mac = NULL;
9548 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9549 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9550 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9551
9552 if (routermac)
9553 mac = ecom_mac2str((char *)routermac->val);
9554 if (mac) {
9555 if (!json_path) {
c4efd0f4 9556 vty_out(vty, "/%s", mac);
05864da7
DS
9557 } else {
9558 json_object_string_add(json_overlay, "rmac",
9559 mac);
988258b4 9560 }
05864da7 9561 XFREE(MTYPE_TMP, mac);
988258b4 9562 }
05864da7 9563 }
718e3744 9564
05864da7
DS
9565 if (!json_path) {
9566 vty_out(vty, "\n");
9567 } else {
9568 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9569
05864da7 9570 json_object_array_add(json_paths, json_path);
14f51eba 9571 }
d62a17ae 9572}
718e3744 9573
d62a17ae 9574/* dampening route */
5f040085
DS
9575static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9576 struct bgp_path_info *path, int display,
9577 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9578 json_object *json_paths)
d62a17ae 9579{
e5be8c1d 9580 struct attr *attr = path->attr;
d62a17ae 9581 int len;
9582 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9583 json_object *json_path = NULL;
9584
9585 if (use_json)
9586 json_path = json_object_new_object();
d62a17ae 9587
9588 /* short status lead text */
e5be8c1d 9589 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9590
9591 /* print prefix and mask */
9592 if (!use_json) {
9593 if (!display)
7d3cae70 9594 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9595 else
9596 vty_out(vty, "%*s", 17, " ");
d62a17ae 9597
e5be8c1d
DA
9598 len = vty_out(vty, "%s", path->peer->host);
9599 len = 17 - len;
9600
9601 if (len < 1)
d62a17ae 9602 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9603 else
9604 vty_out(vty, "%*s", len, " ");
d62a17ae 9605
9b6d8fcf
DS
9606 vty_out(vty, "%s ",
9607 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9608 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9609 use_json, NULL));
d62a17ae 9610
e5be8c1d 9611 if (attr->aspath)
05864da7 9612 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9613
05864da7
DS
9614 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9615
d62a17ae 9616 vty_out(vty, "\n");
e5be8c1d
DA
9617 } else {
9618 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9619 safi, use_json, json_path);
9620
9621 if (attr->aspath)
9622 json_object_string_add(json_path, "asPath",
9623 attr->aspath->str);
9624
9625 json_object_string_add(json_path, "origin",
9626 bgp_origin_str[attr->origin]);
9627 json_object_string_add(json_path, "peerHost", path->peer->host);
9628
9629 json_object_array_add(json_paths, json_path);
9630 }
d62a17ae 9631}
718e3744 9632
d62a17ae 9633/* flap route */
5f040085
DS
9634static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9635 struct bgp_path_info *path, int display,
9636 afi_t afi, safi_t safi, bool use_json,
31258046 9637 json_object *json_paths)
784d3a42 9638{
31258046 9639 struct attr *attr = path->attr;
d62a17ae 9640 struct bgp_damp_info *bdi;
9641 char timebuf[BGP_UPTIME_LEN];
9642 int len;
31258046 9643 json_object *json_path = NULL;
784d3a42 9644
9b6d8fcf 9645 if (!path->extra)
d62a17ae 9646 return;
784d3a42 9647
31258046
DA
9648 if (use_json)
9649 json_path = json_object_new_object();
9650
9b6d8fcf 9651 bdi = path->extra->damp_info;
784d3a42 9652
d62a17ae 9653 /* short status lead text */
31258046 9654 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9655
d62a17ae 9656 if (!use_json) {
9657 if (!display)
7d3cae70 9658 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9659 else
9660 vty_out(vty, "%*s", 17, " ");
784d3a42 9661
31258046
DA
9662 len = vty_out(vty, "%s", path->peer->host);
9663 len = 16 - len;
9664 if (len < 1)
d62a17ae 9665 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9666 else
9667 vty_out(vty, "%*s", len, " ");
784d3a42 9668
31258046
DA
9669 len = vty_out(vty, "%d", bdi->flap);
9670 len = 5 - len;
9671 if (len < 1)
d62a17ae 9672 vty_out(vty, " ");
d62a17ae 9673 else
9674 vty_out(vty, "%*s", len, " ");
d62a17ae 9675
996c9314
LB
9676 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9677 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9678
31258046
DA
9679 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9680 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9681 vty_out(vty, "%s ",
9b6d8fcf 9682 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9683 BGP_UPTIME_LEN, afi,
31258046
DA
9684 safi, use_json, NULL));
9685 else
d62a17ae 9686 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9687
31258046 9688 if (attr->aspath)
05864da7 9689 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9690
05864da7
DS
9691 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9692
d62a17ae 9693 vty_out(vty, "\n");
31258046
DA
9694 } else {
9695 json_object_string_add(json_path, "peerHost", path->peer->host);
9696 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9697
9698 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9699 json_path);
9700
9701 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9702 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9703 bgp_damp_reuse_time_vty(vty, path, timebuf,
9704 BGP_UPTIME_LEN, afi, safi,
9705 use_json, json_path);
9706
9707 if (attr->aspath)
9708 json_object_string_add(json_path, "asPath",
9709 attr->aspath->str);
9710
9711 json_object_string_add(json_path, "origin",
9712 bgp_origin_str[attr->origin]);
9713
9714 json_object_array_add(json_paths, json_path);
9715 }
d62a17ae 9716}
9717
9718static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9719 int *first, const char *header,
9720 json_object *json_adv_to)
9721{
9722 char buf1[INET6_ADDRSTRLEN];
9723 json_object *json_peer = NULL;
9724
9725 if (json_adv_to) {
9726 /* 'advertised-to' is a dictionary of peers we have advertised
9727 * this
9728 * prefix too. The key is the peer's IP or swpX, the value is
9729 * the
9730 * hostname if we know it and "" if not.
9731 */
9732 json_peer = json_object_new_object();
9733
9734 if (peer->hostname)
9735 json_object_string_add(json_peer, "hostname",
9736 peer->hostname);
9737
9738 if (peer->conf_if)
9739 json_object_object_add(json_adv_to, peer->conf_if,
9740 json_peer);
9741 else
9742 json_object_object_add(
9743 json_adv_to,
9744 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9745 json_peer);
9746 } else {
9747 if (*first) {
9748 vty_out(vty, "%s", header);
9749 *first = 0;
9750 }
9751
9752 if (peer->hostname
892fedb6 9753 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9754 if (peer->conf_if)
9755 vty_out(vty, " %s(%s)", peer->hostname,
9756 peer->conf_if);
9757 else
9758 vty_out(vty, " %s(%s)", peer->hostname,
9759 sockunion2str(&peer->su, buf1,
9760 SU_ADDRSTRLEN));
9761 } else {
9762 if (peer->conf_if)
9763 vty_out(vty, " %s", peer->conf_if);
9764 else
9765 vty_out(vty, " %s",
9766 sockunion2str(&peer->su, buf1,
9767 SU_ADDRSTRLEN));
9768 }
9769 }
784d3a42
PG
9770}
9771
dcc68b5e
MS
9772static void route_vty_out_tx_ids(struct vty *vty,
9773 struct bgp_addpath_info_data *d)
9774{
9775 int i;
9776
9777 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9778 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9779 d->addpath_tx_id[i],
9780 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9781 }
9782}
9783
5e4d4c8a 9784static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9785 struct bgp_path_info *pi,
9786 struct attr *attr,
9787 json_object *json_path)
5e4d4c8a
AK
9788{
9789 char esi_buf[ESI_STR_LEN];
9790 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9791 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9792 ATTR_ES_PEER_ROUTER);
9793 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9794 ATTR_ES_PEER_ACTIVE);
9795 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9796 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9797 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9798 if (json_path) {
9799 json_object *json_es_info = NULL;
9800
9801 json_object_string_add(
9802 json_path, "esi",
9803 esi_buf);
9804 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9805 json_es_info = json_object_new_object();
9806 if (es_local)
9807 json_object_boolean_true_add(
9808 json_es_info, "localEs");
9809 if (peer_active)
9810 json_object_boolean_true_add(
9811 json_es_info, "peerActive");
9812 if (peer_proxy)
9813 json_object_boolean_true_add(
9814 json_es_info, "peerProxy");
9815 if (peer_router)
9816 json_object_boolean_true_add(
9817 json_es_info, "peerRouter");
9818 if (attr->mm_sync_seqnum)
9819 json_object_int_add(
9820 json_es_info, "peerSeq",
9821 attr->mm_sync_seqnum);
9822 json_object_object_add(
9823 json_path, "es_info",
9824 json_es_info);
9825 }
9826 } else {
9827 if (bgp_evpn_attr_is_sync(attr))
9828 vty_out(vty,
9829 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9830 esi_buf,
9831 es_local ? "local-es":"",
9832 peer_proxy ? "proxy " : "",
9833 peer_active ? "active ":"",
9834 peer_router ? "router ":"",
9835 attr->mm_sync_seqnum);
9836 else
9837 vty_out(vty, " ESI %s %s\n",
9838 esi_buf,
9839 es_local ? "local-es":"");
9840 }
9841}
9842
4933eaaf
DS
9843void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9844 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9845 enum rpki_states rpki_curr_state,
9846 json_object *json_paths)
d62a17ae 9847{
9848 char buf[INET6_ADDRSTRLEN];
9849 char buf1[BUFSIZ];
515c2602 9850 struct attr *attr = path->attr;
d62a17ae 9851 int sockunion_vty_out(struct vty *, union sockunion *);
9852 time_t tbuf;
9853 json_object *json_bestpath = NULL;
9854 json_object *json_cluster_list = NULL;
9855 json_object *json_cluster_list_list = NULL;
9856 json_object *json_ext_community = NULL;
9857 json_object *json_last_update = NULL;
7fd077aa 9858 json_object *json_pmsi = NULL;
d62a17ae 9859 json_object *json_nexthop_global = NULL;
9860 json_object *json_nexthop_ll = NULL;
9861 json_object *json_nexthops = NULL;
9862 json_object *json_path = NULL;
9863 json_object *json_peer = NULL;
9864 json_object *json_string = NULL;
9865 json_object *json_adv_to = NULL;
9866 int first = 0;
9867 struct listnode *node, *nnode;
9868 struct peer *peer;
be92fc9f 9869 bool addpath_capable;
d62a17ae 9870 int has_adj;
9871 unsigned int first_as;
1defdda8 9872 bool nexthop_self =
9b6d8fcf 9873 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9874 int i;
2ba93fd6
DA
9875 char *nexthop_hostname =
9876 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9877
9878 if (json_paths) {
9879 json_path = json_object_new_object();
9880 json_peer = json_object_new_object();
9881 json_nexthop_global = json_object_new_object();
9882 }
9883
8304dabf
AD
9884 if (safi == SAFI_EVPN) {
9885 if (!json_paths)
9886 vty_out(vty, " Route %pRN", bn);
9887 }
9888
44c69747 9889 if (path->extra) {
b57ba6d2 9890 char tag_buf[30];
d62a17ae 9891
d62a17ae 9892 tag_buf[0] = '\0';
9b6d8fcf
DS
9893 if (path->extra && path->extra->num_labels) {
9894 bgp_evpn_label2str(path->extra->label,
9895 path->extra->num_labels, tag_buf,
a4d82a8a 9896 sizeof(tag_buf));
d62a17ae 9897 }
d7325ee7 9898 if (safi == SAFI_EVPN) {
44c69747 9899 if (!json_paths) {
44c69747
LK
9900 if (tag_buf[0] != '\0')
9901 vty_out(vty, " VNI %s", tag_buf);
44c69747 9902 } else {
77a2f8e5 9903 if (tag_buf[0]) {
44c69747
LK
9904 json_object_string_add(json_path, "VNI",
9905 tag_buf);
77a2f8e5
DA
9906 json_object_string_add(json_path, "vni",
9907 tag_buf);
9908 }
44c69747 9909 }
d7325ee7
DD
9910 }
9911
44c69747 9912 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9913 struct bgp_path_info *parent_ri;
9bcb3eef 9914 struct bgp_dest *dest, *pdest;
d62a17ae 9915
9b6d8fcf 9916 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9917 dest = parent_ri->net;
9918 if (dest && dest->pdest) {
9919 pdest = dest->pdest;
9920 prefix_rd2str(
9921 (struct prefix_rd *)bgp_dest_get_prefix(
9922 pdest),
9923 buf1, sizeof(buf1));
d7325ee7 9924 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9925 vty_out(vty,
58bff4d1 9926 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9927 buf1,
9928 (struct prefix_evpn *)
9929 bgp_dest_get_prefix(
9930 dest),
9931 tag_buf);
58bff4d1
AK
9932 if (attr->es_flags & ATTR_ES_L3_NHG)
9933 vty_out(vty, ", L3NHG %s",
9934 (attr->es_flags
9935 & ATTR_ES_L3_NHG_ACTIVE)
9936 ? "active"
9937 : "inactive");
9938 vty_out(vty, "\n");
9939
d7325ee7 9940 } else
2dbe669b
DA
9941 vty_out(vty,
9942 " Imported from %s:%pFX\n",
9943 buf1,
9944 (struct prefix_evpn *)
9945 bgp_dest_get_prefix(
9946 dest));
d62a17ae 9947 }
9948 }
9949 }
d62a17ae 9950
8304dabf
AD
9951 if (safi == SAFI_EVPN
9952 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9953 char gwip_buf[INET6_ADDRSTRLEN];
9954
860e740b
IR
9955 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
9956 sizeof(gwip_buf));
8304dabf
AD
9957
9958 if (json_paths)
9959 json_object_string_add(json_path, "gatewayIP",
9960 gwip_buf);
9961 else
9962 vty_out(vty, " Gateway IP %s", gwip_buf);
9963 }
9964
9965 if (safi == SAFI_EVPN)
9966 vty_out(vty, "\n");
9967
05864da7
DS
9968 /* Line1 display AS-path, Aggregator */
9969 if (attr->aspath) {
9970 if (json_paths) {
9971 if (!attr->aspath->json)
9972 aspath_str_update(attr->aspath, true);
9973 json_object_lock(attr->aspath->json);
9974 json_object_object_add(json_path, "aspath",
9975 attr->aspath->json);
9976 } else {
9977 if (attr->aspath->segments)
9978 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9979 else
05864da7 9980 vty_out(vty, " Local");
d62a17ae 9981 }
05864da7 9982 }
d62a17ae 9983
05864da7
DS
9984 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9985 if (json_paths)
9986 json_object_boolean_true_add(json_path, "removed");
9987 else
9988 vty_out(vty, ", (removed)");
9989 }
d62a17ae 9990
05864da7
DS
9991 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9992 if (json_paths)
9993 json_object_boolean_true_add(json_path, "stale");
9994 else
9995 vty_out(vty, ", (stale)");
9996 }
d62a17ae 9997
05864da7
DS
9998 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9999 if (json_paths) {
10000 json_object_int_add(json_path, "aggregatorAs",
10001 attr->aggregator_as);
c949c771
DA
10002 json_object_string_addf(json_path, "aggregatorId",
10003 "%pI4", &attr->aggregator_addr);
05864da7 10004 } else {
88d495a9
DA
10005 vty_out(vty, ", (aggregated by %u %pI4)",
10006 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10007 }
05864da7 10008 }
d62a17ae 10009
05864da7
DS
10010 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10011 PEER_FLAG_REFLECTOR_CLIENT)) {
10012 if (json_paths)
10013 json_object_boolean_true_add(json_path,
10014 "rxedFromRrClient");
10015 else
10016 vty_out(vty, ", (Received from a RR-client)");
10017 }
d62a17ae 10018
05864da7
DS
10019 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10020 PEER_FLAG_RSERVER_CLIENT)) {
10021 if (json_paths)
10022 json_object_boolean_true_add(json_path,
10023 "rxedFromRsClient");
10024 else
10025 vty_out(vty, ", (Received from a RS-client)");
10026 }
d62a17ae 10027
05864da7
DS
10028 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10029 if (json_paths)
10030 json_object_boolean_true_add(json_path,
10031 "dampeningHistoryEntry");
10032 else
10033 vty_out(vty, ", (history entry)");
10034 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10035 if (json_paths)
10036 json_object_boolean_true_add(json_path,
10037 "dampeningSuppressed");
10038 else
10039 vty_out(vty, ", (suppressed due to dampening)");
10040 }
d62a17ae 10041
05864da7
DS
10042 if (!json_paths)
10043 vty_out(vty, "\n");
d62a17ae 10044
05864da7
DS
10045 /* Line2 display Next-hop, Neighbor, Router-id */
10046 /* Display the nexthop */
9bcb3eef 10047 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10048
10049 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10050 || bn_p->family == AF_EVPN)
05864da7
DS
10051 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10052 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10053 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10054 || safi == SAFI_EVPN) {
515c2602 10055 if (json_paths) {
c949c771
DA
10056 json_object_string_addf(
10057 json_nexthop_global, "ip", "%pI4",
10058 &attr->mp_nexthop_global_in);
515c2602 10059
939a97f4 10060 if (path->peer->hostname)
515c2602
DA
10061 json_object_string_add(
10062 json_nexthop_global, "hostname",
939a97f4 10063 path->peer->hostname);
aef999a2
DA
10064 } else {
10065 if (nexthop_hostname)
10066 vty_out(vty, " %pI4(%s)",
10067 &attr->mp_nexthop_global_in,
10068 nexthop_hostname);
10069 else
10070 vty_out(vty, " %pI4",
10071 &attr->mp_nexthop_global_in);
10072 }
d62a17ae 10073 } else {
515c2602 10074 if (json_paths) {
c949c771
DA
10075 json_object_string_addf(json_nexthop_global,
10076 "ip", "%pI4",
10077 &attr->nexthop);
515c2602 10078
939a97f4 10079 if (path->peer->hostname)
515c2602
DA
10080 json_object_string_add(
10081 json_nexthop_global, "hostname",
939a97f4 10082 path->peer->hostname);
aef999a2
DA
10083 } else {
10084 if (nexthop_hostname)
10085 vty_out(vty, " %pI4(%s)",
10086 &attr->nexthop,
10087 nexthop_hostname);
10088 else
10089 vty_out(vty, " %pI4",
10090 &attr->nexthop);
10091 }
d62a17ae 10092 }
10093
05864da7
DS
10094 if (json_paths)
10095 json_object_string_add(json_nexthop_global, "afi",
10096 "ipv4");
10097 } else {
10098 if (json_paths) {
c949c771
DA
10099 json_object_string_addf(json_nexthop_global, "ip",
10100 "%pI6",
10101 &attr->mp_nexthop_global);
515c2602 10102
939a97f4 10103 if (path->peer->hostname)
515c2602
DA
10104 json_object_string_add(json_nexthop_global,
10105 "hostname",
939a97f4 10106 path->peer->hostname);
515c2602 10107
05864da7
DS
10108 json_object_string_add(json_nexthop_global, "afi",
10109 "ipv6");
10110 json_object_string_add(json_nexthop_global, "scope",
10111 "global");
10112 } else {
aef999a2
DA
10113 if (nexthop_hostname)
10114 vty_out(vty, " %pI6(%s)",
10115 &attr->mp_nexthop_global,
10116 nexthop_hostname);
10117 else
10118 vty_out(vty, " %pI6",
10119 &attr->mp_nexthop_global);
d62a17ae 10120 }
05864da7 10121 }
d62a17ae 10122
05864da7
DS
10123 /* Display the IGP cost or 'inaccessible' */
10124 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10125 if (json_paths)
10126 json_object_boolean_false_add(json_nexthop_global,
10127 "accessible");
10128 else
10129 vty_out(vty, " (inaccessible)");
10130 } else {
10131 if (path->extra && path->extra->igpmetric) {
d62a17ae 10132 if (json_paths)
05864da7
DS
10133 json_object_int_add(json_nexthop_global,
10134 "metric",
10135 path->extra->igpmetric);
d62a17ae 10136 else
05864da7
DS
10137 vty_out(vty, " (metric %u)",
10138 path->extra->igpmetric);
d62a17ae 10139 }
10140
05864da7 10141 /* IGP cost is 0, display this only for json */
d62a17ae 10142 else {
d62a17ae 10143 if (json_paths)
05864da7
DS
10144 json_object_int_add(json_nexthop_global,
10145 "metric", 0);
d62a17ae 10146 }
d62a17ae 10147
05864da7
DS
10148 if (json_paths)
10149 json_object_boolean_true_add(json_nexthop_global,
10150 "accessible");
10151 }
d62a17ae 10152
05864da7
DS
10153 /* Display peer "from" output */
10154 /* This path was originated locally */
10155 if (path->peer == bgp->peer_self) {
d62a17ae 10156
05864da7 10157 if (safi == SAFI_EVPN
b54892e0 10158 || (bn_p->family == AF_INET
05864da7 10159 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10160 if (json_paths)
05864da7
DS
10161 json_object_string_add(json_peer, "peerId",
10162 "0.0.0.0");
d62a17ae 10163 else
05864da7
DS
10164 vty_out(vty, " from 0.0.0.0 ");
10165 } else {
d62a17ae 10166 if (json_paths)
05864da7
DS
10167 json_object_string_add(json_peer, "peerId",
10168 "::");
d62a17ae 10169 else
05864da7 10170 vty_out(vty, " from :: ");
d62a17ae 10171 }
d62a17ae 10172
4e9a9863 10173 if (json_paths)
c949c771
DA
10174 json_object_string_addf(json_peer, "routerId", "%pI4",
10175 &bgp->router_id);
4e9a9863 10176 else
23d0a753 10177 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10178 }
d62a17ae 10179
05864da7
DS
10180 /* We RXed this path from one of our peers */
10181 else {
10182
10183 if (json_paths) {
10184 json_object_string_add(json_peer, "peerId",
10185 sockunion2str(&path->peer->su,
10186 buf,
10187 SU_ADDRSTRLEN));
c949c771
DA
10188 json_object_string_addf(json_peer, "routerId", "%pI4",
10189 &path->peer->remote_id);
05864da7
DS
10190
10191 if (path->peer->hostname)
10192 json_object_string_add(json_peer, "hostname",
10193 path->peer->hostname);
10194
10195 if (path->peer->domainname)
10196 json_object_string_add(json_peer, "domainname",
10197 path->peer->domainname);
10198
10199 if (path->peer->conf_if)
10200 json_object_string_add(json_peer, "interface",
10201 path->peer->conf_if);
10202 } else {
10203 if (path->peer->conf_if) {
10204 if (path->peer->hostname
892fedb6
DA
10205 && CHECK_FLAG(path->peer->bgp->flags,
10206 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10207 vty_out(vty, " from %s(%s)",
10208 path->peer->hostname,
10209 path->peer->conf_if);
d62a17ae 10210 else
05864da7 10211 vty_out(vty, " from %s",
9b6d8fcf 10212 path->peer->conf_if);
d62a17ae 10213 } else {
05864da7 10214 if (path->peer->hostname
892fedb6
DA
10215 && CHECK_FLAG(path->peer->bgp->flags,
10216 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10217 vty_out(vty, " from %s(%s)",
10218 path->peer->hostname,
10219 path->peer->host);
d62a17ae 10220 else
05864da7
DS
10221 vty_out(vty, " from %s",
10222 sockunion2str(&path->peer->su,
10223 buf,
10224 SU_ADDRSTRLEN));
d62a17ae 10225 }
d62a17ae 10226
05864da7 10227 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10228 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10229 else
10230 vty_out(vty, " (%s)",
10231 inet_ntop(AF_INET,
10232 &path->peer->remote_id, buf1,
10233 sizeof(buf1)));
d62a17ae 10234 }
05864da7 10235 }
9df8b37c 10236
05864da7
DS
10237 /*
10238 * Note when vrfid of nexthop is different from that of prefix
10239 */
10240 if (path->extra && path->extra->bgp_orig) {
10241 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10242
05864da7
DS
10243 if (json_paths) {
10244 const char *vn;
9df8b37c 10245
05864da7
DS
10246 if (path->extra->bgp_orig->inst_type
10247 == BGP_INSTANCE_TYPE_DEFAULT)
10248 vn = VRF_DEFAULT_NAME;
10249 else
10250 vn = path->extra->bgp_orig->name;
9df8b37c 10251
05864da7 10252 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10253
05864da7
DS
10254 if (nexthop_vrfid == VRF_UNKNOWN) {
10255 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10256 } else {
05864da7
DS
10257 json_object_int_add(json_path, "nhVrfId",
10258 (int)nexthop_vrfid);
9df8b37c 10259 }
05864da7
DS
10260 } else {
10261 if (nexthop_vrfid == VRF_UNKNOWN)
10262 vty_out(vty, " vrf ?");
137147c6
DS
10263 else {
10264 struct vrf *vrf;
10265
10266 vrf = vrf_lookup_by_id(nexthop_vrfid);
10267 vty_out(vty, " vrf %s(%u)",
10268 VRF_LOGNAME(vrf), nexthop_vrfid);
10269 }
9df8b37c 10270 }
05864da7 10271 }
9df8b37c 10272
05864da7
DS
10273 if (nexthop_self) {
10274 if (json_paths) {
10275 json_object_boolean_true_add(json_path,
10276 "announceNexthopSelf");
10277 } else {
10278 vty_out(vty, " announce-nh-self");
9df8b37c 10279 }
05864da7 10280 }
9df8b37c 10281
05864da7
DS
10282 if (!json_paths)
10283 vty_out(vty, "\n");
d62a17ae 10284
05864da7
DS
10285 /* display the link-local nexthop */
10286 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10287 if (json_paths) {
10288 json_nexthop_ll = json_object_new_object();
c949c771
DA
10289 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10290 &attr->mp_nexthop_local);
515c2602 10291
939a97f4 10292 if (path->peer->hostname)
515c2602
DA
10293 json_object_string_add(json_nexthop_ll,
10294 "hostname",
939a97f4 10295 path->peer->hostname);
515c2602 10296
05864da7
DS
10297 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10298 json_object_string_add(json_nexthop_ll, "scope",
10299 "link-local");
d62a17ae 10300
05864da7
DS
10301 json_object_boolean_true_add(json_nexthop_ll,
10302 "accessible");
d62a17ae 10303
05864da7 10304 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10305 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10306 "used");
10307 else
10308 json_object_boolean_true_add(
10309 json_nexthop_global, "used");
10310 } else {
10311 vty_out(vty, " (%s) %s\n",
10312 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10313 buf, INET6_ADDRSTRLEN),
10314 attr->mp_nexthop_prefer_global
10315 ? "(prefer-global)"
10316 : "(used)");
d62a17ae 10317 }
05864da7
DS
10318 }
10319 /* If we do not have a link-local nexthop then we must flag the
10320 global as "used" */
10321 else {
10322 if (json_paths)
10323 json_object_boolean_true_add(json_nexthop_global,
10324 "used");
10325 }
d62a17ae 10326
b5e140c8 10327 if (safi == SAFI_EVPN &&
5e4d4c8a 10328 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10329 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10330 }
10331
05864da7
DS
10332 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10333 * Int/Ext/Local, Atomic, best */
10334 if (json_paths)
10335 json_object_string_add(json_path, "origin",
10336 bgp_origin_long_str[attr->origin]);
10337 else
10338 vty_out(vty, " Origin %s",
10339 bgp_origin_long_str[attr->origin]);
9df8b37c 10340
05864da7 10341 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10342 if (json_paths)
05864da7 10343 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10344 else
05864da7
DS
10345 vty_out(vty, ", metric %u", attr->med);
10346 }
9df8b37c 10347
05864da7
DS
10348 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10349 if (json_paths)
0fbac0b4 10350 json_object_int_add(json_path, "locPrf",
05864da7
DS
10351 attr->local_pref);
10352 else
10353 vty_out(vty, ", localpref %u", attr->local_pref);
10354 }
9df8b37c 10355
05864da7
DS
10356 if (attr->weight != 0) {
10357 if (json_paths)
10358 json_object_int_add(json_path, "weight", attr->weight);
10359 else
10360 vty_out(vty, ", weight %u", attr->weight);
10361 }
9df8b37c 10362
05864da7
DS
10363 if (attr->tag != 0) {
10364 if (json_paths)
10365 json_object_int_add(json_path, "tag", attr->tag);
10366 else
10367 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10368 }
9df8b37c 10369
05864da7
DS
10370 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10371 if (json_paths)
10372 json_object_boolean_false_add(json_path, "valid");
10373 else
10374 vty_out(vty, ", invalid");
10375 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10376 if (json_paths)
10377 json_object_boolean_true_add(json_path, "valid");
10378 else
10379 vty_out(vty, ", valid");
10380 }
9df8b37c 10381
7d3cae70
DA
10382 if (json_paths)
10383 json_object_int_add(json_path, "version", bn->version);
10384
05864da7
DS
10385 if (path->peer != bgp->peer_self) {
10386 if (path->peer->as == path->peer->local_as) {
10387 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10388 if (json_paths)
10389 json_object_string_add(
10390 json_peer, "type",
10391 "confed-internal");
d62a17ae 10392 else
05864da7 10393 vty_out(vty, ", confed-internal");
d62a17ae 10394 } else {
05864da7
DS
10395 if (json_paths)
10396 json_object_string_add(
10397 json_peer, "type", "internal");
10398 else
10399 vty_out(vty, ", internal");
9df8b37c 10400 }
05864da7
DS
10401 } else {
10402 if (bgp_confederation_peers_check(bgp,
10403 path->peer->as)) {
10404 if (json_paths)
10405 json_object_string_add(
10406 json_peer, "type",
10407 "confed-external");
d62a17ae 10408 else
05864da7 10409 vty_out(vty, ", confed-external");
d62a17ae 10410 } else {
05864da7
DS
10411 if (json_paths)
10412 json_object_string_add(
10413 json_peer, "type", "external");
10414 else
10415 vty_out(vty, ", external");
d62a17ae 10416 }
10417 }
05864da7
DS
10418 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10419 if (json_paths) {
10420 json_object_boolean_true_add(json_path, "aggregated");
10421 json_object_boolean_true_add(json_path, "local");
10422 } else {
10423 vty_out(vty, ", aggregated, local");
10424 }
10425 } else if (path->type != ZEBRA_ROUTE_BGP) {
10426 if (json_paths)
10427 json_object_boolean_true_add(json_path, "sourced");
10428 else
10429 vty_out(vty, ", sourced");
10430 } else {
10431 if (json_paths) {
10432 json_object_boolean_true_add(json_path, "sourced");
10433 json_object_boolean_true_add(json_path, "local");
10434 } else {
10435 vty_out(vty, ", sourced, local");
d62a17ae 10436 }
05864da7 10437 }
718e3744 10438
05864da7 10439 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10440 if (json_paths)
05864da7
DS
10441 json_object_boolean_true_add(json_path,
10442 "atomicAggregate");
d62a17ae 10443 else
05864da7
DS
10444 vty_out(vty, ", atomic-aggregate");
10445 }
d62a17ae 10446
05864da7
DS
10447 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10448 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10449 && bgp_path_info_mpath_count(path))) {
10450 if (json_paths)
10451 json_object_boolean_true_add(json_path, "multipath");
10452 else
10453 vty_out(vty, ", multipath");
10454 }
50e05855 10455
05864da7
DS
10456 // Mark the bestpath(s)
10457 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10458 first_as = aspath_get_first_as(attr->aspath);
718e3744 10459
05864da7
DS
10460 if (json_paths) {
10461 if (!json_bestpath)
10462 json_bestpath = json_object_new_object();
10463 json_object_int_add(json_bestpath, "bestpathFromAs",
10464 first_as);
10465 } else {
10466 if (first_as)
10467 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10468 else
05864da7 10469 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10470 }
05864da7 10471 }
718e3744 10472
05864da7
DS
10473 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10474 if (json_paths) {
10475 if (!json_bestpath)
10476 json_bestpath = json_object_new_object();
10477 json_object_boolean_true_add(json_bestpath, "overall");
10478 json_object_string_add(
10479 json_bestpath, "selectionReason",
10480 bgp_path_selection_reason2str(bn->reason));
10481 } else {
10482 vty_out(vty, ", best");
10483 vty_out(vty, " (%s)",
10484 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10485 }
05864da7 10486 }
718e3744 10487
4027d19b 10488 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10489 if (json_paths)
10490 json_object_string_add(
10491 json_path, "rpkiValidationState",
4027d19b 10492 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10493 else
1d327209 10494 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10495 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10496 }
10497
05864da7
DS
10498 if (json_bestpath)
10499 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10500
05864da7
DS
10501 if (!json_paths)
10502 vty_out(vty, "\n");
10503
10504 /* Line 4 display Community */
29e72930 10505 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10506 if (json_paths) {
9a706b42
DA
10507 if (!bgp_attr_get_community(attr)->json)
10508 community_str(bgp_attr_get_community(attr),
10509 true);
10510 json_object_lock(bgp_attr_get_community(attr)->json);
10511 json_object_object_add(
10512 json_path, "community",
10513 bgp_attr_get_community(attr)->json);
05864da7
DS
10514 } else {
10515 vty_out(vty, " Community: %s\n",
9a706b42 10516 bgp_attr_get_community(attr)->str);
d62a17ae 10517 }
05864da7 10518 }
718e3744 10519
05864da7
DS
10520 /* Line 5 display Extended-community */
10521 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10522 if (json_paths) {
10523 json_ext_community = json_object_new_object();
b53e67a3
DA
10524 json_object_string_add(
10525 json_ext_community, "string",
10526 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10527 json_object_object_add(json_path, "extendedCommunity",
10528 json_ext_community);
d62a17ae 10529 } else {
05864da7 10530 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10531 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10532 }
05864da7 10533 }
718e3744 10534
05864da7
DS
10535 /* Line 6 display Large community */
10536 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10537 if (json_paths) {
1bcf3a96
DA
10538 if (!bgp_attr_get_lcommunity(attr)->json)
10539 lcommunity_str(bgp_attr_get_lcommunity(attr),
10540 true);
10541 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10542 json_object_object_add(
10543 json_path, "largeCommunity",
10544 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10545 } else {
10546 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10547 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10548 }
05864da7 10549 }
718e3744 10550
05864da7
DS
10551 /* Line 7 display Originator, Cluster-id */
10552 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10553 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10554 char buf[BUFSIZ] = {0};
10555
05864da7 10556 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10557 if (json_paths)
c949c771
DA
10558 json_object_string_addf(json_path,
10559 "originatorId", "%pI4",
10560 &attr->originator_id);
d62a17ae 10561 else
23d0a753
DA
10562 vty_out(vty, " Originator: %pI4",
10563 &attr->originator_id);
d62a17ae 10564 }
856ca177 10565
05864da7 10566 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10567 struct cluster_list *cluster =
10568 bgp_attr_get_cluster(attr);
05864da7 10569 int i;
d62a17ae 10570
10571 if (json_paths) {
05864da7
DS
10572 json_cluster_list = json_object_new_object();
10573 json_cluster_list_list =
10574 json_object_new_array();
10575
779fee93 10576 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10577 json_string = json_object_new_string(
779fee93
DS
10578 inet_ntop(AF_INET,
10579 &cluster->list[i],
10580 buf, sizeof(buf)));
05864da7
DS
10581 json_object_array_add(
10582 json_cluster_list_list,
10583 json_string);
10584 }
718e3744 10585
05864da7
DS
10586 /*
10587 * struct cluster_list does not have
10588 * "str" variable like aspath and community
10589 * do. Add this someday if someone asks
10590 * for it.
10591 * json_object_string_add(json_cluster_list,
779fee93 10592 * "string", cluster->str);
05864da7
DS
10593 */
10594 json_object_object_add(json_cluster_list,
10595 "list",
10596 json_cluster_list_list);
10597 json_object_object_add(json_path, "clusterList",
10598 json_cluster_list);
0dc8ee70 10599 } else {
05864da7
DS
10600 vty_out(vty, ", Cluster list: ");
10601
779fee93 10602 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10603 vty_out(vty, "%pI4 ",
779fee93 10604 &cluster->list[i]);
05864da7 10605 }
0dc8ee70 10606 }
d62a17ae 10607 }
718e3744 10608
d62a17ae 10609 if (!json_paths)
10610 vty_out(vty, "\n");
05864da7 10611 }
d62a17ae 10612
05864da7 10613 if (path->extra && path->extra->damp_info)
b4f7f45b 10614 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10615
05864da7
DS
10616 /* Remote Label */
10617 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10618 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10619 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10620
05864da7
DS
10621 if (json_paths)
10622 json_object_int_add(json_path, "remoteLabel", label);
10623 else
10624 vty_out(vty, " Remote label: %d\n", label);
10625 }
d62a17ae 10626
e496b420
HS
10627 /* Remote SID */
10628 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10629 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10630 if (json_paths)
10631 json_object_string_add(json_path, "remoteSid", buf);
10632 else
10633 vty_out(vty, " Remote SID: %s\n", buf);
10634 }
10635
05864da7
DS
10636 /* Label Index */
10637 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10638 if (json_paths)
10639 json_object_int_add(json_path, "labelIndex",
10640 attr->label_index);
10641 else
10642 vty_out(vty, " Label Index: %d\n",
10643 attr->label_index);
10644 }
d62a17ae 10645
05864da7
DS
10646 /* Line 8 display Addpath IDs */
10647 if (path->addpath_rx_id
10648 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10649 if (json_paths) {
10650 json_object_int_add(json_path, "addpathRxId",
10651 path->addpath_rx_id);
d62a17ae 10652
05864da7
DS
10653 /* Keep backwards compatibility with the old API
10654 * by putting TX All's ID in the old field
10655 */
10656 json_object_int_add(
10657 json_path, "addpathTxId",
10658 path->tx_addpath
10659 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10660
05864da7
DS
10661 /* ... but create a specific field for each
10662 * strategy
10663 */
10664 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10665 json_object_int_add(
10666 json_path,
10667 bgp_addpath_names(i)->id_json_name,
10668 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10669 }
05864da7
DS
10670 } else {
10671 vty_out(vty, " AddPath ID: RX %u, ",
10672 path->addpath_rx_id);
d62a17ae 10673
05864da7 10674 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10675 }
05864da7 10676 }
520d5d76 10677
05864da7
DS
10678 /* If we used addpath to TX a non-bestpath we need to display
10679 * "Advertised to" on a path-by-path basis
10680 */
10681 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10682 first = 1;
dcc68b5e 10683
05864da7
DS
10684 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10685 addpath_capable =
10686 bgp_addpath_encode_tx(peer, afi, safi);
10687 has_adj = bgp_adj_out_lookup(
10688 peer, path->net,
10689 bgp_addpath_id_for_peer(peer, afi, safi,
10690 &path->tx_addpath));
10691
10692 if ((addpath_capable && has_adj)
10693 || (!addpath_capable && has_adj
10694 && CHECK_FLAG(path->flags,
10695 BGP_PATH_SELECTED))) {
10696 if (json_path && !json_adv_to)
10697 json_adv_to = json_object_new_object();
dcc68b5e 10698
05864da7
DS
10699 route_vty_out_advertised_to(
10700 vty, peer, &first,
10701 " Advertised to:", json_adv_to);
d62a17ae 10702 }
10703 }
718e3744 10704
05864da7
DS
10705 if (json_path) {
10706 if (json_adv_to) {
10707 json_object_object_add(
10708 json_path, "advertisedTo", json_adv_to);
d62a17ae 10709 }
05864da7
DS
10710 } else {
10711 if (!first) {
10712 vty_out(vty, "\n");
d62a17ae 10713 }
10714 }
05864da7 10715 }
b05a1c8b 10716
05864da7
DS
10717 /* Line 9 display Uptime */
10718 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10719 if (json_paths) {
10720 json_last_update = json_object_new_object();
10721 json_object_int_add(json_last_update, "epoch", tbuf);
10722 json_object_string_add(json_last_update, "string",
10723 ctime(&tbuf));
10724 json_object_object_add(json_path, "lastUpdate",
10725 json_last_update);
10726 } else
10727 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10728
05864da7
DS
10729 /* Line 10 display PMSI tunnel attribute, if present */
10730 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10731 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10732 bgp_attr_get_pmsi_tnl_type(attr),
10733 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10734
05864da7
DS
10735 if (json_paths) {
10736 json_pmsi = json_object_new_object();
10737 json_object_string_add(json_pmsi, "tunnelType", str);
10738 json_object_int_add(json_pmsi, "label",
10739 label2vni(&attr->label));
10740 json_object_object_add(json_path, "pmsi", json_pmsi);
10741 } else
10742 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10743 str, label2vni(&attr->label));
d62a17ae 10744 }
f1aa5d8a 10745
848e8cf6
DA
10746 if (path->peer->t_gr_restart &&
10747 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10748 unsigned long gr_remaining =
10749 thread_timer_remain_second(path->peer->t_gr_restart);
10750
10751 if (json_paths) {
10752 json_object_int_add(json_path,
10753 "gracefulRestartSecondsRemaining",
10754 gr_remaining);
10755 } else
10756 vty_out(vty,
10757 " Time until Graceful Restart stale route deleted: %lu\n",
10758 gr_remaining);
10759 }
10760
9a706b42
DA
10761 if (path->peer->t_llgr_stale[afi][safi] &&
10762 bgp_attr_get_community(attr) &&
10763 community_include(bgp_attr_get_community(attr),
10764 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10765 unsigned long llgr_remaining = thread_timer_remain_second(
10766 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10767
48ebba04
DA
10768 if (json_paths) {
10769 json_object_int_add(json_path, "llgrSecondsRemaining",
10770 llgr_remaining);
10771 } else
10772 vty_out(vty,
10773 " Time until Long-lived stale route deleted: %lu\n",
10774 llgr_remaining);
10775 }
10776
92269aa2
DS
10777 /* Output some debug about internal state of the dest flags */
10778 if (json_paths) {
10779 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10780 json_object_boolean_true_add(json_path, "processScheduled");
10781 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10782 json_object_boolean_true_add(json_path, "userCleared");
10783 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10784 json_object_boolean_true_add(json_path, "labelChanged");
10785 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10786 json_object_boolean_true_add(json_path, "registeredForLabel");
10787 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10788 json_object_boolean_true_add(json_path, "selectDefered");
10789 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10790 json_object_boolean_true_add(json_path, "fibInstalled");
10791 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10792 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10793
d62a17ae 10794 if (json_nexthop_global || json_nexthop_ll) {
10795 json_nexthops = json_object_new_array();
f1aa5d8a 10796
d62a17ae 10797 if (json_nexthop_global)
10798 json_object_array_add(json_nexthops,
10799 json_nexthop_global);
f1aa5d8a 10800
d62a17ae 10801 if (json_nexthop_ll)
10802 json_object_array_add(json_nexthops,
10803 json_nexthop_ll);
f1aa5d8a 10804
d62a17ae 10805 json_object_object_add(json_path, "nexthops",
10806 json_nexthops);
10807 }
10808
10809 json_object_object_add(json_path, "peer", json_peer);
10810 json_object_array_add(json_paths, json_path);
05864da7 10811 }
b366b518
BB
10812}
10813
96ade3ed 10814#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10815#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10816#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10817
a4d82a8a 10818static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10819 afi_t afi, safi_t safi, enum bgp_show_type type,
10820 bool use_json);
7f323236
DW
10821static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10822 const char *comstr, int exact, afi_t afi,
96c81f66 10823 safi_t safi, uint16_t show_flags);
d62a17ae 10824
1ae44dfc 10825static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10826 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10827 void *output_arg, const char *rd, int is_last,
96f3485c 10828 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10829 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10830 enum rpki_states rpki_target_state)
d62a17ae 10831{
40381db7 10832 struct bgp_path_info *pi;
9bcb3eef 10833 struct bgp_dest *dest;
2aad8c42
MS
10834 bool header = true;
10835 bool json_detail_header = false;
d62a17ae 10836 int display;
1ae44dfc
LB
10837 unsigned long output_count = 0;
10838 unsigned long total_count = 0;
d62a17ae 10839 struct prefix *p;
d62a17ae 10840 json_object *json_paths = NULL;
10841 int first = 1;
96f3485c
MK
10842 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10843 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10844 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10845
1ae44dfc 10846 if (output_cum && *output_cum != 0)
2aad8c42 10847 header = false;
1ae44dfc 10848
9386b588 10849 if (use_json && !*json_header_depth) {
96f3485c
MK
10850 if (all)
10851 *json_header_depth = 1;
10852 else {
10853 vty_out(vty, "{\n");
10854 *json_header_depth = 2;
10855 }
10856
d62a17ae 10857 vty_out(vty,
23d0a753
DA
10858 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10859 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10860 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10861 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10862 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10863 ? VRF_DEFAULT_NAME
10864 : bgp->name,
10865 table->version, &bgp->router_id,
01eced22 10866 bgp->default_local_pref, bgp->as);
9386b588 10867 if (rd) {
445c2480 10868 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10869 ++*json_header_depth;
10870 }
d62a17ae 10871 }
718e3744 10872
445c2480
DS
10873 if (use_json && rd) {
10874 vty_out(vty, " \"%s\" : { ", rd);
10875 }
10876
2aad8c42
MS
10877 /* Check for 'json detail', where we need header output once per dest */
10878 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10879 type != bgp_show_type_dampend_paths &&
10880 type != bgp_show_type_damp_neighbor &&
10881 type != bgp_show_type_flap_statistics &&
10882 type != bgp_show_type_flap_neighbor)
10883 json_detail_header = true;
10884
d62a17ae 10885 /* Start processing of routes. */
9bcb3eef
DS
10886 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10887 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10888 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10889 bool json_detail = json_detail_header;
b54892e0 10890
9bcb3eef 10891 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10892 if (pi == NULL)
98ce9a06 10893 continue;
d62a17ae 10894
98ce9a06 10895 display = 0;
98ce9a06
DS
10896 if (use_json)
10897 json_paths = json_object_new_array();
10898 else
10899 json_paths = NULL;
d62a17ae 10900
6f94b685 10901 for (; pi; pi = pi->next) {
9a706b42
DA
10902 struct community *picomm = NULL;
10903
10904 picomm = bgp_attr_get_community(pi->attr);
10905
98ce9a06 10906 total_count++;
1e2ce4f1 10907
7d3cae70
DA
10908 if (type == bgp_show_type_prefix_version) {
10909 uint32_t version =
10910 strtoul(output_arg, NULL, 10);
10911 if (dest->version < version)
10912 continue;
10913 }
10914
a70a28a5
DA
10915 if (type == bgp_show_type_community_alias) {
10916 char *alias = output_arg;
10917 char **communities;
10918 int num;
10919 bool found = false;
10920
9a706b42
DA
10921 if (picomm) {
10922 frrstr_split(picomm->str, " ",
10923 &communities, &num);
a70a28a5
DA
10924 for (int i = 0; i < num; i++) {
10925 const char *com2alias =
10926 bgp_community2alias(
10927 communities[i]);
cd9cc0e6
IR
10928 if (!found
10929 && strcmp(alias, com2alias)
10930 == 0)
a70a28a5 10931 found = true;
cd9cc0e6
IR
10932 XFREE(MTYPE_TMP,
10933 communities[i]);
a70a28a5 10934 }
cd9cc0e6 10935 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10936 }
10937
1bcf3a96
DA
10938 if (!found &&
10939 bgp_attr_get_lcommunity(pi->attr)) {
10940 frrstr_split(bgp_attr_get_lcommunity(
10941 pi->attr)
10942 ->str,
a70a28a5
DA
10943 " ", &communities, &num);
10944 for (int i = 0; i < num; i++) {
10945 const char *com2alias =
10946 bgp_community2alias(
10947 communities[i]);
cd9cc0e6
IR
10948 if (!found
10949 && strcmp(alias, com2alias)
10950 == 0)
a70a28a5 10951 found = true;
cd9cc0e6
IR
10952 XFREE(MTYPE_TMP,
10953 communities[i]);
a70a28a5 10954 }
cd9cc0e6 10955 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10956 }
10957
10958 if (!found)
10959 continue;
10960 }
10961
1e2ce4f1
DS
10962 if (type == bgp_show_type_rpki) {
10963 if (dest_p->family == AF_INET
10964 || dest_p->family == AF_INET6)
4027d19b 10965 rpki_curr_state = hook_call(
1e2ce4f1
DS
10966 bgp_rpki_prefix_status,
10967 pi->peer, pi->attr, dest_p);
4027d19b
DS
10968 if (rpki_target_state != RPKI_NOT_BEING_USED
10969 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10970 continue;
10971 }
10972
98ce9a06
DS
10973 if (type == bgp_show_type_flap_statistics
10974 || type == bgp_show_type_flap_neighbor
10975 || type == bgp_show_type_dampend_paths
10976 || type == bgp_show_type_damp_neighbor) {
40381db7 10977 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10978 continue;
10979 }
10980 if (type == bgp_show_type_regexp) {
10981 regex_t *regex = output_arg;
d62a17ae 10982
40381db7 10983 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10984 == REG_NOMATCH)
10985 continue;
10986 }
10987 if (type == bgp_show_type_prefix_list) {
10988 struct prefix_list *plist = output_arg;
d62a17ae 10989
9bcb3eef 10990 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10991 != PREFIX_PERMIT)
10992 continue;
10993 }
10994 if (type == bgp_show_type_filter_list) {
10995 struct as_list *as_list = output_arg;
d62a17ae 10996
40381db7 10997 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10998 != AS_FILTER_PERMIT)
10999 continue;
11000 }
11001 if (type == bgp_show_type_route_map) {
11002 struct route_map *rmap = output_arg;
9b6d8fcf 11003 struct bgp_path_info path;
98ce9a06 11004 struct attr dummy_attr;
b68885f9 11005 route_map_result_t ret;
d62a17ae 11006
6f4f49b2 11007 dummy_attr = *pi->attr;
d62a17ae 11008
40381db7 11009 path.peer = pi->peer;
9b6d8fcf 11010 path.attr = &dummy_attr;
d62a17ae 11011
1782514f 11012 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11013 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11014 if (ret == RMAP_DENYMATCH)
11015 continue;
11016 }
11017 if (type == bgp_show_type_neighbor
11018 || type == bgp_show_type_flap_neighbor
11019 || type == bgp_show_type_damp_neighbor) {
11020 union sockunion *su = output_arg;
11021
40381db7
DS
11022 if (pi->peer == NULL
11023 || pi->peer->su_remote == NULL
11024 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11025 continue;
11026 }
11027 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11028 uint32_t destination;
d62a17ae 11029
9bcb3eef 11030 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11031 if (IN_CLASSC(destination)
9bcb3eef 11032 && dest_p->prefixlen == 24)
98ce9a06
DS
11033 continue;
11034 if (IN_CLASSB(destination)
9bcb3eef 11035 && dest_p->prefixlen == 16)
98ce9a06
DS
11036 continue;
11037 if (IN_CLASSA(destination)
9bcb3eef 11038 && dest_p->prefixlen == 8)
98ce9a06
DS
11039 continue;
11040 }
11041 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11042 p = output_arg;
9bcb3eef 11043 if (!prefix_match(p, dest_p))
98ce9a06
DS
11044 continue;
11045 }
11046 if (type == bgp_show_type_community_all) {
9a706b42 11047 if (!picomm)
98ce9a06
DS
11048 continue;
11049 }
11050 if (type == bgp_show_type_community) {
11051 struct community *com = output_arg;
d62a17ae 11052
9a706b42 11053 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11054 continue;
11055 }
11056 if (type == bgp_show_type_community_exact) {
11057 struct community *com = output_arg;
d62a17ae 11058
9a706b42 11059 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11060 continue;
11061 }
11062 if (type == bgp_show_type_community_list) {
11063 struct community_list *list = output_arg;
d62a17ae 11064
9a706b42 11065 if (!community_list_match(picomm, list))
98ce9a06
DS
11066 continue;
11067 }
a4d82a8a 11068 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11069 struct community_list *list = output_arg;
d62a17ae 11070
9a706b42 11071 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11072 continue;
11073 }
11074 if (type == bgp_show_type_lcommunity) {
11075 struct lcommunity *lcom = output_arg;
d62a17ae 11076
1bcf3a96
DA
11077 if (!bgp_attr_get_lcommunity(pi->attr) ||
11078 !lcommunity_match(
11079 bgp_attr_get_lcommunity(pi->attr),
11080 lcom))
98ce9a06
DS
11081 continue;
11082 }
36a206db 11083
11084 if (type == bgp_show_type_lcommunity_exact) {
11085 struct lcommunity *lcom = output_arg;
11086
1bcf3a96
DA
11087 if (!bgp_attr_get_lcommunity(pi->attr) ||
11088 !lcommunity_cmp(
11089 bgp_attr_get_lcommunity(pi->attr),
11090 lcom))
36a206db 11091 continue;
11092 }
98ce9a06
DS
11093 if (type == bgp_show_type_lcommunity_list) {
11094 struct community_list *list = output_arg;
d62a17ae 11095
1bcf3a96
DA
11096 if (!lcommunity_list_match(
11097 bgp_attr_get_lcommunity(pi->attr),
11098 list))
98ce9a06
DS
11099 continue;
11100 }
36a206db 11101 if (type
11102 == bgp_show_type_lcommunity_list_exact) {
11103 struct community_list *list = output_arg;
11104
11105 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11106 bgp_attr_get_lcommunity(pi->attr),
11107 list))
36a206db 11108 continue;
11109 }
98ce9a06 11110 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11111 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11112 continue;
11113 }
11114 if (type == bgp_show_type_dampend_paths
11115 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11116 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11117 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11118 continue;
11119 }
11120
11121 if (!use_json && header) {
23d0a753
DA
11122 vty_out(vty,
11123 "BGP table version is %" PRIu64
11124 ", local router ID is %pI4, vrf id ",
11125 table->version, &bgp->router_id);
9df8b37c
PZ
11126 if (bgp->vrf_id == VRF_UNKNOWN)
11127 vty_out(vty, "%s", VRFID_NONE_STR);
11128 else
11129 vty_out(vty, "%u", bgp->vrf_id);
11130 vty_out(vty, "\n");
01eced22
AD
11131 vty_out(vty, "Default local pref %u, ",
11132 bgp->default_local_pref);
11133 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11134 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11135 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11136 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11137 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11138 if (type == bgp_show_type_dampend_paths
11139 || type == bgp_show_type_damp_neighbor)
98ce9a06 11140 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11141 else if (type == bgp_show_type_flap_statistics
11142 || type == bgp_show_type_flap_neighbor)
98ce9a06 11143 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11144 else
ae248832
MK
11145 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11146 : BGP_SHOW_HEADER));
2aad8c42
MS
11147 header = false;
11148
11149 } else if (json_detail && json_paths != NULL) {
11150 const struct prefix_rd *prd;
11151 json_object *jtemp;
11152
11153 /* Use common detail header, for most types;
11154 * need a json 'object'.
11155 */
11156
11157 jtemp = json_object_new_object();
11158 prd = bgp_rd_from_dest(dest, safi);
11159
11160 route_vty_out_detail_header(
11161 vty, bgp, dest, prd, table->afi,
11162 safi, jtemp);
11163
11164 json_object_array_add(json_paths, jtemp);
11165
11166 json_detail = false;
d62a17ae 11167 }
2aad8c42 11168
98ce9a06
DS
11169 if (rd != NULL && !display && !output_count) {
11170 if (!use_json)
11171 vty_out(vty,
11172 "Route Distinguisher: %s\n",
11173 rd);
d62a17ae 11174 }
98ce9a06
DS
11175 if (type == bgp_show_type_dampend_paths
11176 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11177 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11178 AFI_IP, safi, use_json,
11179 json_paths);
98ce9a06
DS
11180 else if (type == bgp_show_type_flap_statistics
11181 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11182 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11183 AFI_IP, safi, use_json,
11184 json_paths);
f280c93b
DA
11185 else {
11186 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11187 route_vty_out_detail(
11188 vty, bgp, dest, pi,
11189 family2afi(dest_p->family),
11190 safi, RPKI_NOT_BEING_USED,
11191 json_paths);
11192 else
11193 route_vty_out(vty, dest_p, pi, display,
11194 safi, json_paths, wide);
11195 }
98ce9a06 11196 display++;
d62a17ae 11197 }
11198
98ce9a06
DS
11199 if (display) {
11200 output_count++;
11201 if (!use_json)
11202 continue;
11203
625d2931 11204 /* encode prefix */
9bcb3eef 11205 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11206 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11207
1840384b 11208
b54892e0
DS
11209 bgp_fs_nlri_get_string(
11210 (unsigned char *)
9bcb3eef
DS
11211 dest_p->u.prefix_flowspec.ptr,
11212 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11213 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11214 family2afi(dest_p->u
11215 .prefix_flowspec.family));
625d2931 11216 if (first)
b54892e0 11217 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11218 dest_p->u.prefix_flowspec
b54892e0 11219 .prefixlen);
625d2931 11220 else
b54892e0 11221 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11222 dest_p->u.prefix_flowspec
b54892e0 11223 .prefixlen);
625d2931 11224 } else {
625d2931 11225 if (first)
1b78780b 11226 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11227 else
1b78780b 11228 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11229 }
3757f964 11230 vty_json(vty, json_paths);
449feb8e 11231 json_paths = NULL;
98ce9a06 11232 first = 0;
1f83ed02
DS
11233 } else
11234 json_object_free(json_paths);
98ce9a06
DS
11235 }
11236
1ae44dfc
LB
11237 if (output_cum) {
11238 output_count += *output_cum;
11239 *output_cum = output_count;
11240 }
11241 if (total_cum) {
11242 total_count += *total_cum;
11243 *total_cum = total_count;
11244 }
d62a17ae 11245 if (use_json) {
9386b588 11246 if (rd) {
a4d82a8a 11247 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11248 }
11249 if (is_last) {
a4d82a8a
PZ
11250 unsigned long i;
11251 for (i = 0; i < *json_header_depth; ++i)
11252 vty_out(vty, " } ");
96f3485c
MK
11253 if (!all)
11254 vty_out(vty, "\n");
9386b588 11255 }
d62a17ae 11256 } else {
1ae44dfc
LB
11257 if (is_last) {
11258 /* No route is displayed */
11259 if (output_count == 0) {
11260 if (type == bgp_show_type_normal)
11261 vty_out(vty,
11262 "No BGP prefixes displayed, %ld exist\n",
11263 total_count);
11264 } else
d62a17ae 11265 vty_out(vty,
1ae44dfc
LB
11266 "\nDisplayed %ld routes and %ld total paths\n",
11267 output_count, total_count);
11268 }
d62a17ae 11269 }
718e3744 11270
d62a17ae 11271 return CMD_SUCCESS;
718e3744 11272}
11273
1ae44dfc
LB
11274int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11275 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11276 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11277{
9bcb3eef 11278 struct bgp_dest *dest, *next;
1ae44dfc
LB
11279 unsigned long output_cum = 0;
11280 unsigned long total_cum = 0;
9386b588 11281 unsigned long json_header_depth = 0;
67009e22 11282 struct bgp_table *itable;
0136788c 11283 bool show_msg;
96c81f66 11284 uint16_t show_flags = 0;
0136788c
LB
11285
11286 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11287
96f3485c
MK
11288 if (use_json)
11289 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11290
9bcb3eef
DS
11291 for (dest = bgp_table_top(table); dest; dest = next) {
11292 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11293
9bcb3eef
DS
11294 next = bgp_route_next(dest);
11295 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11296 continue;
67009e22 11297
9bcb3eef 11298 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11299 if (itable != NULL) {
1ae44dfc 11300 struct prefix_rd prd;
06b9f471 11301 char rd[RD_ADDRSTRLEN];
1ae44dfc 11302
9bcb3eef 11303 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11304 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11305 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11306 rd, next == NULL, &output_cum,
11307 &total_cum, &json_header_depth,
1e2ce4f1 11308 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11309 if (next == NULL)
11310 show_msg = false;
1ae44dfc
LB
11311 }
11312 }
0136788c
LB
11313 if (show_msg) {
11314 if (output_cum == 0)
11315 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11316 total_cum);
11317 else
11318 vty_out(vty,
11319 "\nDisplayed %ld routes and %ld total paths\n",
11320 output_cum, total_cum);
11321 }
1ae44dfc
LB
11322 return CMD_SUCCESS;
11323}
2aad8c42 11324
d62a17ae 11325static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11326 enum bgp_show_type type, void *output_arg,
96c81f66 11327 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11328{
d62a17ae 11329 struct bgp_table *table;
9386b588 11330 unsigned long json_header_depth = 0;
96f3485c 11331 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11332
d62a17ae 11333 if (bgp == NULL) {
11334 bgp = bgp_get_default();
11335 }
fee0f4c6 11336
d62a17ae 11337 if (bgp == NULL) {
11338 if (!use_json)
11339 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11340 else
11341 vty_out(vty, "{}\n");
d62a17ae 11342 return CMD_WARNING;
11343 }
4dd6177e 11344
cd8c2a27
MS
11345 /* Labeled-unicast routes live in the unicast table. */
11346 if (safi == SAFI_LABELED_UNICAST)
11347 safi = SAFI_UNICAST;
11348
1ae44dfc 11349 table = bgp->rib[afi][safi];
d62a17ae 11350 /* use MPLS and ENCAP specific shows until they are merged */
11351 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11352 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11353 output_arg, use_json);
d62a17ae 11354 }
dba3c1d3
PG
11355
11356 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11357 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11358 output_arg, use_json,
11359 1, NULL, NULL);
11360 }
fee0f4c6 11361
96f3485c 11362 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11363 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11364 rpki_target_state);
fee0f4c6 11365}
11366
d62a17ae 11367static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11368 safi_t safi, uint16_t show_flags)
f186de26 11369{
d62a17ae 11370 struct listnode *node, *nnode;
11371 struct bgp *bgp;
11372 int is_first = 1;
9f049418 11373 bool route_output = false;
96f3485c 11374 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11375
d62a17ae 11376 if (use_json)
11377 vty_out(vty, "{\n");
9f689658 11378
d62a17ae 11379 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11380 route_output = true;
d62a17ae 11381 if (use_json) {
11382 if (!is_first)
11383 vty_out(vty, ",\n");
11384 else
11385 is_first = 0;
11386
11387 vty_out(vty, "\"%s\":",
11388 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11389 ? VRF_DEFAULT_NAME
d62a17ae 11390 : bgp->name);
11391 } else {
11392 vty_out(vty, "\nInstance %s:\n",
11393 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11394 ? VRF_DEFAULT_NAME
d62a17ae 11395 : bgp->name);
11396 }
11397 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11398 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11399 }
9f689658 11400
d62a17ae 11401 if (use_json)
11402 vty_out(vty, "}\n");
9f049418
DS
11403 else if (!route_output)
11404 vty_out(vty, "%% BGP instance not found\n");
f186de26 11405}
11406
718e3744 11407/* Header of detailed BGP route information */
d62a17ae 11408void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11409 struct bgp_dest *dest,
11410 const struct prefix_rd *prd,
d62a17ae 11411 afi_t afi, safi_t safi, json_object *json)
11412{
40381db7 11413 struct bgp_path_info *pi;
b54892e0 11414 const struct prefix *p;
d62a17ae 11415 struct peer *peer;
11416 struct listnode *node, *nnode;
06b9f471 11417 char buf1[RD_ADDRSTRLEN];
d62a17ae 11418 int count = 0;
11419 int best = 0;
11420 int suppress = 0;
c5f1e1b2
C
11421 int accept_own = 0;
11422 int route_filter_translated_v4 = 0;
11423 int route_filter_v4 = 0;
11424 int route_filter_translated_v6 = 0;
11425 int route_filter_v6 = 0;
11426 int llgr_stale = 0;
11427 int no_llgr = 0;
11428 int accept_own_nexthop = 0;
11429 int blackhole = 0;
d62a17ae 11430 int no_export = 0;
11431 int no_advertise = 0;
11432 int local_as = 0;
c5f1e1b2 11433 int no_peer = 0;
d62a17ae 11434 int first = 1;
11435 int has_valid_label = 0;
11436 mpls_label_t label = 0;
11437 json_object *json_adv_to = NULL;
9bedbb1e 11438
9bcb3eef
DS
11439 p = bgp_dest_get_prefix(dest);
11440 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11441
11442 if (has_valid_label)
9bcb3eef 11443 label = label_pton(&dest->local_label);
d62a17ae 11444
44c69747 11445 if (safi == SAFI_EVPN) {
d62a17ae 11446
44c69747 11447 if (!json) {
2dbe669b 11448 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11449 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11450 : "",
2dbe669b 11451 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11452 } else {
11453 json_object_string_add(json, "rd",
11454 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11455 "");
11456 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11457 }
11458 } else {
11459 if (!json) {
9119ef3a
DA
11460 vty_out(vty,
11461 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11462 "\n",
d62a17ae 11463 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11464 ? prefix_rd2str(prd, buf1,
11465 sizeof(buf1))
11466 : ""),
9119ef3a
DA
11467 safi == SAFI_MPLS_VPN ? ":" : "", p,
11468 dest->version);
cd1964ff 11469
9119ef3a 11470 } else {
67d7e256 11471 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11472 json_object_int_add(json, "version", dest->version);
11473
11474 }
44c69747
LK
11475 }
11476
11477 if (has_valid_label) {
11478 if (json)
11479 json_object_int_add(json, "localLabel", label);
11480 else
d62a17ae 11481 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11482 }
11483
11484 if (!json)
d62a17ae 11485 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11486 vty_out(vty, "not allocated\n");
718e3744 11487
9bcb3eef 11488 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11489 struct community *picomm = NULL;
11490
11491 picomm = bgp_attr_get_community(pi->attr);
11492
d62a17ae 11493 count++;
40381db7 11494 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11495 best = count;
4056a5f6 11496 if (bgp_path_suppressed(pi))
d62a17ae 11497 suppress = 1;
cee9c031 11498
9a706b42 11499 if (!picomm)
cee9c031
QY
11500 continue;
11501
11502 no_advertise += community_include(
9a706b42
DA
11503 picomm, COMMUNITY_NO_ADVERTISE);
11504 no_export +=
11505 community_include(picomm, COMMUNITY_NO_EXPORT);
11506 local_as +=
11507 community_include(picomm, COMMUNITY_LOCAL_AS);
11508 accept_own +=
11509 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11510 route_filter_translated_v4 += community_include(
9a706b42 11511 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11512 route_filter_translated_v6 += community_include(
9a706b42 11513 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11514 route_filter_v4 += community_include(
9a706b42 11515 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11516 route_filter_v6 += community_include(
9a706b42
DA
11517 picomm, COMMUNITY_ROUTE_FILTER_v6);
11518 llgr_stale +=
11519 community_include(picomm, COMMUNITY_LLGR_STALE);
11520 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11521 accept_own_nexthop += community_include(
11522 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11523 blackhole +=
11524 community_include(picomm, COMMUNITY_BLACKHOLE);
11525 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11526 }
718e3744 11527 }
718e3744 11528
d62a17ae 11529 if (!json) {
11530 vty_out(vty, "Paths: (%d available", count);
11531 if (best) {
11532 vty_out(vty, ", best #%d", best);
b84060bb
PG
11533 if (safi == SAFI_UNICAST) {
11534 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11535 vty_out(vty, ", table %s",
11536 VRF_DEFAULT_NAME);
11537 else
11538 vty_out(vty, ", vrf %s",
11539 bgp->name);
11540 }
d62a17ae 11541 } else
11542 vty_out(vty, ", no best path");
11543
c5f1e1b2
C
11544 if (accept_own)
11545 vty_out(vty,
11546 ", accept own local route exported and imported in different VRF");
11547 else if (route_filter_translated_v4)
11548 vty_out(vty,
11549 ", mark translated RTs for VPNv4 route filtering");
11550 else if (route_filter_v4)
11551 vty_out(vty,
11552 ", attach RT as-is for VPNv4 route filtering");
11553 else if (route_filter_translated_v6)
11554 vty_out(vty,
11555 ", mark translated RTs for VPNv6 route filtering");
11556 else if (route_filter_v6)
11557 vty_out(vty,
11558 ", attach RT as-is for VPNv6 route filtering");
11559 else if (llgr_stale)
11560 vty_out(vty,
1479ed2f 11561 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11562 else if (no_llgr)
11563 vty_out(vty,
11564 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11565 else if (accept_own_nexthop)
11566 vty_out(vty,
11567 ", accept local nexthop");
11568 else if (blackhole)
11569 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11570 else if (no_export)
11571 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11572 else if (no_advertise)
11573 vty_out(vty, ", not advertised to any peer");
d62a17ae 11574 else if (local_as)
11575 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11576 else if (no_peer)
11577 vty_out(vty,
11578 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11579
11580 if (suppress)
11581 vty_out(vty,
11582 ", Advertisements suppressed by an aggregate.");
11583 vty_out(vty, ")\n");
11584 }
718e3744 11585
d62a17ae 11586 /* If we are not using addpath then we can display Advertised to and
11587 * that will
11588 * show what peers we advertised the bestpath to. If we are using
11589 * addpath
11590 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11591 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11592 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11593 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11594 if (json && !json_adv_to)
11595 json_adv_to = json_object_new_object();
11596
11597 route_vty_out_advertised_to(
11598 vty, peer, &first,
11599 " Advertised to non peer-group peers:\n ",
11600 json_adv_to);
11601 }
11602 }
11603
11604 if (json) {
11605 if (json_adv_to) {
11606 json_object_object_add(json, "advertisedTo",
11607 json_adv_to);
11608 }
11609 } else {
11610 if (first)
11611 vty_out(vty, " Not advertised to any peer");
11612 vty_out(vty, "\n");
11613 }
11614 }
718e3744 11615}
11616
edfee30d 11617static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11618 struct bgp_dest *bgp_node, struct vty *vty,
11619 struct bgp *bgp, afi_t afi, safi_t safi,
11620 json_object *json, enum bgp_path_type pathtype,
4027d19b 11621 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11622{
11623 struct bgp_path_info *pi;
11624 int header = 1;
11625 char rdbuf[RD_ADDRSTRLEN];
11626 json_object *json_header = NULL;
11627 json_object *json_paths = NULL;
4933eaaf 11628 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11629
9bcb3eef 11630 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11631 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11632
11633 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11634 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11635 pi->peer, pi->attr, p);
4933eaaf 11636
4027d19b
DS
11637 if (rpki_target_state != RPKI_NOT_BEING_USED
11638 && rpki_curr_state != rpki_target_state)
4933eaaf 11639 continue;
44c69747
LK
11640
11641 if (json && !json_paths) {
11642 /* Instantiate json_paths only if path is valid */
11643 json_paths = json_object_new_array();
11644 if (pfx_rd) {
11645 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11646 json_header = json_object_new_object();
11647 } else
11648 json_header = json;
11649 }
11650
11651 if (header) {
11652 route_vty_out_detail_header(
11653 vty, bgp, bgp_node, pfx_rd,
11654 AFI_IP, safi, json_header);
11655 header = 0;
11656 }
11657 (*display)++;
11658
11659 if (pathtype == BGP_PATH_SHOW_ALL
11660 || (pathtype == BGP_PATH_SHOW_BESTPATH
11661 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11662 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11663 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11664 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11665 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11666 safi, rpki_curr_state, json_paths);
44c69747
LK
11667 }
11668
11669 if (json && json_paths) {
11670 json_object_object_add(json_header, "paths", json_paths);
11671
11672 if (pfx_rd)
11673 json_object_object_add(json, rdbuf, json_header);
11674 }
11675}
11676
2aad8c42
MS
11677/*
11678 * Return rd based on safi
11679 */
11680static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11681 safi_t safi)
11682{
11683 switch (safi) {
11684 case SAFI_MPLS_VPN:
11685 case SAFI_ENCAP:
11686 case SAFI_EVPN:
11687 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11688 default:
11689 return NULL;
11690
11691 }
11692}
11693
718e3744 11694/* Display specified route of BGP table. */
d62a17ae 11695static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11696 struct bgp_table *rib, const char *ip_str,
11697 afi_t afi, safi_t safi,
4027d19b 11698 enum rpki_states rpki_target_state,
d62a17ae 11699 struct prefix_rd *prd, int prefix_check,
9f049418 11700 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11701{
11702 int ret;
d62a17ae 11703 int display = 0;
11704 struct prefix match;
9bcb3eef
DS
11705 struct bgp_dest *dest;
11706 struct bgp_dest *rm;
d62a17ae 11707 struct bgp_table *table;
11708 json_object *json = NULL;
11709 json_object *json_paths = NULL;
11710
11711 /* Check IP address argument. */
11712 ret = str2prefix(ip_str, &match);
11713 if (!ret) {
11714 vty_out(vty, "address is malformed\n");
11715 return CMD_WARNING;
11716 }
718e3744 11717
d62a17ae 11718 match.family = afi2family(afi);
b05a1c8b 11719
44c69747 11720 if (use_json)
d62a17ae 11721 json = json_object_new_object();
718e3744 11722
44c69747 11723 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11724 for (dest = bgp_table_top(rib); dest;
11725 dest = bgp_route_next(dest)) {
11726 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11727
9bcb3eef 11728 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11729 continue;
9bcb3eef 11730 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11731 if (!table)
ea47320b 11732 continue;
d62a17ae 11733
4953391b
DA
11734 rm = bgp_node_match(table, &match);
11735 if (rm == NULL)
ea47320b 11736 continue;
d62a17ae 11737
9bcb3eef 11738 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11739 if (prefix_check
b54892e0 11740 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11741 bgp_dest_unlock_node(rm);
ea47320b
DL
11742 continue;
11743 }
d62a17ae 11744
9bcb3eef 11745 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11746 bgp, afi, safi, json, pathtype,
4027d19b 11747 &display, rpki_target_state);
44c69747 11748
9bcb3eef 11749 bgp_dest_unlock_node(rm);
44c69747
LK
11750 }
11751 } else if (safi == SAFI_EVPN) {
9bcb3eef 11752 struct bgp_dest *longest_pfx;
cded3b72 11753 bool is_exact_pfxlen_match = false;
44c69747 11754
9bcb3eef
DS
11755 for (dest = bgp_table_top(rib); dest;
11756 dest = bgp_route_next(dest)) {
11757 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11758
9bcb3eef 11759 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11760 continue;
9bcb3eef 11761 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11762 if (!table)
11763 continue;
11764
11765 longest_pfx = NULL;
cded3b72 11766 is_exact_pfxlen_match = false;
44c69747
LK
11767 /*
11768 * Search through all the prefixes for a match. The
11769 * pfx's are enumerated in ascending order of pfxlens.
11770 * So, the last pfx match is the longest match. Set
11771 * is_exact_pfxlen_match when we get exact pfxlen match
11772 */
11773 for (rm = bgp_table_top(table); rm;
11774 rm = bgp_route_next(rm)) {
b54892e0 11775 const struct prefix *rm_p =
9bcb3eef 11776 bgp_dest_get_prefix(rm);
44c69747
LK
11777 /*
11778 * Get prefixlen of the ip-prefix within type5
11779 * evpn route
11780 */
b54892e0
DS
11781 if (evpn_type5_prefix_match(rm_p, &match)
11782 && rm->info) {
44c69747
LK
11783 longest_pfx = rm;
11784 int type5_pfxlen =
b54892e0
DS
11785 bgp_evpn_get_type5_prefixlen(
11786 rm_p);
44c69747 11787 if (type5_pfxlen == match.prefixlen) {
cded3b72 11788 is_exact_pfxlen_match = true;
9bcb3eef 11789 bgp_dest_unlock_node(rm);
44c69747
LK
11790 break;
11791 }
d62a17ae 11792 }
11793 }
ea47320b 11794
44c69747
LK
11795 if (!longest_pfx)
11796 continue;
11797
11798 if (prefix_check && !is_exact_pfxlen_match)
11799 continue;
11800
11801 rm = longest_pfx;
9bcb3eef 11802 bgp_dest_lock_node(rm);
44c69747 11803
9bcb3eef 11804 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11805 bgp, afi, safi, json, pathtype,
4027d19b 11806 &display, rpki_target_state);
44c69747 11807
9bcb3eef 11808 bgp_dest_unlock_node(rm);
d62a17ae 11809 }
98a9dbc7 11810 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11811 if (use_json)
11812 json_paths = json_object_new_array();
11813
63a0b7a9
PG
11814 display = bgp_flowspec_display_match_per_ip(afi, rib,
11815 &match, prefix_check,
11816 vty,
11817 use_json,
11818 json_paths);
d5f20468
SP
11819 if (use_json) {
11820 if (display)
11821 json_object_object_add(json, "paths",
11822 json_paths);
11823 else
11824 json_object_free(json_paths);
11825 }
d62a17ae 11826 } else {
4953391b
DA
11827 dest = bgp_node_match(rib, &match);
11828 if (dest != NULL) {
9bcb3eef 11829 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11830 if (!prefix_check
9bcb3eef
DS
11831 || dest_p->prefixlen == match.prefixlen) {
11832 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11833 safi, json, pathtype,
4027d19b 11834 &display, rpki_target_state);
d62a17ae 11835 }
11836
9bcb3eef 11837 bgp_dest_unlock_node(dest);
d62a17ae 11838 }
11839 }
e5eee9af 11840
d62a17ae 11841 if (use_json) {
75eeda93 11842 vty_json(vty, json);
d62a17ae 11843 } else {
11844 if (!display) {
11845 vty_out(vty, "%% Network not in table\n");
11846 return CMD_WARNING;
11847 }
11848 }
b05a1c8b 11849
d62a17ae 11850 return CMD_SUCCESS;
718e3744 11851}
11852
fee0f4c6 11853/* Display specified route of Main RIB */
d62a17ae 11854static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11855 afi_t afi, safi_t safi, struct prefix_rd *prd,
11856 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11857 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11858{
9b86009a 11859 if (!bgp) {
d62a17ae 11860 bgp = bgp_get_default();
9b86009a
RW
11861 if (!bgp) {
11862 if (!use_json)
11863 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11864 else
11865 vty_out(vty, "{}\n");
9b86009a
RW
11866 return CMD_WARNING;
11867 }
11868 }
d62a17ae 11869
11870 /* labeled-unicast routes live in the unicast table */
11871 if (safi == SAFI_LABELED_UNICAST)
11872 safi = SAFI_UNICAST;
11873
11874 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11875 afi, safi, rpki_target_state, prd,
8aa22bbb 11876 prefix_check, pathtype, use_json);
d62a17ae 11877}
11878
11879static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11880 struct cmd_token **argv, bool exact, afi_t afi,
11881 safi_t safi, bool uj)
d62a17ae 11882{
11883 struct lcommunity *lcom;
11884 struct buffer *b;
11885 int i;
11886 char *str;
11887 int first = 0;
96c81f66 11888 uint16_t show_flags = 0;
4f28b2b5 11889 int ret;
96f3485c
MK
11890
11891 if (uj)
11892 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11893
11894 b = buffer_new(1024);
11895 for (i = 0; i < argc; i++) {
11896 if (first)
11897 buffer_putc(b, ' ');
11898 else {
11899 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11900 first = 1;
11901 buffer_putstr(b, argv[i]->arg);
11902 }
11903 }
11904 }
11905 buffer_putc(b, '\0');
57d187bc 11906
d62a17ae 11907 str = buffer_getstr(b);
11908 buffer_free(b);
57d187bc 11909
d62a17ae 11910 lcom = lcommunity_str2com(str);
11911 XFREE(MTYPE_TMP, str);
11912 if (!lcom) {
11913 vty_out(vty, "%% Large-community malformed\n");
11914 return CMD_WARNING;
11915 }
57d187bc 11916
4f28b2b5 11917 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11918 (exact ? bgp_show_type_lcommunity_exact
11919 : bgp_show_type_lcommunity),
11920 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11921
11922 lcommunity_free(&lcom);
11923 return ret;
57d187bc
JS
11924}
11925
d62a17ae 11926static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11927 const char *lcom, bool exact, afi_t afi,
11928 safi_t safi, bool uj)
57d187bc 11929{
d62a17ae 11930 struct community_list *list;
96c81f66 11931 uint16_t show_flags = 0;
96f3485c
MK
11932
11933 if (uj)
11934 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11935
57d187bc 11936
e237b0d2 11937 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11938 LARGE_COMMUNITY_LIST_MASTER);
11939 if (list == NULL) {
11940 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11941 lcom);
11942 return CMD_WARNING;
11943 }
57d187bc 11944
36a206db 11945 return bgp_show(vty, bgp, afi, safi,
11946 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11947 : bgp_show_type_lcommunity_list),
1e2ce4f1 11948 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11949}
11950
52951b63
DS
11951DEFUN (show_ip_bgp_large_community_list,
11952 show_ip_bgp_large_community_list_cmd,
77a3a95e 11953 "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
11954 SHOW_STR
11955 IP_STR
11956 BGP_STR
11957 BGP_INSTANCE_HELP_STR
9bedbb1e 11958 BGP_AFI_HELP_STR
4dd6177e 11959 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11960 "Display routes matching the large-community-list\n"
11961 "large-community-list number\n"
11962 "large-community-list name\n"
36a206db 11963 "Exact match of the large-communities\n"
52951b63
DS
11964 JSON_STR)
11965{
d62a17ae 11966 afi_t afi = AFI_IP6;
11967 safi_t safi = SAFI_UNICAST;
11968 int idx = 0;
36a206db 11969 bool exact_match = 0;
4d678463 11970 struct bgp *bgp = NULL;
9f049418 11971 bool uj = use_json(argc, argv);
d62a17ae 11972
ef3364f0
DA
11973 if (uj)
11974 argc--;
4d678463 11975
ef3364f0
DA
11976 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11977 &bgp, uj);
11978 if (!idx)
11979 return CMD_WARNING;
d62a17ae 11980
11981 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11982
11983 const char *clist_number_or_name = argv[++idx]->arg;
11984
11985 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11986 exact_match = 1;
11987
11988 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11989 exact_match, afi, safi, uj);
52951b63
DS
11990}
11991DEFUN (show_ip_bgp_large_community,
11992 show_ip_bgp_large_community_cmd,
36a206db 11993 "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
11994 SHOW_STR
11995 IP_STR
11996 BGP_STR
11997 BGP_INSTANCE_HELP_STR
9bedbb1e 11998 BGP_AFI_HELP_STR
4dd6177e 11999 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12000 "Display routes matching the large-communities\n"
12001 "List of large-community numbers\n"
36a206db 12002 "Exact match of the large-communities\n"
52951b63
DS
12003 JSON_STR)
12004{
d62a17ae 12005 afi_t afi = AFI_IP6;
12006 safi_t safi = SAFI_UNICAST;
12007 int idx = 0;
36a206db 12008 bool exact_match = 0;
4d678463 12009 struct bgp *bgp = NULL;
9f049418 12010 bool uj = use_json(argc, argv);
96c81f66 12011 uint16_t show_flags = 0;
d62a17ae 12012
96f3485c
MK
12013 if (uj) {
12014 argc--;
12015 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12016 }
4d678463 12017
96f3485c
MK
12018 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12019 &bgp, uj);
12020 if (!idx)
12021 return CMD_WARNING;
d62a17ae 12022
36a206db 12023 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12024 if (argv_find(argv, argc, "exact-match", &idx))
12025 exact_match = 1;
12026 return bgp_show_lcommunity(vty, bgp, argc, argv,
12027 exact_match, afi, safi, uj);
12028 } else
d62a17ae 12029 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12030 bgp_show_type_lcommunity_all, NULL, show_flags,
12031 RPKI_NOT_BEING_USED);
52951b63
DS
12032}
12033
71f1613a
DA
12034static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12035 safi_t safi, struct json_object *json_array);
d62a17ae 12036static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12037 safi_t safi, struct json_object *json);
e01ca200 12038
7b2ff250 12039
9ab0cf58
PG
12040DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12041 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12042 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12043 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12044{
12045 bool uj = use_json(argc, argv);
12046 struct bgp *bgp = NULL;
ec76a1d1
DA
12047 safi_t safi = SAFI_UNICAST;
12048 afi_t afi = AFI_IP6;
4265b261 12049 int idx = 0;
6c9d22e2
PG
12050 struct json_object *json_all = NULL;
12051 struct json_object *json_afi_safi = NULL;
4265b261
PG
12052
12053 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12054 &bgp, false);
71f1613a 12055 if (!idx)
4265b261 12056 return CMD_WARNING;
6c9d22e2 12057
4265b261 12058 if (uj)
6c9d22e2 12059 json_all = json_object_new_object();
4265b261 12060
9ab0cf58
PG
12061 FOREACH_AFI_SAFI (afi, safi) {
12062 /*
12063 * So limit output to those afi/safi pairs that
12064 * actually have something interesting in them
12065 */
12066 if (strmatch(get_afi_safi_str(afi, safi, true),
12067 "Unknown")) {
12068 continue;
12069 }
12070 if (uj) {
12071 json_afi_safi = json_object_new_array();
12072 json_object_object_add(
12073 json_all,
12074 get_afi_safi_str(afi, safi, true),
12075 json_afi_safi);
12076 } else {
12077 json_afi_safi = NULL;
6c9d22e2 12078 }
9ab0cf58
PG
12079
12080 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12081 }
6c9d22e2 12082
3757f964
DA
12083 if (uj)
12084 vty_json(vty, json_all);
6c9d22e2 12085
4265b261
PG
12086 return CMD_SUCCESS;
12087}
12088
7b2ff250 12089/* BGP route print out function without JSON */
14718643
PG
12090DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12091 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12092 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12093 SHOW_STR
12094 IP_STR
12095 BGP_STR
12096 BGP_INSTANCE_HELP_STR
12097 L2VPN_HELP_STR
12098 EVPN_HELP_STR
12099 "BGP RIB advertisement statistics\n"
12100 JSON_STR)
12101{
ec76a1d1
DA
12102 afi_t afi = AFI_IP6;
12103 safi_t safi = SAFI_UNICAST;
14718643
PG
12104 struct bgp *bgp = NULL;
12105 int idx = 0, ret;
12106 bool uj = use_json(argc, argv);
12107 struct json_object *json_afi_safi = NULL, *json = NULL;
12108
12109 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12110 &bgp, false);
12111 if (!idx)
12112 return CMD_WARNING;
12113
12114 if (uj)
12115 json_afi_safi = json_object_new_array();
12116 else
12117 json_afi_safi = NULL;
12118
12119 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12120
12121 if (uj) {
12122 json = json_object_new_object();
12123 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12124 json_afi_safi);
3757f964 12125 vty_json(vty, json);
14718643
PG
12126 }
12127 return ret;
12128}
12129
893cccd0 12130/* BGP route print out function without JSON */
9ab0cf58
PG
12131DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12132 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12133 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12134 "]]\
893cccd0 12135 statistics [json]",
9ab0cf58
PG
12136 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12137 BGP_SAFI_WITH_LABEL_HELP_STR
12138 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12139{
ec76a1d1
DA
12140 afi_t afi = AFI_IP6;
12141 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12142 struct bgp *bgp = NULL;
12143 int idx = 0, ret;
12144 bool uj = use_json(argc, argv);
6c9d22e2 12145 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12146
12147 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12148 &bgp, false);
12149 if (!idx)
12150 return CMD_WARNING;
6c9d22e2 12151
893cccd0 12152 if (uj)
6c9d22e2
PG
12153 json_afi_safi = json_object_new_array();
12154 else
12155 json_afi_safi = NULL;
12156
12157 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12158
12159 if (uj) {
12160 json = json_object_new_object();
12161 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12162 json_afi_safi);
3757f964 12163 vty_json(vty, json);
893cccd0
PG
12164 }
12165 return ret;
893cccd0 12166}
7b2ff250 12167
fe0f234d 12168DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12169 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12170 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12171 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12172 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12173 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12174 "Display the entries for all address families\n"
9ab0cf58
PG
12175 "Display detailed information about dampening\n"
12176 "Display detail of configured dampening parameters\n"
fe0f234d 12177 JSON_STR)
718e3744 12178{
d62a17ae 12179 afi_t afi = AFI_IP6;
12180 safi_t safi = SAFI_UNICAST;
d62a17ae 12181 struct bgp *bgp = NULL;
12182 int idx = 0;
96c81f66 12183 uint16_t show_flags = 0;
fe0f234d
RW
12184 bool uj = use_json(argc, argv);
12185
12186 if (uj) {
12187 argc--;
12188 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12189 }
96f3485c
MK
12190
12191 /* [<ipv4|ipv6> [all]] */
12192 if (all) {
12193 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12194 if (argv_find(argv, argc, "ipv4", &idx))
12195 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12196
12197 if (argv_find(argv, argc, "ipv6", &idx))
12198 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12199 }
d62a17ae 12200
12201 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12202 &bgp, false);
d62a17ae 12203 if (!idx)
12204 return CMD_WARNING;
12205
fe0f234d 12206 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12207}
12208
fe0f234d
RW
12209/* BGP route print out function */
12210DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12211 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12212 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12213 "]]\
96f3485c 12214 [all$all]\
cf4898bc
QY
12215 [cidr-only\
12216 |dampening <flap-statistics|dampened-paths>\
12217 |community [AA:NN|local-AS|no-advertise|no-export\
12218 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12219 |accept-own|accept-own-nexthop|route-filter-v6\
12220 |route-filter-v4|route-filter-translated-v6\
12221 |route-filter-translated-v4] [exact-match]\
70799983 12222 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12223 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12224 |prefix-list WORD\
bf1a944a 12225 |route-map WORD\
1e2ce4f1 12226 |rpki <invalid|valid|notfound>\
7d3cae70 12227 |version (1-4294967295)\
b4ad2fae 12228 |alias ALIAS_NAME\
39c3c736
RW
12229 |A.B.C.D/M longer-prefixes\
12230 |X:X::X:X/M longer-prefixes\
f280c93b 12231 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12232 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12233 BGP_SAFI_WITH_LABEL_HELP_STR
12234 "Display the entries for all address families\n"
12235 "Display only routes with non-natural netmasks\n"
12236 "Display detailed information about dampening\n"
12237 "Display flap statistics of routes\n"
12238 "Display paths suppressed due to dampening\n"
12239 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12240 "Do not send outside local AS (well-known community)\n"
12241 "Do not advertise to any peer (well-known community)\n"
12242 "Do not export to next AS (well-known community)\n"
12243 "Graceful shutdown (well-known community)\n"
12244 "Do not export to any peer (well-known community)\n"
12245 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12246 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12247 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12248 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12249 "Should accept VPN route with local nexthop (well-known community)\n"
12250 "RT VPNv6 route filtering (well-known community)\n"
12251 "RT VPNv4 route filtering (well-known community)\n"
12252 "RT translated VPNv6 route filtering (well-known community)\n"
12253 "RT translated VPNv4 route filtering (well-known community)\n"
12254 "Exact match of the communities\n"
70799983
RW
12255 "Community-list number\n"
12256 "Community-list name\n"
12257 "Display routes matching the community-list\n"
12258 "Exact match of the communities\n"
a7129347
RW
12259 "Display routes conforming to the filter-list\n"
12260 "Regular expression access list name\n"
6deaf579
RW
12261 "Display routes conforming to the prefix-list\n"
12262 "Prefix-list name\n"
bf1a944a
RW
12263 "Display routes matching the route-map\n"
12264 "A route-map to match on\n"
a70a28a5
DA
12265 "RPKI route types\n"
12266 "A valid path as determined by rpki\n"
12267 "A invalid path as determined by rpki\n"
12268 "A path that has no rpki data\n"
12269 "Display prefixes with matching version numbers\n"
12270 "Version number and above\n"
12271 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12272 "BGP community alias\n"
12273 "IPv4 prefix\n"
12274 "Display route and more specific routes\n"
12275 "IPv6 prefix\n"
12276 "Display route and more specific routes\n"
12277 JSON_STR
a70a28a5
DA
12278 "Display detailed version of JSON output\n"
12279 "Increase table width for longer prefixes\n")
7b2ff250
DW
12280{
12281 afi_t afi = AFI_IP6;
12282 safi_t safi = SAFI_UNICAST;
12283 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12284 void *output_arg = NULL;
7b2ff250
DW
12285 struct bgp *bgp = NULL;
12286 int idx = 0;
d0086e8e 12287 int exact_match = 0;
96f3485c
MK
12288 char *community = NULL;
12289 bool first = true;
96c81f66 12290 uint16_t show_flags = 0;
4027d19b 12291 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12292 struct prefix p;
96f3485c
MK
12293
12294 if (uj) {
9f049418 12295 argc--;
96f3485c
MK
12296 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12297 }
12298
f280c93b
DA
12299 if (detail)
12300 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12301
96f3485c
MK
12302 /* [<ipv4|ipv6> [all]] */
12303 if (all) {
12304 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12305
12306 if (argv_find(argv, argc, "ipv4", &idx))
12307 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12308
12309 if (argv_find(argv, argc, "ipv6", &idx))
12310 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12311 }
12312
12313 if (wide)
12314 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12315
12316 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12317 &bgp, uj);
7b2ff250
DW
12318 if (!idx)
12319 return CMD_WARNING;
12320
7b2ff250 12321 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12322 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12323
12324 if (argv_find(argv, argc, "dampening", &idx)) {
12325 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12326 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12327 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12328 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12329 }
12330
12331 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12332 char *maybecomm = NULL;
d0086e8e 12333
79bc257a
RW
12334 if (idx + 1 < argc) {
12335 if (argv[idx + 1]->type == VARIABLE_TKN)
12336 maybecomm = argv[idx + 1]->arg;
12337 else
12338 maybecomm = argv[idx + 1]->text;
12339 }
12340
cf4898bc
QY
12341 if (maybecomm && !strmatch(maybecomm, "json")
12342 && !strmatch(maybecomm, "exact-match"))
12343 community = maybecomm;
d0086e8e 12344
cf4898bc
QY
12345 if (argv_find(argv, argc, "exact-match", &idx))
12346 exact_match = 1;
d0086e8e 12347
96f3485c
MK
12348 if (!community)
12349 sh_type = bgp_show_type_community_all;
12350 }
12351
70799983
RW
12352 if (argv_find(argv, argc, "community-list", &idx)) {
12353 const char *clist_number_or_name = argv[++idx]->arg;
12354 struct community_list *list;
12355
12356 if (argv_find(argv, argc, "exact-match", &idx))
12357 exact_match = 1;
12358
12359 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12360 COMMUNITY_LIST_MASTER);
12361 if (list == NULL) {
12362 vty_out(vty,
12363 "%% %s is not a valid community-list name\n",
12364 clist_number_or_name);
12365 return CMD_WARNING;
12366 }
12367
12368 if (exact_match)
12369 sh_type = bgp_show_type_community_list_exact;
12370 else
12371 sh_type = bgp_show_type_community_list;
12372 output_arg = list;
12373 }
12374
a7129347
RW
12375 if (argv_find(argv, argc, "filter-list", &idx)) {
12376 const char *filter = argv[++idx]->arg;
12377 struct as_list *as_list;
12378
12379 as_list = as_list_lookup(filter);
12380 if (as_list == NULL) {
12381 vty_out(vty,
12382 "%% %s is not a valid AS-path access-list name\n",
12383 filter);
12384 return CMD_WARNING;
12385 }
12386
12387 sh_type = bgp_show_type_filter_list;
12388 output_arg = as_list;
12389 }
12390
6deaf579
RW
12391 if (argv_find(argv, argc, "prefix-list", &idx)) {
12392 const char *prefix_list_str = argv[++idx]->arg;
12393 struct prefix_list *plist;
12394
12395 plist = prefix_list_lookup(afi, prefix_list_str);
12396 if (plist == NULL) {
12397 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12398 prefix_list_str);
12399 return CMD_WARNING;
12400 }
12401
12402 sh_type = bgp_show_type_prefix_list;
12403 output_arg = plist;
12404 }
12405
bf1a944a
RW
12406 if (argv_find(argv, argc, "route-map", &idx)) {
12407 const char *rmap_str = argv[++idx]->arg;
12408 struct route_map *rmap;
12409
12410 rmap = route_map_lookup_by_name(rmap_str);
12411 if (!rmap) {
12412 vty_out(vty, "%% %s is not a valid route-map name\n",
12413 rmap_str);
12414 return CMD_WARNING;
12415 }
12416
12417 sh_type = bgp_show_type_route_map;
12418 output_arg = rmap;
12419 }
12420
1e2ce4f1
DS
12421 if (argv_find(argv, argc, "rpki", &idx)) {
12422 sh_type = bgp_show_type_rpki;
12423 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12424 rpki_target_state = RPKI_VALID;
1e2ce4f1 12425 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12426 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12427 }
12428
7d3cae70
DA
12429 /* Display prefixes with matching version numbers */
12430 if (argv_find(argv, argc, "version", &idx)) {
12431 sh_type = bgp_show_type_prefix_version;
2391833e 12432 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12433 }
12434
a70a28a5
DA
12435 /* Display prefixes with matching BGP community alias */
12436 if (argv_find(argv, argc, "alias", &idx)) {
12437 sh_type = bgp_show_type_community_alias;
2391833e 12438 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12439 }
12440
39c3c736
RW
12441 /* prefix-longer */
12442 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12443 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12444 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12445
12446 if (!str2prefix(prefix_str, &p)) {
12447 vty_out(vty, "%% Malformed Prefix\n");
12448 return CMD_WARNING;
12449 }
12450
12451 sh_type = bgp_show_type_prefix_longer;
12452 output_arg = &p;
a70a28a5
DA
12453 }
12454
96f3485c
MK
12455 if (!all) {
12456 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12457 if (community)
12458 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12459 exact_match, afi, safi,
12460 show_flags);
2391833e 12461 else
a70a28a5 12462 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12463 output_arg, show_flags,
a70a28a5 12464 rpki_target_state);
96f3485c
MK
12465 } else {
12466 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12467 * AFI_IP6 */
12468
12469 if (uj)
12470 vty_out(vty, "{\n");
12471
12472 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12473 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12474 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12475 ? AFI_IP
12476 : AFI_IP6;
12477 FOREACH_SAFI (safi) {
96f3485c
MK
12478 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12479 continue;
12480
12481 if (uj) {
12482 if (first)
12483 first = false;
12484 else
12485 vty_out(vty, ",\n");
12486 vty_out(vty, "\"%s\":{\n",
12487 get_afi_safi_str(afi, safi,
12488 true));
12489 } else
12490 vty_out(vty,
12491 "\nFor address family: %s\n",
12492 get_afi_safi_str(afi, safi,
12493 false));
12494
12495 if (community)
12496 bgp_show_community(vty, bgp, community,
12497 exact_match, afi,
12498 safi, show_flags);
12499 else
12500 bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12501 output_arg, show_flags,
4027d19b 12502 rpki_target_state);
96f3485c
MK
12503 if (uj)
12504 vty_out(vty, "}\n");
12505 }
12506 } else {
12507 /* show <ip> bgp all: for each AFI and SAFI*/
12508 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12509 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12510 continue;
12511
12512 if (uj) {
12513 if (first)
12514 first = false;
12515 else
12516 vty_out(vty, ",\n");
d0086e8e 12517
96f3485c
MK
12518 vty_out(vty, "\"%s\":{\n",
12519 get_afi_safi_str(afi, safi,
12520 true));
12521 } else
12522 vty_out(vty,
12523 "\nFor address family: %s\n",
12524 get_afi_safi_str(afi, safi,
12525 false));
12526
12527 if (community)
12528 bgp_show_community(vty, bgp, community,
12529 exact_match, afi,
12530 safi, show_flags);
12531 else
12532 bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12533 output_arg, show_flags,
4027d19b 12534 rpki_target_state);
96f3485c
MK
12535 if (uj)
12536 vty_out(vty, "}\n");
12537 }
12538 }
12539 if (uj)
12540 vty_out(vty, "}\n");
12541 }
12542 return CMD_SUCCESS;
a636c635 12543}
47fc97cc 12544
718e3744 12545DEFUN (show_ip_bgp_route,
12546 show_ip_bgp_route_cmd,
8aa22bbb 12547 "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 12548 SHOW_STR
12549 IP_STR
12550 BGP_STR
a636c635 12551 BGP_INSTANCE_HELP_STR
4f280b15 12552 BGP_AFI_HELP_STR
4dd6177e 12553 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12554 "Network in the BGP routing table to display\n"
0c7b1b01 12555 "IPv4 prefix\n"
8c3deaae 12556 "Network in the BGP routing table to display\n"
0c7b1b01 12557 "IPv6 prefix\n"
4092b06c 12558 "Display only the bestpath\n"
b05a1c8b 12559 "Display only multipaths\n"
8aa22bbb
DS
12560 "Display only paths that match the specified rpki state\n"
12561 "A valid path as determined by rpki\n"
12562 "A invalid path as determined by rpki\n"
12563 "A path that has no rpki data\n"
9973d184 12564 JSON_STR)
4092b06c 12565{
d62a17ae 12566 int prefix_check = 0;
ae19d7dd 12567
d62a17ae 12568 afi_t afi = AFI_IP6;
12569 safi_t safi = SAFI_UNICAST;
12570 char *prefix = NULL;
12571 struct bgp *bgp = NULL;
12572 enum bgp_path_type path_type;
9f049418 12573 bool uj = use_json(argc, argv);
b05a1c8b 12574
d62a17ae 12575 int idx = 0;
ae19d7dd 12576
d62a17ae 12577 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12578 &bgp, uj);
d62a17ae 12579 if (!idx)
12580 return CMD_WARNING;
c41247f5 12581
d62a17ae 12582 if (!bgp) {
12583 vty_out(vty,
12584 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12585 return CMD_WARNING;
12586 }
a636c635 12587
d62a17ae 12588 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12589 if (argv_find(argv, argc, "A.B.C.D", &idx)
12590 || argv_find(argv, argc, "X:X::X:X", &idx))
12591 prefix_check = 0;
12592 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12593 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12594 prefix_check = 1;
12595
12596 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12597 && afi != AFI_IP6) {
12598 vty_out(vty,
12599 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12600 return CMD_WARNING;
12601 }
12602 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12603 && afi != AFI_IP) {
12604 vty_out(vty,
12605 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12606 return CMD_WARNING;
12607 }
12608
12609 prefix = argv[idx]->arg;
12610
12611 /* [<bestpath|multipath>] */
12612 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12613 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12614 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12615 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12616 else
360660c6 12617 path_type = BGP_PATH_SHOW_ALL;
a636c635 12618
d62a17ae 12619 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12620 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12621}
12622
8c3deaae
QY
12623DEFUN (show_ip_bgp_regexp,
12624 show_ip_bgp_regexp_cmd,
3e5b31b3 12625 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12626 SHOW_STR
12627 IP_STR
12628 BGP_STR
b00b230a 12629 BGP_INSTANCE_HELP_STR
4f280b15 12630 BGP_AFI_HELP_STR
4dd6177e 12631 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12632 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12633 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12634 JSON_STR)
8c3deaae 12635{
d62a17ae 12636 afi_t afi = AFI_IP6;
12637 safi_t safi = SAFI_UNICAST;
12638 struct bgp *bgp = NULL;
3e5b31b3
DA
12639 bool uj = use_json(argc, argv);
12640 char *regstr = NULL;
8c3deaae 12641
d62a17ae 12642 int idx = 0;
12643 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12644 &bgp, false);
d62a17ae 12645 if (!idx)
12646 return CMD_WARNING;
8c3deaae 12647
d62a17ae 12648 // get index of regex
3e5b31b3
DA
12649 if (argv_find(argv, argc, "REGEX", &idx))
12650 regstr = argv[idx]->arg;
8c3deaae 12651
5f71d11c 12652 assert(regstr);
3e5b31b3
DA
12653 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12654 bgp_show_type_regexp, uj);
8c3deaae
QY
12655}
12656
ae248832 12657DEFPY (show_ip_bgp_instance_all,
a636c635 12658 show_ip_bgp_instance_all_cmd,
ae248832 12659 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12660 SHOW_STR
a636c635 12661 IP_STR
4092b06c 12662 BGP_STR
a636c635 12663 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12664 BGP_AFI_HELP_STR
4dd6177e 12665 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12666 JSON_STR
12667 "Increase table width for longer prefixes\n")
4092b06c 12668{
54d05dea 12669 afi_t afi = AFI_IP6;
d62a17ae 12670 safi_t safi = SAFI_UNICAST;
12671 struct bgp *bgp = NULL;
d62a17ae 12672 int idx = 0;
96c81f66 12673 uint16_t show_flags = 0;
ae19d7dd 12674
96f3485c 12675 if (uj) {
d62a17ae 12676 argc--;
96f3485c
MK
12677 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12678 }
12679
12680 if (wide)
12681 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12682
9f049418
DS
12683 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12684 &bgp, uj);
12685 if (!idx)
12686 return CMD_WARNING;
12687
96f3485c 12688 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12689 return CMD_SUCCESS;
e3e29b32
LB
12690}
12691
a4d82a8a 12692static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12693 afi_t afi, safi_t safi, enum bgp_show_type type,
12694 bool use_json)
718e3744 12695{
d62a17ae 12696 regex_t *regex;
12697 int rc;
96c81f66 12698 uint16_t show_flags = 0;
96f3485c
MK
12699
12700 if (use_json)
12701 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12702
c3900853 12703 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12704 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12705 regstr);
12706 return CMD_WARNING_CONFIG_FAILED;
12707 }
12708
d62a17ae 12709 regex = bgp_regcomp(regstr);
12710 if (!regex) {
12711 vty_out(vty, "Can't compile regexp %s\n", regstr);
12712 return CMD_WARNING;
12713 }
a636c635 12714
1e2ce4f1
DS
12715 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12716 RPKI_NOT_BEING_USED);
d62a17ae 12717 bgp_regex_free(regex);
12718 return rc;
e3e29b32
LB
12719}
12720
7f323236
DW
12721static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12722 const char *comstr, int exact, afi_t afi,
96c81f66 12723 safi_t safi, uint16_t show_flags)
d62a17ae 12724{
12725 struct community *com;
d62a17ae 12726 int ret = 0;
12727
7f323236 12728 com = community_str2com(comstr);
d62a17ae 12729 if (!com) {
7f323236 12730 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12731 return CMD_WARNING;
12732 }
12733
12734 ret = bgp_show(vty, bgp, afi, safi,
12735 (exact ? bgp_show_type_community_exact
12736 : bgp_show_type_community),
1e2ce4f1 12737 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12738 community_free(&com);
46c3ce83 12739
d62a17ae 12740 return ret;
718e3744 12741}
12742
d62a17ae 12743enum bgp_stats {
12744 BGP_STATS_MAXBITLEN = 0,
12745 BGP_STATS_RIB,
12746 BGP_STATS_PREFIXES,
12747 BGP_STATS_TOTPLEN,
12748 BGP_STATS_UNAGGREGATEABLE,
12749 BGP_STATS_MAX_AGGREGATEABLE,
12750 BGP_STATS_AGGREGATES,
12751 BGP_STATS_SPACE,
12752 BGP_STATS_ASPATH_COUNT,
12753 BGP_STATS_ASPATH_MAXHOPS,
12754 BGP_STATS_ASPATH_TOTHOPS,
12755 BGP_STATS_ASPATH_MAXSIZE,
12756 BGP_STATS_ASPATH_TOTSIZE,
12757 BGP_STATS_ASN_HIGHEST,
12758 BGP_STATS_MAX,
a636c635 12759};
2815e61f 12760
9ab0cf58 12761#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12762#define TABLE_STATS_IDX_JSON 1
12763
12764static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12765 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12766 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12767 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12768 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12769 "unaggregateablePrefixes"},
12770 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12771 "maximumAggregateablePrefixes"},
12772 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12773 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12774 [BGP_STATS_SPACE] = {"Address space advertised",
12775 "addressSpaceAdvertised"},
9ab0cf58
PG
12776 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12777 "advertisementsWithPaths"},
12778 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12779 "longestAsPath"},
12780 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12781 "largestAsPath"},
12782 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12783 "averageAsPathLengthHops"},
12784 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12785 "averageAsPathSizeBytes"},
12786 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12787 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12788};
2815e61f 12789
d62a17ae 12790struct bgp_table_stats {
12791 struct bgp_table *table;
12792 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12793 double total_space;
ff7924f6
PJ
12794};
12795
9bcb3eef 12796static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12797 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12798{
9bcb3eef 12799 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12800 struct bgp_path_info *pi;
b54892e0 12801 const struct prefix *rn_p;
d62a17ae 12802
9bcb3eef 12803 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12804 return;
d62a17ae 12805
9bcb3eef 12806 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12807 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12808 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12809
9c14ec72 12810 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12811 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12812 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12813
9bcb3eef 12814 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12815 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12816 /* announced address space */
12817 if (space)
b54892e0 12818 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12819 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12820 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12821
9c14ec72 12822
9bcb3eef 12823 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12824 ts->counts[BGP_STATS_RIB]++;
12825
05864da7
DS
12826 if (CHECK_FLAG(pi->attr->flag,
12827 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12828 ts->counts[BGP_STATS_AGGREGATES]++;
12829
12830 /* as-path stats */
05864da7 12831 if (pi->attr->aspath) {
9c14ec72
RW
12832 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12833 unsigned int size = aspath_size(pi->attr->aspath);
12834 as_t highest = aspath_highest(pi->attr->aspath);
12835
12836 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12837
12838 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12839 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12840
12841 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12842 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12843
12844 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12845 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12846 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12847 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12848 }
12849 }
12850}
12851
cc9f21da 12852static void bgp_table_stats_walker(struct thread *t)
9c14ec72 12853{
9bcb3eef
DS
12854 struct bgp_dest *dest, *ndest;
12855 struct bgp_dest *top;
9c14ec72
RW
12856 struct bgp_table_stats *ts = THREAD_ARG(t);
12857 unsigned int space = 0;
12858
12859 if (!(top = bgp_table_top(ts->table)))
cc9f21da 12860 return;
9c14ec72
RW
12861
12862 switch (ts->table->afi) {
12863 case AFI_IP:
12864 space = IPV4_MAX_BITLEN;
12865 break;
12866 case AFI_IP6:
12867 space = IPV6_MAX_BITLEN;
12868 break;
3ba7b4af
TA
12869 case AFI_L2VPN:
12870 space = EVPN_ROUTE_PREFIXLEN;
12871 break;
9c14ec72 12872 default:
cc9f21da 12873 return;
9c14ec72
RW
12874 }
12875
12876 ts->counts[BGP_STATS_MAXBITLEN] = space;
12877
9bcb3eef 12878 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12879 if (ts->table->safi == SAFI_MPLS_VPN
12880 || ts->table->safi == SAFI_ENCAP
12881 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12882 struct bgp_table *table;
12883
9bcb3eef 12884 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12885 if (!table)
12886 continue;
12887
12888 top = bgp_table_top(table);
9bcb3eef
DS
12889 for (ndest = bgp_table_top(table); ndest;
12890 ndest = bgp_route_next(ndest))
12891 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12892 } else {
9bcb3eef 12893 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12894 }
12895 }
2815e61f 12896}
ff7924f6 12897
71f1613a
DA
12898static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12899 struct json_object *json_array)
12900{
12901 struct listnode *node, *nnode;
12902 struct bgp *bgp;
12903
12904 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12905 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12906}
12907
12908static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12909 safi_t safi, struct json_object *json_array)
2815e61f 12910{
d62a17ae 12911 struct bgp_table_stats ts;
12912 unsigned int i;
893cccd0
PG
12913 int ret = CMD_SUCCESS;
12914 char temp_buf[20];
6c9d22e2
PG
12915 struct json_object *json = NULL;
12916
12917 if (json_array)
12918 json = json_object_new_object();
019386c2 12919
d62a17ae 12920 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12921 char warning_msg[50];
12922
12923 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12924 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12925 safi);
6c9d22e2
PG
12926
12927 if (!json)
893cccd0
PG
12928 vty_out(vty, "%s\n", warning_msg);
12929 else
9ab0cf58 12930 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12931
893cccd0
PG
12932 ret = CMD_WARNING;
12933 goto end_table_stats;
d62a17ae 12934 }
019386c2 12935
893cccd0 12936 if (!json)
5290ceab
DA
12937 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12938 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12939 else
12940 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12941
d62a17ae 12942 /* labeled-unicast routes live in the unicast table */
12943 if (safi == SAFI_LABELED_UNICAST)
12944 safi = SAFI_UNICAST;
019386c2 12945
d62a17ae 12946 memset(&ts, 0, sizeof(ts));
12947 ts.table = bgp->rib[afi][safi];
12948 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12949
d62a17ae 12950 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12951 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12952 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12953 continue;
12954
12955 switch (i) {
d62a17ae 12956 case BGP_STATS_ASPATH_TOTHOPS:
12957 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12958 if (!json) {
9ab0cf58
PG
12959 snprintf(
12960 temp_buf, sizeof(temp_buf), "%12.2f",
12961 ts.counts[i]
12962 ? (float)ts.counts[i]
12963 / (float)ts.counts
12964 [BGP_STATS_ASPATH_COUNT]
12965 : 0);
893cccd0 12966 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12967 table_stats_strs[i]
12968 [TABLE_STATS_IDX_VTY],
893cccd0 12969 temp_buf);
9ab0cf58
PG
12970 } else {
12971 json_object_double_add(
12972 json,
12973 table_stats_strs[i]
12974 [TABLE_STATS_IDX_JSON],
12975 ts.counts[i]
12976 ? (double)ts.counts[i]
12977 / (double)ts.counts
d62a17ae 12978 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12979 : 0);
12980 }
d62a17ae 12981 break;
12982 case BGP_STATS_TOTPLEN:
6c9d22e2 12983 if (!json) {
9ab0cf58
PG
12984 snprintf(
12985 temp_buf, sizeof(temp_buf), "%12.2f",
12986 ts.counts[i]
12987 ? (float)ts.counts[i]
12988 / (float)ts.counts
12989 [BGP_STATS_PREFIXES]
12990 : 0);
893cccd0 12991 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12992 table_stats_strs[i]
12993 [TABLE_STATS_IDX_VTY],
893cccd0 12994 temp_buf);
9ab0cf58
PG
12995 } else {
12996 json_object_double_add(
12997 json,
12998 table_stats_strs[i]
12999 [TABLE_STATS_IDX_JSON],
13000 ts.counts[i]
13001 ? (double)ts.counts[i]
13002 / (double)ts.counts
d62a17ae 13003 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13004 : 0);
13005 }
d62a17ae 13006 break;
13007 case BGP_STATS_SPACE:
6c9d22e2
PG
13008 if (!json) {
13009 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13010 ts.total_space);
893cccd0 13011 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13012 table_stats_strs[i]
13013 [TABLE_STATS_IDX_VTY],
893cccd0 13014 temp_buf);
9ab0cf58
PG
13015 } else {
13016 json_object_double_add(
13017 json,
13018 table_stats_strs[i]
13019 [TABLE_STATS_IDX_JSON],
13020 (double)ts.total_space);
13021 }
8d0ab76d 13022 if (afi == AFI_IP6) {
6c9d22e2
PG
13023 if (!json) {
13024 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13025 "%12g",
13026 ts.total_space
13027 * pow(2.0, -128 + 32));
6c9d22e2
PG
13028 vty_out(vty, "%30s: %s\n",
13029 "/32 equivalent %s\n",
13030 temp_buf);
9ab0cf58
PG
13031 } else {
13032 json_object_double_add(
13033 json, "/32equivalent",
13034 (double)(ts.total_space
13035 * pow(2.0,
13036 -128 + 32)));
13037 }
6c9d22e2
PG
13038 if (!json) {
13039 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13040 "%12g",
13041 ts.total_space
13042 * pow(2.0, -128 + 48));
6c9d22e2
PG
13043 vty_out(vty, "%30s: %s\n",
13044 "/48 equivalent %s\n",
13045 temp_buf);
9ab0cf58
PG
13046 } else {
13047 json_object_double_add(
13048 json, "/48equivalent",
13049 (double)(ts.total_space
13050 * pow(2.0,
13051 -128 + 48)));
13052 }
8d0ab76d 13053 } else {
6c9d22e2
PG
13054 if (!json) {
13055 snprintf(temp_buf, sizeof(temp_buf),
13056 "%12.2f",
9ab0cf58
PG
13057 ts.total_space * 100.
13058 * pow(2.0, -32));
6c9d22e2 13059 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13060 "% announced ", temp_buf);
13061 } else {
13062 json_object_double_add(
13063 json, "%announced",
13064 (double)(ts.total_space * 100.
13065 * pow(2.0, -32)));
13066 }
6c9d22e2
PG
13067 if (!json) {
13068 snprintf(temp_buf, sizeof(temp_buf),
13069 "%12.2f",
9ab0cf58
PG
13070 ts.total_space
13071 * pow(2.0, -32 + 8));
6c9d22e2
PG
13072 vty_out(vty, "%30s: %s\n",
13073 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13074 } else {
13075 json_object_double_add(
13076 json, "/8equivalent",
13077 (double)(ts.total_space
13078 * pow(2.0, -32 + 8)));
13079 }
6c9d22e2
PG
13080 if (!json) {
13081 snprintf(temp_buf, sizeof(temp_buf),
13082 "%12.2f",
9ab0cf58
PG
13083 ts.total_space
13084 * pow(2.0, -32 + 24));
6c9d22e2 13085 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13086 "/24 equivalent ", temp_buf);
13087 } else {
13088 json_object_double_add(
13089 json, "/24equivalent",
13090 (double)(ts.total_space
13091 * pow(2.0, -32 + 24)));
13092 }
8d0ab76d 13093 }
d62a17ae 13094 break;
13095 default:
6c9d22e2
PG
13096 if (!json) {
13097 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13098 ts.counts[i]);
893cccd0 13099 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13100 table_stats_strs[i]
13101 [TABLE_STATS_IDX_VTY],
13102 temp_buf);
13103 } else {
13104 json_object_int_add(
13105 json,
13106 table_stats_strs[i]
13107 [TABLE_STATS_IDX_JSON],
13108 ts.counts[i]);
13109 }
d62a17ae 13110 }
893cccd0
PG
13111 if (!json)
13112 vty_out(vty, "\n");
d62a17ae 13113 }
9ab0cf58 13114end_table_stats:
6c9d22e2
PG
13115 if (json)
13116 json_object_array_add(json_array, json);
893cccd0 13117 return ret;
d62a17ae 13118}
13119
71f1613a
DA
13120static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13121 safi_t safi, struct json_object *json_array)
13122{
13123 if (!bgp) {
13124 bgp_table_stats_all(vty, afi, safi, json_array);
13125 return CMD_SUCCESS;
13126 }
13127
13128 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13129}
13130
d62a17ae 13131enum bgp_pcounts {
13132 PCOUNT_ADJ_IN = 0,
13133 PCOUNT_DAMPED,
13134 PCOUNT_REMOVED,
13135 PCOUNT_HISTORY,
13136 PCOUNT_STALE,
13137 PCOUNT_VALID,
13138 PCOUNT_ALL,
13139 PCOUNT_COUNTED,
7e3d9632 13140 PCOUNT_BPATH_SELECTED,
d62a17ae 13141 PCOUNT_PFCNT, /* the figure we display to users */
13142 PCOUNT_MAX,
a636c635 13143};
718e3744 13144
2b64873d 13145static const char *const pcount_strs[] = {
9d303b37
DL
13146 [PCOUNT_ADJ_IN] = "Adj-in",
13147 [PCOUNT_DAMPED] = "Damped",
13148 [PCOUNT_REMOVED] = "Removed",
13149 [PCOUNT_HISTORY] = "History",
13150 [PCOUNT_STALE] = "Stale",
13151 [PCOUNT_VALID] = "Valid",
13152 [PCOUNT_ALL] = "All RIB",
13153 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13154 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13155 [PCOUNT_PFCNT] = "Useable",
13156 [PCOUNT_MAX] = NULL,
a636c635 13157};
718e3744 13158
d62a17ae 13159struct peer_pcounts {
13160 unsigned int count[PCOUNT_MAX];
13161 const struct peer *peer;
13162 const struct bgp_table *table;
54317cba 13163 safi_t safi;
a636c635 13164};
47fc97cc 13165
9bcb3eef 13166static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13167{
54317cba
JW
13168 const struct bgp_adj_in *ain;
13169 const struct bgp_path_info *pi;
d62a17ae 13170 const struct peer *peer = pc->peer;
13171
54317cba
JW
13172 for (ain = rn->adj_in; ain; ain = ain->next)
13173 if (ain->peer == peer)
13174 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13175
9bcb3eef 13176 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13177
54317cba
JW
13178 if (pi->peer != peer)
13179 continue;
d62a17ae 13180
54317cba 13181 pc->count[PCOUNT_ALL]++;
d62a17ae 13182
54317cba
JW
13183 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13184 pc->count[PCOUNT_DAMPED]++;
13185 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13186 pc->count[PCOUNT_HISTORY]++;
13187 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13188 pc->count[PCOUNT_REMOVED]++;
13189 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13190 pc->count[PCOUNT_STALE]++;
13191 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13192 pc->count[PCOUNT_VALID]++;
13193 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13194 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13195 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13196 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13197
13198 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13199 pc->count[PCOUNT_COUNTED]++;
13200 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13201 flog_err(
13202 EC_LIB_DEVELOPMENT,
13203 "Attempting to count but flags say it is unusable");
13204 } else {
40381db7 13205 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13206 flog_err(
13207 EC_LIB_DEVELOPMENT,
13208 "Not counted but flags say we should");
d62a17ae 13209 }
13210 }
54317cba
JW
13211}
13212
cc9f21da 13213static void bgp_peer_count_walker(struct thread *t)
54317cba 13214{
9bcb3eef 13215 struct bgp_dest *rn, *rm;
54317cba
JW
13216 const struct bgp_table *table;
13217 struct peer_pcounts *pc = THREAD_ARG(t);
13218
13219 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13220 || pc->safi == SAFI_EVPN) {
13221 /* Special handling for 2-level routing tables. */
13222 for (rn = bgp_table_top(pc->table); rn;
13223 rn = bgp_route_next(rn)) {
9bcb3eef 13224 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13225 if (table != NULL)
13226 for (rm = bgp_table_top(table); rm;
13227 rm = bgp_route_next(rm))
13228 bgp_peer_count_proc(rm, pc);
13229 }
13230 } else
13231 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13232 bgp_peer_count_proc(rn, pc);
718e3744 13233}
13234
d62a17ae 13235static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13236 safi_t safi, bool use_json)
856ca177 13237{
d62a17ae 13238 struct peer_pcounts pcounts = {.peer = peer};
13239 unsigned int i;
13240 json_object *json = NULL;
13241 json_object *json_loop = NULL;
856ca177 13242
d62a17ae 13243 if (use_json) {
13244 json = json_object_new_object();
13245 json_loop = json_object_new_object();
13246 }
718e3744 13247
d62a17ae 13248 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13249 || !peer->bgp->rib[afi][safi]) {
13250 if (use_json) {
13251 json_object_string_add(
13252 json, "warning",
13253 "No such neighbor or address family");
13254 vty_out(vty, "%s\n", json_object_to_json_string(json));
13255 json_object_free(json);
d5f20468 13256 json_object_free(json_loop);
d62a17ae 13257 } else
13258 vty_out(vty, "%% No such neighbor or address family\n");
13259
13260 return CMD_WARNING;
13261 }
2a71e9ce 13262
d62a17ae 13263 memset(&pcounts, 0, sizeof(pcounts));
13264 pcounts.peer = peer;
13265 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13266 pcounts.safi = safi;
d62a17ae 13267
13268 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13269 * stats for the thread-walk (i.e. ensure this can't be blamed on
13270 * on just vty_read()).
13271 */
d62a17ae 13272 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13273
13274 if (use_json) {
13275 json_object_string_add(json, "prefixCountsFor", peer->host);
13276 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13277 get_afi_safi_str(afi, safi, true));
d62a17ae 13278 json_object_int_add(json, "pfxCounter",
13279 peer->pcount[afi][safi]);
13280
13281 for (i = 0; i < PCOUNT_MAX; i++)
13282 json_object_int_add(json_loop, pcount_strs[i],
13283 pcounts.count[i]);
13284
13285 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13286
13287 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13288 json_object_string_add(json, "pfxctDriftFor",
13289 peer->host);
13290 json_object_string_add(
13291 json, "recommended",
13292 "Please report this bug, with the above command output");
13293 }
75eeda93 13294 vty_json(vty, json);
d62a17ae 13295 } else {
13296
13297 if (peer->hostname
892fedb6 13298 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13299 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13300 peer->hostname, peer->host,
5cb5f4d0 13301 get_afi_safi_str(afi, safi, false));
d62a17ae 13302 } else {
13303 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13304 get_afi_safi_str(afi, safi, false));
d62a17ae 13305 }
13306
6cde4b45 13307 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13308 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13309
13310 for (i = 0; i < PCOUNT_MAX; i++)
13311 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13312 pcounts.count[i]);
13313
13314 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13315 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13316 vty_out(vty,
13317 "Please report this bug, with the above command output\n");
13318 }
13319 }
13320
13321 return CMD_SUCCESS;
718e3744 13322}
13323
a636c635
DW
13324DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13325 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13326 "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 13327 SHOW_STR
13328 IP_STR
13329 BGP_STR
8386ac43 13330 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13331 BGP_AFI_HELP_STR
13332 BGP_SAFI_HELP_STR
0b16f239
DS
13333 "Detailed information on TCP and BGP neighbor connections\n"
13334 "Neighbor to display information about\n"
13335 "Neighbor to display information about\n"
91d37724 13336 "Neighbor on BGP configured interface\n"
a636c635 13337 "Display detailed prefix count information\n"
9973d184 13338 JSON_STR)
0b16f239 13339{
d62a17ae 13340 afi_t afi = AFI_IP6;
13341 safi_t safi = SAFI_UNICAST;
13342 struct peer *peer;
13343 int idx = 0;
13344 struct bgp *bgp = NULL;
9f049418
DS
13345 bool uj = use_json(argc, argv);
13346
13347 if (uj)
13348 argc--;
856ca177 13349
d62a17ae 13350 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13351 &bgp, uj);
d62a17ae 13352 if (!idx)
13353 return CMD_WARNING;
0b16f239 13354
d62a17ae 13355 argv_find(argv, argc, "neighbors", &idx);
13356 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13357 if (!peer)
13358 return CMD_WARNING;
bb46e94f 13359
29c8d9da 13360 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13361}
0b16f239 13362
d6902373
PG
13363#ifdef KEEP_OLD_VPN_COMMANDS
13364DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13365 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13366 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13367 SHOW_STR
13368 IP_STR
13369 BGP_STR
d6902373 13370 BGP_VPNVX_HELP_STR
91d37724 13371 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13372 "Detailed information on TCP and BGP neighbor connections\n"
13373 "Neighbor to display information about\n"
13374 "Neighbor to display information about\n"
91d37724 13375 "Neighbor on BGP configured interface\n"
a636c635 13376 "Display detailed prefix count information\n"
9973d184 13377 JSON_STR)
a636c635 13378{
d62a17ae 13379 int idx_peer = 6;
13380 struct peer *peer;
9f049418 13381 bool uj = use_json(argc, argv);
a636c635 13382
d62a17ae 13383 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13384 if (!peer)
13385 return CMD_WARNING;
13386
13387 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13388}
13389
d6902373
PG
13390DEFUN (show_ip_bgp_vpn_all_route_prefix,
13391 show_ip_bgp_vpn_all_route_prefix_cmd,
13392 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13393 SHOW_STR
13394 IP_STR
13395 BGP_STR
d6902373 13396 BGP_VPNVX_HELP_STR
91d37724
QY
13397 "Display information about all VPNv4 NLRIs\n"
13398 "Network in the BGP routing table to display\n"
3a2d747c 13399 "Network in the BGP routing table to display\n"
9973d184 13400 JSON_STR)
91d37724 13401{
d62a17ae 13402 int idx = 0;
13403 char *network = NULL;
13404 struct bgp *bgp = bgp_get_default();
13405 if (!bgp) {
13406 vty_out(vty, "Can't find default instance\n");
13407 return CMD_WARNING;
13408 }
87e34b58 13409
d62a17ae 13410 if (argv_find(argv, argc, "A.B.C.D", &idx))
13411 network = argv[idx]->arg;
13412 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13413 network = argv[idx]->arg;
13414 else {
13415 vty_out(vty, "Unable to figure out Network\n");
13416 return CMD_WARNING;
13417 }
87e34b58 13418
d62a17ae 13419 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13420 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13421 use_json(argc, argv));
91d37724 13422}
d6902373 13423#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13424
44c69747
LK
13425DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13426 show_bgp_l2vpn_evpn_route_prefix_cmd,
13427 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13428 SHOW_STR
4c63a661
PG
13429 BGP_STR
13430 L2VPN_HELP_STR
13431 EVPN_HELP_STR
44c69747
LK
13432 "Network in the BGP routing table to display\n"
13433 "Network in the BGP routing table to display\n"
4c63a661
PG
13434 "Network in the BGP routing table to display\n"
13435 "Network in the BGP routing table to display\n"
13436 JSON_STR)
13437{
d62a17ae 13438 int idx = 0;
13439 char *network = NULL;
44c69747 13440 int prefix_check = 0;
a636c635 13441
44c69747
LK
13442 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13443 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13444 network = argv[idx]->arg;
44c69747 13445 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13446 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13447 network = argv[idx]->arg;
44c69747
LK
13448 prefix_check = 1;
13449 } else {
d62a17ae 13450 vty_out(vty, "Unable to figure out Network\n");
13451 return CMD_WARNING;
13452 }
44c69747
LK
13453 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13454 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13455 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13456}
13457
2f9bc755
DS
13458static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13459 struct bgp_table *table, int *header1,
13460 int *header2, json_object *json,
13461 json_object *json_scode,
13462 json_object *json_ocode, bool wide)
13463{
13464 uint64_t version = table ? table->version : 0;
13465
13466 if (*header1) {
13467 if (json) {
13468 json_object_int_add(json, "bgpTableVersion", version);
c949c771
DA
13469 json_object_string_addf(json, "bgpLocalRouterId",
13470 "%pI4", &bgp->router_id);
2f9bc755
DS
13471 json_object_int_add(json, "defaultLocPrf",
13472 bgp->default_local_pref);
13473 json_object_int_add(json, "localAS", bgp->as);
13474 json_object_object_add(json, "bgpStatusCodes",
13475 json_scode);
13476 json_object_object_add(json, "bgpOriginCodes",
13477 json_ocode);
13478 } else {
13479 vty_out(vty,
23d0a753
DA
13480 "BGP table version is %" PRIu64
13481 ", local router ID is %pI4, vrf id ",
13482 version, &bgp->router_id);
2f9bc755
DS
13483 if (bgp->vrf_id == VRF_UNKNOWN)
13484 vty_out(vty, "%s", VRFID_NONE_STR);
13485 else
13486 vty_out(vty, "%u", bgp->vrf_id);
13487 vty_out(vty, "\n");
13488 vty_out(vty, "Default local pref %u, ",
13489 bgp->default_local_pref);
13490 vty_out(vty, "local AS %u\n", bgp->as);
13491 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13492 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13493 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13494 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13495 }
13496 *header1 = 0;
13497 }
13498 if (*header2) {
13499 if (!json)
13500 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13501 : BGP_SHOW_HEADER));
13502 *header2 = 0;
13503 }
13504}
13505
d9478df0
TA
13506static void
13507show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13508 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13509 const char *rmap_name, json_object *json, json_object *json_ar,
13510 json_object *json_scode, json_object *json_ocode,
96c81f66 13511 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13512 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13513{
d62a17ae 13514 struct bgp_adj_in *ain;
13515 struct bgp_adj_out *adj;
9bcb3eef 13516 struct bgp_dest *dest;
d62a17ae 13517 struct bgp *bgp;
d62a17ae 13518 struct attr attr;
13519 int ret;
13520 struct update_subgroup *subgrp;
d62a17ae 13521 struct peer_af *paf;
f99def61 13522 bool route_filtered;
96f3485c
MK
13523 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13524 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13525 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13526 || (safi == SAFI_EVPN))
13527 ? true
13528 : false;
a636c635 13529
d62a17ae 13530 bgp = peer->bgp;
a636c635 13531
d62a17ae 13532 subgrp = peer_subgroup(peer, afi, safi);
13533
6392aaa6 13534 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13535 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13536 if (use_json) {
13537 json_object_int_add(json, "bgpTableVersion",
13538 table->version);
c949c771
DA
13539 json_object_string_addf(json, "bgpLocalRouterId",
13540 "%pI4", &bgp->router_id);
01eced22
AD
13541 json_object_int_add(json, "defaultLocPrf",
13542 bgp->default_local_pref);
13543 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13544 json_object_object_add(json, "bgpStatusCodes",
13545 json_scode);
13546 json_object_object_add(json, "bgpOriginCodes",
13547 json_ocode);
07d0c4ed
DA
13548 json_object_string_add(
13549 json, "bgpOriginatingDefaultNetwork",
13550 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13551 } else {
23d0a753
DA
13552 vty_out(vty,
13553 "BGP table version is %" PRIu64
13554 ", local router ID is %pI4, vrf id ",
13555 table->version, &bgp->router_id);
9df8b37c
PZ
13556 if (bgp->vrf_id == VRF_UNKNOWN)
13557 vty_out(vty, "%s", VRFID_NONE_STR);
13558 else
13559 vty_out(vty, "%u", bgp->vrf_id);
13560 vty_out(vty, "\n");
01eced22
AD
13561 vty_out(vty, "Default local pref %u, ",
13562 bgp->default_local_pref);
13563 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13564 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13565 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13566 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13567 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13568
07d0c4ed
DA
13569 vty_out(vty, "Originating default network %s\n\n",
13570 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13571 }
d9478df0 13572 *header1 = 0;
d62a17ae 13573 }
a636c635 13574
9bcb3eef 13575 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13576 if (type == bgp_show_adj_route_received
13577 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13578 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13579 if (ain->peer != peer)
ea47320b 13580 continue;
6392aaa6 13581
d9478df0
TA
13582 show_adj_route_header(vty, bgp, table, header1,
13583 header2, json, json_scode,
13584 json_ocode, wide);
13585
13586 if ((safi == SAFI_MPLS_VPN)
13587 || (safi == SAFI_ENCAP)
13588 || (safi == SAFI_EVPN)) {
13589 if (use_json)
13590 json_object_string_add(
13591 json_ar, "rd", rd_str);
13592 else if (show_rd && rd_str) {
13593 vty_out(vty,
13594 "Route Distinguisher: %s\n",
13595 rd_str);
13596 show_rd = false;
13597 }
13598 }
6392aaa6 13599
6f4f49b2 13600 attr = *ain->attr;
f99def61
AD
13601 route_filtered = false;
13602
13603 /* Filter prefix using distribute list,
13604 * filter list or prefix list
13605 */
b54892e0 13606 const struct prefix *rn_p =
9bcb3eef 13607 bgp_dest_get_prefix(dest);
b54892e0
DS
13608 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13609 safi))
13610 == FILTER_DENY)
f99def61
AD
13611 route_filtered = true;
13612
13613 /* Filter prefix using route-map */
b54892e0
DS
13614 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13615 safi, rmap_name, NULL,
13616 0, NULL);
6392aaa6 13617
13c8e163
AD
13618 if (type == bgp_show_adj_route_filtered &&
13619 !route_filtered && ret != RMAP_DENY) {
d498917e 13620 bgp_attr_flush(&attr);
6392aaa6 13621 continue;
d62a17ae 13622 }
6392aaa6 13623
d9478df0
TA
13624 if (type == bgp_show_adj_route_received
13625 && (route_filtered || ret == RMAP_DENY))
13626 (*filtered_count)++;
6392aaa6 13627
7d3cae70 13628 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13629 use_json, json_ar, wide);
d498917e 13630 bgp_attr_flush(&attr);
d9478df0 13631 (*output_count)++;
d62a17ae 13632 }
6392aaa6 13633 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13634 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13635 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13636 if (paf->peer != peer || !adj->attr)
924c3f6a 13637 continue;
d62a17ae 13638
d9478df0
TA
13639 show_adj_route_header(vty, bgp, table,
13640 header1, header2,
13641 json, json_scode,
13642 json_ocode, wide);
d62a17ae 13643
b54892e0 13644 const struct prefix *rn_p =
9bcb3eef 13645 bgp_dest_get_prefix(dest);
b54892e0 13646
6f4f49b2 13647 attr = *adj->attr;
b755861b 13648 ret = bgp_output_modifier(
b54892e0 13649 peer, rn_p, &attr, afi, safi,
b755861b 13650 rmap_name);
f46d8e1e 13651
b755861b 13652 if (ret != RMAP_DENY) {
d9478df0
TA
13653 if ((safi == SAFI_MPLS_VPN)
13654 || (safi == SAFI_ENCAP)
13655 || (safi == SAFI_EVPN)) {
13656 if (use_json)
13657 json_object_string_add(
13658 json_ar,
13659 "rd",
13660 rd_str);
13661 else if (show_rd
13662 && rd_str) {
13663 vty_out(vty,
13664 "Route Distinguisher: %s\n",
13665 rd_str);
13666 show_rd = false;
13667 }
13668 }
b54892e0 13669 route_vty_out_tmp(
7d3cae70
DA
13670 vty, dest, rn_p, &attr,
13671 safi, use_json, json_ar,
ae248832 13672 wide);
d9478df0 13673 (*output_count)++;
b755861b 13674 } else {
d9478df0 13675 (*filtered_count)++;
a2addae8 13676 }
b755861b 13677
d498917e 13678 bgp_attr_flush(&attr);
924c3f6a 13679 }
f20ce998
DS
13680 } else if (type == bgp_show_adj_route_bestpath) {
13681 struct bgp_path_info *pi;
13682
d9478df0
TA
13683 show_adj_route_header(vty, bgp, table, header1, header2,
13684 json, json_scode, json_ocode,
13685 wide);
f20ce998
DS
13686
13687 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13688 pi = pi->next) {
13689 if (pi->peer != peer)
13690 continue;
13691
13692 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13693 continue;
13694
7d3cae70 13695 route_vty_out_tmp(vty, dest,
f20ce998
DS
13696 bgp_dest_get_prefix(dest),
13697 pi->attr, safi, use_json,
13698 json_ar, wide);
d9478df0 13699 (*output_count)++;
f20ce998 13700 }
d62a17ae 13701 }
13702 }
a636c635 13703}
2a71e9ce 13704
d62a17ae 13705static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13706 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13707 const char *rmap_name, uint16_t show_flags)
0b16f239 13708{
d9478df0
TA
13709 struct bgp *bgp;
13710 struct bgp_table *table;
d62a17ae 13711 json_object *json = NULL;
d9478df0
TA
13712 json_object *json_scode = NULL;
13713 json_object *json_ocode = NULL;
13714 json_object *json_ar = NULL;
96f3485c 13715 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13716
d9478df0
TA
13717 /* Init BGP headers here so they're only displayed once
13718 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13719 */
13720 int header1 = 1;
13721 int header2 = 1;
13722
13723 /*
13724 * Initialize variables for each RD
13725 * All prefixes under an RD is aggregated within "json_routes"
13726 */
13727 char rd_str[BUFSIZ] = {0};
13728 json_object *json_routes = NULL;
13729
13730
13731 /* For 2-tier tables, prefix counts need to be
13732 * maintained across multiple runs of show_adj_route()
13733 */
13734 unsigned long output_count_per_rd;
13735 unsigned long filtered_count_per_rd;
13736 unsigned long output_count = 0;
13737 unsigned long filtered_count = 0;
13738
13739 if (use_json) {
d62a17ae 13740 json = json_object_new_object();
d9478df0
TA
13741 json_ar = json_object_new_object();
13742 json_scode = json_object_new_object();
13743 json_ocode = json_object_new_object();
13744
13745 json_object_string_add(json_scode, "suppressed", "s");
13746 json_object_string_add(json_scode, "damped", "d");
13747 json_object_string_add(json_scode, "history", "h");
13748 json_object_string_add(json_scode, "valid", "*");
13749 json_object_string_add(json_scode, "best", ">");
13750 json_object_string_add(json_scode, "multipath", "=");
13751 json_object_string_add(json_scode, "internal", "i");
13752 json_object_string_add(json_scode, "ribFailure", "r");
13753 json_object_string_add(json_scode, "stale", "S");
13754 json_object_string_add(json_scode, "removed", "R");
13755
13756 json_object_string_add(json_ocode, "igp", "i");
13757 json_object_string_add(json_ocode, "egp", "e");
13758 json_object_string_add(json_ocode, "incomplete", "?");
13759 }
0b16f239 13760
d62a17ae 13761 if (!peer || !peer->afc[afi][safi]) {
13762 if (use_json) {
13763 json_object_string_add(
13764 json, "warning",
13765 "No such neighbor or address family");
13766 vty_out(vty, "%s\n", json_object_to_json_string(json));
13767 json_object_free(json);
690c3134
MW
13768 json_object_free(json_ar);
13769 json_object_free(json_scode);
13770 json_object_free(json_ocode);
d62a17ae 13771 } else
13772 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13773
d62a17ae 13774 return CMD_WARNING;
13775 }
13776
6392aaa6
PM
13777 if ((type == bgp_show_adj_route_received
13778 || type == bgp_show_adj_route_filtered)
d62a17ae 13779 && !CHECK_FLAG(peer->af_flags[afi][safi],
13780 PEER_FLAG_SOFT_RECONFIG)) {
13781 if (use_json) {
13782 json_object_string_add(
13783 json, "warning",
13784 "Inbound soft reconfiguration not enabled");
13785 vty_out(vty, "%s\n", json_object_to_json_string(json));
13786 json_object_free(json);
690c3134
MW
13787 json_object_free(json_ar);
13788 json_object_free(json_scode);
13789 json_object_free(json_ocode);
d62a17ae 13790 } else
13791 vty_out(vty,
13792 "%% Inbound soft reconfiguration not enabled\n");
13793
13794 return CMD_WARNING;
13795 }
0b16f239 13796
d9478df0
TA
13797 bgp = peer->bgp;
13798
13799 /* labeled-unicast routes live in the unicast table */
13800 if (safi == SAFI_LABELED_UNICAST)
13801 table = bgp->rib[afi][SAFI_UNICAST];
13802 else
13803 table = bgp->rib[afi][safi];
13804
13805 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13806 || (safi == SAFI_EVPN)) {
13807
13808 struct bgp_dest *dest;
13809
13810 for (dest = bgp_table_top(table); dest;
13811 dest = bgp_route_next(dest)) {
13812 table = bgp_dest_get_bgp_table_info(dest);
13813 if (!table)
13814 continue;
13815
13816 output_count_per_rd = 0;
13817 filtered_count_per_rd = 0;
13818
13819 if (use_json)
13820 json_routes = json_object_new_object();
13821
13822 const struct prefix_rd *prd;
13823 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13824 dest);
13825
13826 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13827
13828 show_adj_route(vty, peer, table, afi, safi, type,
13829 rmap_name, json, json_routes, json_scode,
13830 json_ocode, show_flags, &header1,
13831 &header2, rd_str, &output_count_per_rd,
13832 &filtered_count_per_rd);
13833
13834 /* Don't include an empty RD in the output! */
13835 if (json_routes && (output_count_per_rd > 0))
13836 json_object_object_add(json_ar, rd_str,
13837 json_routes);
13838
13839 output_count += output_count_per_rd;
13840 filtered_count += filtered_count_per_rd;
13841 }
13842 } else
13843 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13844 json, json_ar, json_scode, json_ocode,
13845 show_flags, &header1, &header2, rd_str,
13846 &output_count, &filtered_count);
13847
13848 if (use_json) {
c1984955
TA
13849 if (type == bgp_show_adj_route_advertised)
13850 json_object_object_add(json, "advertisedRoutes",
13851 json_ar);
13852 else
13853 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
13854 json_object_int_add(json, "totalPrefixCounter", output_count);
13855 json_object_int_add(json, "filteredPrefixCounter",
13856 filtered_count);
13857
690c3134
MW
13858 /*
13859 * These fields only give up ownership to `json` when `header1`
13860 * is used (set to zero). See code in `show_adj_route` and
13861 * `show_adj_route_header`.
13862 */
13863 if (header1 == 1) {
d9478df0
TA
13864 json_object_free(json_scode);
13865 json_object_free(json_ocode);
13866 }
13867
75eeda93 13868 vty_json(vty, json);
d9478df0
TA
13869 } else if (output_count > 0) {
13870 if (filtered_count > 0)
13871 vty_out(vty,
13872 "\nTotal number of prefixes %ld (%ld filtered)\n",
13873 output_count, filtered_count);
13874 else
13875 vty_out(vty, "\nTotal number of prefixes %ld\n",
13876 output_count);
13877 }
0b16f239 13878
d62a17ae 13879 return CMD_SUCCESS;
a636c635 13880}
50ef26d4 13881
f20ce998
DS
13882DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13883 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13884 "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]",
13885 SHOW_STR
13886 IP_STR
13887 BGP_STR
13888 BGP_INSTANCE_HELP_STR
13889 BGP_AFI_HELP_STR
13890 BGP_SAFI_WITH_LABEL_HELP_STR
13891 "Detailed information on TCP and BGP neighbor connections\n"
13892 "Neighbor to display information about\n"
13893 "Neighbor to display information about\n"
13894 "Neighbor on BGP configured interface\n"
13895 "Display the routes selected by best path\n"
13896 JSON_STR
13897 "Increase table width for longer prefixes\n")
13898{
13899 afi_t afi = AFI_IP6;
13900 safi_t safi = SAFI_UNICAST;
13901 char *rmap_name = NULL;
13902 char *peerstr = NULL;
13903 struct bgp *bgp = NULL;
13904 struct peer *peer;
13905 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13906 int idx = 0;
96c81f66 13907 uint16_t show_flags = 0;
96f3485c
MK
13908
13909 if (uj)
13910 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13911
13912 if (wide)
13913 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13914
13915 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13916 &bgp, uj);
13917
13918 if (!idx)
13919 return CMD_WARNING;
13920
13921 argv_find(argv, argc, "neighbors", &idx);
13922 peerstr = argv[++idx]->arg;
13923
13924 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13925 if (!peer)
13926 return CMD_WARNING;
13927
96f3485c
MK
13928 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13929 show_flags);
f20ce998
DS
13930}
13931
ae248832 13932DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13933 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13934 "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 13935 SHOW_STR
13936 IP_STR
13937 BGP_STR
a636c635 13938 BGP_INSTANCE_HELP_STR
7395a2c9 13939 BGP_AFI_HELP_STR
4dd6177e 13940 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13941 "Display the entries for all address families\n"
718e3744 13942 "Detailed information on TCP and BGP neighbor connections\n"
13943 "Neighbor to display information about\n"
13944 "Neighbor to display information about\n"
91d37724 13945 "Neighbor on BGP configured interface\n"
a636c635 13946 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13947 "Display the received routes from neighbor\n"
13948 "Display the filtered routes received from neighbor\n"
a636c635
DW
13949 "Route-map to modify the attributes\n"
13950 "Name of the route map\n"
ae248832
MK
13951 JSON_STR
13952 "Increase table width for longer prefixes\n")
718e3744 13953{
d62a17ae 13954 afi_t afi = AFI_IP6;
13955 safi_t safi = SAFI_UNICAST;
13956 char *rmap_name = NULL;
13957 char *peerstr = NULL;
d62a17ae 13958 struct bgp *bgp = NULL;
13959 struct peer *peer;
6392aaa6 13960 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13961 int idx = 0;
96f3485c 13962 bool first = true;
96c81f66 13963 uint16_t show_flags = 0;
6392aaa6 13964
96f3485c 13965 if (uj) {
d62a17ae 13966 argc--;
96f3485c
MK
13967 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13968 }
13969
13970 if (all) {
13971 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13972 if (argv_find(argv, argc, "ipv4", &idx))
13973 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13974
13975 if (argv_find(argv, argc, "ipv6", &idx))
13976 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13977 }
13978
13979 if (wide)
13980 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13981
9f049418
DS
13982 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13983 &bgp, uj);
13984 if (!idx)
13985 return CMD_WARNING;
13986
d62a17ae 13987 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13988 argv_find(argv, argc, "neighbors", &idx);
13989 peerstr = argv[++idx]->arg;
8c3deaae 13990
d62a17ae 13991 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13992 if (!peer)
13993 return CMD_WARNING;
856ca177 13994
d62a17ae 13995 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13996 type = bgp_show_adj_route_advertised;
13997 else if (argv_find(argv, argc, "received-routes", &idx))
13998 type = bgp_show_adj_route_received;
13999 else if (argv_find(argv, argc, "filtered-routes", &idx))
14000 type = bgp_show_adj_route_filtered;
14001
d62a17ae 14002 if (argv_find(argv, argc, "route-map", &idx))
14003 rmap_name = argv[++idx]->arg;
95cbbd2a 14004
96f3485c
MK
14005 if (!all)
14006 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14007 show_flags);
14008 if (uj)
14009 vty_out(vty, "{\n");
14010
14011 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14012 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14013 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14014 : AFI_IP6;
14015 FOREACH_SAFI (safi) {
96f3485c
MK
14016 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14017 continue;
14018
14019 if (uj) {
14020 if (first)
14021 first = false;
14022 else
14023 vty_out(vty, ",\n");
14024 vty_out(vty, "\"%s\":",
14025 get_afi_safi_str(afi, safi, true));
14026 } else
14027 vty_out(vty, "\nFor address family: %s\n",
14028 get_afi_safi_str(afi, safi, false));
14029
14030 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14031 show_flags);
14032 }
14033 } else {
14034 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
14035 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14036 continue;
14037
14038 if (uj) {
14039 if (first)
14040 first = false;
14041 else
14042 vty_out(vty, ",\n");
14043 vty_out(vty, "\"%s\":",
14044 get_afi_safi_str(afi, safi, true));
14045 } else
14046 vty_out(vty, "\nFor address family: %s\n",
14047 get_afi_safi_str(afi, safi, false));
14048
14049 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14050 show_flags);
14051 }
14052 }
14053 if (uj)
14054 vty_out(vty, "}\n");
14055
14056 return CMD_SUCCESS;
95cbbd2a
ML
14057}
14058
718e3744 14059DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14060 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14061 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14062 SHOW_STR
14063 IP_STR
14064 BGP_STR
d3120452 14065 BGP_INSTANCE_HELP_STR
8c3deaae
QY
14066 "Address Family\n"
14067 "Address Family\n"
718e3744 14068 "Address Family modifier\n"
14069 "Detailed information on TCP and BGP neighbor connections\n"
14070 "Neighbor to display information about\n"
14071 "Neighbor to display information about\n"
91d37724 14072 "Neighbor on BGP configured interface\n"
718e3744 14073 "Display information received from a BGP neighbor\n"
856ca177 14074 "Display the prefixlist filter\n"
9973d184 14075 JSON_STR)
718e3744 14076{
d62a17ae 14077 afi_t afi = AFI_IP6;
14078 safi_t safi = SAFI_UNICAST;
14079 char *peerstr = NULL;
d62a17ae 14080 char name[BUFSIZ];
d62a17ae 14081 struct peer *peer;
d3120452 14082 int count;
d62a17ae 14083 int idx = 0;
d3120452
IR
14084 struct bgp *bgp = NULL;
14085 bool uj = use_json(argc, argv);
14086
14087 if (uj)
14088 argc--;
14089
14090 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14091 &bgp, uj);
14092 if (!idx)
14093 return CMD_WARNING;
d62a17ae 14094
d62a17ae 14095 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14096 argv_find(argv, argc, "neighbors", &idx);
14097 peerstr = argv[++idx]->arg;
14098
d3120452
IR
14099 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14100 if (!peer)
14101 return CMD_WARNING;
718e3744 14102
4ced1a2c 14103 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14104 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14105 if (count) {
14106 if (!uj)
14107 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14108 get_afi_safi_str(afi, safi, false));
d62a17ae 14109 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14110 } else {
14111 if (uj)
14112 vty_out(vty, "{}\n");
14113 else
14114 vty_out(vty, "No functional output\n");
14115 }
718e3744 14116
d62a17ae 14117 return CMD_SUCCESS;
14118}
14119
14120static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14121 afi_t afi, safi_t safi,
9f049418 14122 enum bgp_show_type type, bool use_json)
d62a17ae 14123{
96c81f66 14124 uint16_t show_flags = 0;
96f3485c
MK
14125
14126 if (use_json)
14127 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14128
d62a17ae 14129 if (!peer || !peer->afc[afi][safi]) {
14130 if (use_json) {
14131 json_object *json_no = NULL;
14132 json_no = json_object_new_object();
14133 json_object_string_add(
14134 json_no, "warning",
14135 "No such neighbor or address family");
14136 vty_out(vty, "%s\n",
14137 json_object_to_json_string(json_no));
14138 json_object_free(json_no);
14139 } else
14140 vty_out(vty, "%% No such neighbor or address family\n");
14141 return CMD_WARNING;
14142 }
47fc97cc 14143
7daf25a3
TA
14144 /* labeled-unicast routes live in the unicast table */
14145 if (safi == SAFI_LABELED_UNICAST)
14146 safi = SAFI_UNICAST;
14147
1e2ce4f1
DS
14148 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14149 RPKI_NOT_BEING_USED);
718e3744 14150}
14151
dba3c1d3
PG
14152DEFUN (show_ip_bgp_flowspec_routes_detailed,
14153 show_ip_bgp_flowspec_routes_detailed_cmd,
14154 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14155 SHOW_STR
14156 IP_STR
14157 BGP_STR
14158 BGP_INSTANCE_HELP_STR
14159 BGP_AFI_HELP_STR
14160 "SAFI Flowspec\n"
14161 "Detailed information on flowspec entries\n"
14162 JSON_STR)
14163{
458c1475 14164 afi_t afi = AFI_IP6;
dba3c1d3
PG
14165 safi_t safi = SAFI_UNICAST;
14166 struct bgp *bgp = NULL;
14167 int idx = 0;
9f049418 14168 bool uj = use_json(argc, argv);
5be6fa9b 14169 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14170
96f3485c 14171 if (uj) {
9f049418 14172 argc--;
96f3485c
MK
14173 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14174 }
dba3c1d3
PG
14175
14176 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14177 &bgp, uj);
dba3c1d3
PG
14178 if (!idx)
14179 return CMD_WARNING;
14180
96f3485c 14181 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14182 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14183}
14184
718e3744 14185DEFUN (show_ip_bgp_neighbor_routes,
14186 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14187 "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 14188 SHOW_STR
14189 IP_STR
14190 BGP_STR
8386ac43 14191 BGP_INSTANCE_HELP_STR
4f280b15 14192 BGP_AFI_HELP_STR
4dd6177e 14193 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14194 "Detailed information on TCP and BGP neighbor connections\n"
14195 "Neighbor to display information about\n"
14196 "Neighbor to display information about\n"
91d37724 14197 "Neighbor on BGP configured interface\n"
2525cf39 14198 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14199 "Display the dampened routes received from neighbor\n"
14200 "Display routes learned from neighbor\n"
9973d184 14201 JSON_STR)
718e3744 14202{
d62a17ae 14203 char *peerstr = NULL;
14204 struct bgp *bgp = NULL;
14205 afi_t afi = AFI_IP6;
14206 safi_t safi = SAFI_UNICAST;
14207 struct peer *peer;
14208 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14209 int idx = 0;
9f049418
DS
14210 bool uj = use_json(argc, argv);
14211
14212 if (uj)
14213 argc--;
bb46e94f 14214
d62a17ae 14215 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14216 &bgp, uj);
d62a17ae 14217 if (!idx)
14218 return CMD_WARNING;
c493f2d8 14219
d62a17ae 14220 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14221 argv_find(argv, argc, "neighbors", &idx);
14222 peerstr = argv[++idx]->arg;
8c3deaae 14223
d62a17ae 14224 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14225 if (!peer)
d62a17ae 14226 return CMD_WARNING;
bb46e94f 14227
d62a17ae 14228 if (argv_find(argv, argc, "flap-statistics", &idx))
14229 sh_type = bgp_show_type_flap_neighbor;
14230 else if (argv_find(argv, argc, "dampened-routes", &idx))
14231 sh_type = bgp_show_type_damp_neighbor;
14232 else if (argv_find(argv, argc, "routes", &idx))
14233 sh_type = bgp_show_type_neighbor;
2525cf39 14234
d62a17ae 14235 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14236}
6b0655a2 14237
734b349e 14238struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14239
d62a17ae 14240struct bgp_distance {
14241 /* Distance value for the IP source prefix. */
d7c0a89a 14242 uint8_t distance;
718e3744 14243
d62a17ae 14244 /* Name of the access-list to be matched. */
14245 char *access_list;
718e3744 14246};
14247
4f280b15
LB
14248DEFUN (show_bgp_afi_vpn_rd_route,
14249 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14250 "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
14251 SHOW_STR
14252 BGP_STR
14253 BGP_AFI_HELP_STR
14254 "Address Family modifier\n"
14255 "Display information for a route distinguisher\n"
14256 "Route Distinguisher\n"
a111dd97 14257 "All Route Distinguishers\n"
7395a2c9
DS
14258 "Network in the BGP routing table to display\n"
14259 "Network in the BGP routing table to display\n"
14260 JSON_STR)
4f280b15 14261{
d62a17ae 14262 int ret;
14263 struct prefix_rd prd;
14264 afi_t afi = AFI_MAX;
14265 int idx = 0;
4f280b15 14266
ff6566f3
DS
14267 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14268 vty_out(vty, "%% Malformed Address Family\n");
14269 return CMD_WARNING;
14270 }
14271
a111dd97
TA
14272 if (!strcmp(argv[5]->arg, "all"))
14273 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14274 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14275 RPKI_NOT_BEING_USED,
14276 use_json(argc, argv));
14277
d62a17ae 14278 ret = str2prefix_rd(argv[5]->arg, &prd);
14279 if (!ret) {
14280 vty_out(vty, "%% Malformed Route Distinguisher\n");
14281 return CMD_WARNING;
14282 }
ff6566f3 14283
d62a17ae 14284 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14285 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14286 use_json(argc, argv));
4f280b15
LB
14287}
14288
d62a17ae 14289static struct bgp_distance *bgp_distance_new(void)
718e3744 14290{
d62a17ae 14291 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14292}
14293
d62a17ae 14294static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14295{
d62a17ae 14296 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14297}
14298
585f1adc
IR
14299static int bgp_distance_set(struct vty *vty, const char *distance_str,
14300 const char *ip_str, const char *access_list_str)
718e3744 14301{
d62a17ae 14302 int ret;
585f1adc
IR
14303 afi_t afi;
14304 safi_t safi;
d62a17ae 14305 struct prefix p;
585f1adc 14306 uint8_t distance;
9bcb3eef 14307 struct bgp_dest *dest;
d62a17ae 14308 struct bgp_distance *bdistance;
718e3744 14309
585f1adc
IR
14310 afi = bgp_node_afi(vty);
14311 safi = bgp_node_safi(vty);
14312
d62a17ae 14313 ret = str2prefix(ip_str, &p);
14314 if (ret == 0) {
585f1adc 14315 vty_out(vty, "Malformed prefix\n");
d62a17ae 14316 return CMD_WARNING_CONFIG_FAILED;
14317 }
718e3744 14318
585f1adc
IR
14319 distance = atoi(distance_str);
14320
d62a17ae 14321 /* Get BGP distance node. */
9bcb3eef
DS
14322 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14323 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14324 if (bdistance)
9bcb3eef 14325 bgp_dest_unlock_node(dest);
ca2e160d 14326 else {
d62a17ae 14327 bdistance = bgp_distance_new();
9bcb3eef 14328 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14329 }
718e3744 14330
d62a17ae 14331 /* Set distance value. */
14332 bdistance->distance = distance;
718e3744 14333
d62a17ae 14334 /* Reset access-list configuration. */
e1b36e13 14335 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14336 if (access_list_str)
14337 bdistance->access_list =
14338 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14339
d62a17ae 14340 return CMD_SUCCESS;
718e3744 14341}
14342
585f1adc
IR
14343static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14344 const char *ip_str, const char *access_list_str)
718e3744 14345{
d62a17ae 14346 int ret;
585f1adc
IR
14347 afi_t afi;
14348 safi_t safi;
d62a17ae 14349 struct prefix p;
585f1adc 14350 int distance;
9bcb3eef 14351 struct bgp_dest *dest;
d62a17ae 14352 struct bgp_distance *bdistance;
718e3744 14353
585f1adc
IR
14354 afi = bgp_node_afi(vty);
14355 safi = bgp_node_safi(vty);
14356
d62a17ae 14357 ret = str2prefix(ip_str, &p);
14358 if (ret == 0) {
585f1adc 14359 vty_out(vty, "Malformed prefix\n");
d62a17ae 14360 return CMD_WARNING_CONFIG_FAILED;
14361 }
718e3744 14362
9bcb3eef
DS
14363 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14364 if (!dest) {
585f1adc 14365 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14366 return CMD_WARNING_CONFIG_FAILED;
14367 }
718e3744 14368
9bcb3eef 14369 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14370 distance = atoi(distance_str);
1f9a9fff 14371
d62a17ae 14372 if (bdistance->distance != distance) {
585f1adc 14373 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14374 bgp_dest_unlock_node(dest);
d62a17ae 14375 return CMD_WARNING_CONFIG_FAILED;
14376 }
718e3744 14377
0a22ddfb 14378 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14379 bgp_distance_free(bdistance);
718e3744 14380
9bcb3eef
DS
14381 bgp_dest_set_bgp_path_info(dest, NULL);
14382 bgp_dest_unlock_node(dest);
14383 bgp_dest_unlock_node(dest);
718e3744 14384
d62a17ae 14385 return CMD_SUCCESS;
718e3744 14386}
14387
718e3744 14388/* Apply BGP information to distance method. */
b8685f9b 14389uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14390 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14391{
9bcb3eef 14392 struct bgp_dest *dest;
801bb996 14393 struct prefix q = {0};
d62a17ae 14394 struct peer *peer;
14395 struct bgp_distance *bdistance;
14396 struct access_list *alist;
14397 struct bgp_static *bgp_static;
14398
14399 if (!bgp)
14400 return 0;
14401
40381db7 14402 peer = pinfo->peer;
d62a17ae 14403
7b7d48e5
DS
14404 if (pinfo->attr->distance)
14405 return pinfo->attr->distance;
14406
801bb996
CS
14407 /* Check source address.
14408 * Note: for aggregate route, peer can have unspec af type.
14409 */
14410 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14411 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14412 return 0;
14413
9bcb3eef
DS
14414 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14415 if (dest) {
14416 bdistance = bgp_dest_get_bgp_distance_info(dest);
14417 bgp_dest_unlock_node(dest);
d62a17ae 14418
14419 if (bdistance->access_list) {
14420 alist = access_list_lookup(afi, bdistance->access_list);
14421 if (alist
14422 && access_list_apply(alist, p) == FILTER_PERMIT)
14423 return bdistance->distance;
14424 } else
14425 return bdistance->distance;
718e3744 14426 }
718e3744 14427
d62a17ae 14428 /* Backdoor check. */
9bcb3eef
DS
14429 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14430 if (dest) {
14431 bgp_static = bgp_dest_get_bgp_static_info(dest);
14432 bgp_dest_unlock_node(dest);
718e3744 14433
d62a17ae 14434 if (bgp_static->backdoor) {
14435 if (bgp->distance_local[afi][safi])
14436 return bgp->distance_local[afi][safi];
14437 else
14438 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14439 }
718e3744 14440 }
718e3744 14441
d62a17ae 14442 if (peer->sort == BGP_PEER_EBGP) {
14443 if (bgp->distance_ebgp[afi][safi])
14444 return bgp->distance_ebgp[afi][safi];
14445 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14446 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14447 if (bgp->distance_ibgp[afi][safi])
14448 return bgp->distance_ibgp[afi][safi];
14449 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14450 } else {
14451 if (bgp->distance_local[afi][safi])
14452 return bgp->distance_local[afi][safi];
14453 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14454 }
718e3744 14455}
14456
a612fb77
DA
14457/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14458 * we should tell ZEBRA update the routes for a specific
14459 * AFI/SAFI to reflect changes in RIB.
14460 */
585f1adc
IR
14461static void bgp_announce_routes_distance_update(struct bgp *bgp,
14462 afi_t update_afi,
14463 safi_t update_safi)
a612fb77
DA
14464{
14465 afi_t afi;
14466 safi_t safi;
14467
14468 FOREACH_AFI_SAFI (afi, safi) {
14469 if (!bgp_fibupd_safi(safi))
14470 continue;
14471
8b54bc30
DA
14472 if (afi != update_afi && safi != update_safi)
14473 continue;
14474
14475 if (BGP_DEBUG(zebra, ZEBRA))
14476 zlog_debug(
14477 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14478 __func__, afi, safi);
14479 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14480 }
14481}
14482
585f1adc
IR
14483DEFUN (bgp_distance,
14484 bgp_distance_cmd,
14485 "distance bgp (1-255) (1-255) (1-255)",
14486 "Define an administrative distance\n"
14487 "BGP distance\n"
14488 "Distance for routes external to the AS\n"
14489 "Distance for routes internal to the AS\n"
14490 "Distance for local routes\n")
718e3744 14491{
585f1adc 14492 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14493 int idx_number = 2;
14494 int idx_number_2 = 3;
14495 int idx_number_3 = 4;
585f1adc
IR
14496 int distance_ebgp = atoi(argv[idx_number]->arg);
14497 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14498 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14499 afi_t afi;
14500 safi_t safi;
718e3744 14501
d62a17ae 14502 afi = bgp_node_afi(vty);
14503 safi = bgp_node_safi(vty);
718e3744 14504
585f1adc
IR
14505 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14506 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14507 || bgp->distance_local[afi][safi] != distance_local) {
14508 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14509 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14510 bgp->distance_local[afi][safi] = distance_local;
14511 bgp_announce_routes_distance_update(bgp, afi, safi);
14512 }
14513 return CMD_SUCCESS;
14514}
37a87b8f 14515
585f1adc
IR
14516DEFUN (no_bgp_distance,
14517 no_bgp_distance_cmd,
14518 "no distance bgp [(1-255) (1-255) (1-255)]",
14519 NO_STR
14520 "Define an administrative distance\n"
14521 "BGP distance\n"
14522 "Distance for routes external to the AS\n"
14523 "Distance for routes internal to the AS\n"
14524 "Distance for local routes\n")
718e3744 14525{
585f1adc 14526 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14527 afi_t afi;
14528 safi_t safi;
37a87b8f
CS
14529
14530 afi = bgp_node_afi(vty);
14531 safi = bgp_node_safi(vty);
14532
585f1adc
IR
14533 if (bgp->distance_ebgp[afi][safi] != 0
14534 || bgp->distance_ibgp[afi][safi] != 0
14535 || bgp->distance_local[afi][safi] != 0) {
14536 bgp->distance_ebgp[afi][safi] = 0;
14537 bgp->distance_ibgp[afi][safi] = 0;
14538 bgp->distance_local[afi][safi] = 0;
14539 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14540 }
585f1adc
IR
14541 return CMD_SUCCESS;
14542}
37a87b8f 14543
37a87b8f 14544
585f1adc
IR
14545DEFUN (bgp_distance_source,
14546 bgp_distance_source_cmd,
14547 "distance (1-255) A.B.C.D/M",
14548 "Define an administrative distance\n"
14549 "Administrative distance\n"
14550 "IP source prefix\n")
14551{
14552 int idx_number = 1;
14553 int idx_ipv4_prefixlen = 2;
14554 bgp_distance_set(vty, argv[idx_number]->arg,
14555 argv[idx_ipv4_prefixlen]->arg, NULL);
14556 return CMD_SUCCESS;
734b349e
MZ
14557}
14558
585f1adc
IR
14559DEFUN (no_bgp_distance_source,
14560 no_bgp_distance_source_cmd,
14561 "no distance (1-255) A.B.C.D/M",
14562 NO_STR
14563 "Define an administrative distance\n"
14564 "Administrative distance\n"
14565 "IP source prefix\n")
37a87b8f 14566{
585f1adc
IR
14567 int idx_number = 2;
14568 int idx_ipv4_prefixlen = 3;
14569 bgp_distance_unset(vty, argv[idx_number]->arg,
14570 argv[idx_ipv4_prefixlen]->arg, NULL);
14571 return CMD_SUCCESS;
37a87b8f
CS
14572}
14573
585f1adc
IR
14574DEFUN (bgp_distance_source_access_list,
14575 bgp_distance_source_access_list_cmd,
14576 "distance (1-255) A.B.C.D/M WORD",
14577 "Define an administrative distance\n"
14578 "Administrative distance\n"
14579 "IP source prefix\n"
14580 "Access list name\n")
37a87b8f 14581{
585f1adc
IR
14582 int idx_number = 1;
14583 int idx_ipv4_prefixlen = 2;
14584 int idx_word = 3;
14585 bgp_distance_set(vty, argv[idx_number]->arg,
14586 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14587 return CMD_SUCCESS;
14588}
718e3744 14589
585f1adc
IR
14590DEFUN (no_bgp_distance_source_access_list,
14591 no_bgp_distance_source_access_list_cmd,
14592 "no distance (1-255) A.B.C.D/M WORD",
14593 NO_STR
14594 "Define an administrative distance\n"
14595 "Administrative distance\n"
14596 "IP source prefix\n"
14597 "Access list name\n")
14598{
14599 int idx_number = 2;
14600 int idx_ipv4_prefixlen = 3;
14601 int idx_word = 4;
14602 bgp_distance_unset(vty, argv[idx_number]->arg,
14603 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14604 return CMD_SUCCESS;
14605}
37a87b8f 14606
585f1adc
IR
14607DEFUN (ipv6_bgp_distance_source,
14608 ipv6_bgp_distance_source_cmd,
14609 "distance (1-255) X:X::X:X/M",
14610 "Define an administrative distance\n"
14611 "Administrative distance\n"
14612 "IP source prefix\n")
14613{
14614 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14615 return CMD_SUCCESS;
14616}
7ebe9748 14617
585f1adc
IR
14618DEFUN (no_ipv6_bgp_distance_source,
14619 no_ipv6_bgp_distance_source_cmd,
14620 "no distance (1-255) X:X::X:X/M",
14621 NO_STR
14622 "Define an administrative distance\n"
14623 "Administrative distance\n"
14624 "IP source prefix\n")
14625{
14626 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14627 return CMD_SUCCESS;
14628}
37a87b8f 14629
585f1adc
IR
14630DEFUN (ipv6_bgp_distance_source_access_list,
14631 ipv6_bgp_distance_source_access_list_cmd,
14632 "distance (1-255) X:X::X:X/M WORD",
14633 "Define an administrative distance\n"
14634 "Administrative distance\n"
14635 "IP source prefix\n"
14636 "Access list name\n")
14637{
14638 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14639 return CMD_SUCCESS;
718e3744 14640}
14641
585f1adc
IR
14642DEFUN (no_ipv6_bgp_distance_source_access_list,
14643 no_ipv6_bgp_distance_source_access_list_cmd,
14644 "no distance (1-255) X:X::X:X/M WORD",
14645 NO_STR
14646 "Define an administrative distance\n"
14647 "Administrative distance\n"
14648 "IP source prefix\n"
14649 "Access list name\n")
718e3744 14650{
585f1adc
IR
14651 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14652 return CMD_SUCCESS;
14653}
37a87b8f 14654
585f1adc
IR
14655DEFUN (bgp_damp_set,
14656 bgp_damp_set_cmd,
a30fec23 14657 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14658 "BGP Specific commands\n"
14659 "Enable route-flap dampening\n"
14660 "Half-life time for the penalty\n"
14661 "Value to start reusing a route\n"
14662 "Value to start suppressing a route\n"
14663 "Maximum duration to suppress a stable route\n")
14664{
14665 VTY_DECLVAR_CONTEXT(bgp, bgp);
14666 int idx_half_life = 2;
14667 int idx_reuse = 3;
14668 int idx_suppress = 4;
14669 int idx_max_suppress = 5;
37a87b8f
CS
14670 int half = DEFAULT_HALF_LIFE * 60;
14671 int reuse = DEFAULT_REUSE;
14672 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14673 int max = 4 * half;
14674
14675 if (argc == 6) {
14676 half = atoi(argv[idx_half_life]->arg) * 60;
14677 reuse = atoi(argv[idx_reuse]->arg);
14678 suppress = atoi(argv[idx_suppress]->arg);
14679 max = atoi(argv[idx_max_suppress]->arg) * 60;
14680 } else if (argc == 3) {
14681 half = atoi(argv[idx_half_life]->arg) * 60;
14682 max = 4 * half;
14683 }
14684
14685 /*
14686 * These can't be 0 but our SA doesn't understand the
14687 * way our cli is constructed
14688 */
14689 assert(reuse);
14690 assert(half);
14691 if (suppress < reuse) {
14692 vty_out(vty,
14693 "Suppress value cannot be less than reuse value \n");
14694 return 0;
14695 }
14696
14697 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14698 reuse, suppress, max);
14699}
14700
14701DEFUN (bgp_damp_unset,
14702 bgp_damp_unset_cmd,
a30fec23 14703 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14704 NO_STR
14705 "BGP Specific commands\n"
14706 "Enable route-flap dampening\n"
14707 "Half-life time for the penalty\n"
14708 "Value to start reusing a route\n"
14709 "Value to start suppressing a route\n"
14710 "Maximum duration to suppress a stable route\n")
14711{
14712 VTY_DECLVAR_CONTEXT(bgp, bgp);
14713 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14714}
14715
718e3744 14716/* Display specified route of BGP table. */
d62a17ae 14717static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14718 const char *ip_str, afi_t afi, safi_t safi,
14719 struct prefix_rd *prd, int prefix_check)
14720{
14721 int ret;
14722 struct prefix match;
9bcb3eef
DS
14723 struct bgp_dest *dest;
14724 struct bgp_dest *rm;
40381db7
DS
14725 struct bgp_path_info *pi;
14726 struct bgp_path_info *pi_temp;
d62a17ae 14727 struct bgp *bgp;
14728 struct bgp_table *table;
14729
14730 /* BGP structure lookup. */
14731 if (view_name) {
14732 bgp = bgp_lookup_by_name(view_name);
14733 if (bgp == NULL) {
14734 vty_out(vty, "%% Can't find BGP instance %s\n",
14735 view_name);
14736 return CMD_WARNING;
14737 }
14738 } else {
14739 bgp = bgp_get_default();
14740 if (bgp == NULL) {
14741 vty_out(vty, "%% No BGP process is configured\n");
14742 return CMD_WARNING;
14743 }
718e3744 14744 }
718e3744 14745
d62a17ae 14746 /* Check IP address argument. */
14747 ret = str2prefix(ip_str, &match);
14748 if (!ret) {
14749 vty_out(vty, "%% address is malformed\n");
14750 return CMD_WARNING;
14751 }
718e3744 14752
d62a17ae 14753 match.family = afi2family(afi);
14754
14755 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14756 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14757 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14758 dest = bgp_route_next(dest)) {
14759 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14760
9bcb3eef 14761 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14762 continue;
9bcb3eef 14763 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14764 if (!table)
ea47320b 14765 continue;
4953391b
DA
14766 rm = bgp_node_match(table, &match);
14767 if (rm == NULL)
ea47320b 14768 continue;
d62a17ae 14769
9bcb3eef 14770 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14771
ea47320b 14772 if (!prefix_check
b54892e0 14773 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14774 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14775 while (pi) {
14776 if (pi->extra && pi->extra->damp_info) {
14777 pi_temp = pi->next;
ea47320b 14778 bgp_damp_info_free(
19971c9a 14779 pi->extra->damp_info,
5c8846f6 14780 1, afi, safi);
40381db7 14781 pi = pi_temp;
ea47320b 14782 } else
40381db7 14783 pi = pi->next;
d62a17ae 14784 }
ea47320b
DL
14785 }
14786
9bcb3eef 14787 bgp_dest_unlock_node(rm);
d62a17ae 14788 }
14789 } else {
4953391b
DA
14790 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14791 if (dest != NULL) {
9bcb3eef 14792 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14793
d62a17ae 14794 if (!prefix_check
9bcb3eef
DS
14795 || dest_p->prefixlen == match.prefixlen) {
14796 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14797 while (pi) {
14798 if (pi->extra && pi->extra->damp_info) {
14799 pi_temp = pi->next;
d62a17ae 14800 bgp_damp_info_free(
19971c9a 14801 pi->extra->damp_info,
5c8846f6 14802 1, afi, safi);
40381db7 14803 pi = pi_temp;
d62a17ae 14804 } else
40381db7 14805 pi = pi->next;
d62a17ae 14806 }
14807 }
14808
9bcb3eef 14809 bgp_dest_unlock_node(dest);
d62a17ae 14810 }
14811 }
718e3744 14812
d62a17ae 14813 return CMD_SUCCESS;
718e3744 14814}
14815
14816DEFUN (clear_ip_bgp_dampening,
14817 clear_ip_bgp_dampening_cmd,
14818 "clear ip bgp dampening",
14819 CLEAR_STR
14820 IP_STR
14821 BGP_STR
14822 "Clear route flap dampening information\n")
14823{
b4f7f45b 14824 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14825 return CMD_SUCCESS;
718e3744 14826}
14827
14828DEFUN (clear_ip_bgp_dampening_prefix,
14829 clear_ip_bgp_dampening_prefix_cmd,
14830 "clear ip bgp dampening A.B.C.D/M",
14831 CLEAR_STR
14832 IP_STR
14833 BGP_STR
14834 "Clear route flap dampening information\n"
0c7b1b01 14835 "IPv4 prefix\n")
718e3744 14836{
d62a17ae 14837 int idx_ipv4_prefixlen = 4;
14838 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14839 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14840}
14841
14842DEFUN (clear_ip_bgp_dampening_address,
14843 clear_ip_bgp_dampening_address_cmd,
14844 "clear ip bgp dampening A.B.C.D",
14845 CLEAR_STR
14846 IP_STR
14847 BGP_STR
14848 "Clear route flap dampening information\n"
14849 "Network to clear damping information\n")
14850{
d62a17ae 14851 int idx_ipv4 = 4;
14852 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14853 SAFI_UNICAST, NULL, 0);
718e3744 14854}
14855
14856DEFUN (clear_ip_bgp_dampening_address_mask,
14857 clear_ip_bgp_dampening_address_mask_cmd,
14858 "clear ip bgp dampening A.B.C.D A.B.C.D",
14859 CLEAR_STR
14860 IP_STR
14861 BGP_STR
14862 "Clear route flap dampening information\n"
14863 "Network to clear damping information\n"
14864 "Network mask\n")
14865{
d62a17ae 14866 int idx_ipv4 = 4;
14867 int idx_ipv4_2 = 5;
14868 int ret;
14869 char prefix_str[BUFSIZ];
718e3744 14870
d62a17ae 14871 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14872 prefix_str, sizeof(prefix_str));
d62a17ae 14873 if (!ret) {
14874 vty_out(vty, "%% Inconsistent address and mask\n");
14875 return CMD_WARNING;
14876 }
718e3744 14877
d62a17ae 14878 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14879 NULL, 0);
718e3744 14880}
6b0655a2 14881
e3b78da8 14882static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14883{
14884 struct vty *vty = arg;
e3b78da8 14885 struct peer *peer = bucket->data;
825d9834
DS
14886 char buf[SU_ADDRSTRLEN];
14887
14888 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14889 sockunion2str(&peer->su, buf, sizeof(buf)));
14890}
14891
2a0e69ae
DS
14892DEFUN (show_bgp_listeners,
14893 show_bgp_listeners_cmd,
14894 "show bgp listeners",
14895 SHOW_STR
14896 BGP_STR
14897 "Display Listen Sockets and who created them\n")
14898{
14899 bgp_dump_listener_info(vty);
14900
14901 return CMD_SUCCESS;
14902}
14903
825d9834
DS
14904DEFUN (show_bgp_peerhash,
14905 show_bgp_peerhash_cmd,
14906 "show bgp peerhash",
14907 SHOW_STR
14908 BGP_STR
14909 "Display information about the BGP peerhash\n")
14910{
14911 struct list *instances = bm->bgp;
14912 struct listnode *node;
14913 struct bgp *bgp;
14914
14915 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14916 vty_out(vty, "BGP: %s\n", bgp->name);
14917 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14918 vty);
14919 }
14920
14921 return CMD_SUCCESS;
14922}
14923
587ff0fd 14924/* also used for encap safi */
2b791107
DL
14925static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14926 afi_t afi, safi_t safi)
d62a17ae 14927{
9bcb3eef
DS
14928 struct bgp_dest *pdest;
14929 struct bgp_dest *dest;
d62a17ae 14930 struct bgp_table *table;
b54892e0
DS
14931 const struct prefix *p;
14932 const struct prefix_rd *prd;
d62a17ae 14933 struct bgp_static *bgp_static;
14934 mpls_label_t label;
d62a17ae 14935 char rdbuf[RD_ADDRSTRLEN];
14936
14937 /* Network configuration. */
9bcb3eef
DS
14938 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14939 pdest = bgp_route_next(pdest)) {
14940 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14941 if (!table)
ea47320b 14942 continue;
d62a17ae 14943
9bcb3eef
DS
14944 for (dest = bgp_table_top(table); dest;
14945 dest = bgp_route_next(dest)) {
14946 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14947 if (bgp_static == NULL)
ea47320b 14948 continue;
d62a17ae 14949
9bcb3eef
DS
14950 p = bgp_dest_get_prefix(dest);
14951 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14952 pdest);
d62a17ae 14953
ea47320b 14954 /* "network" configuration display. */
06b9f471 14955 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14956 label = decode_label(&bgp_static->label);
14957
8228a9a7 14958 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14959 if (safi == SAFI_MPLS_VPN)
14960 vty_out(vty, " label %u", label);
14961
14962 if (bgp_static->rmap.name)
14963 vty_out(vty, " route-map %s",
14964 bgp_static->rmap.name);
e2a86ad9
DS
14965
14966 if (bgp_static->backdoor)
14967 vty_out(vty, " backdoor");
14968
ea47320b
DL
14969 vty_out(vty, "\n");
14970 }
14971 }
d62a17ae 14972}
14973
2b791107
DL
14974static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14975 afi_t afi, safi_t safi)
d62a17ae 14976{
9bcb3eef
DS
14977 struct bgp_dest *pdest;
14978 struct bgp_dest *dest;
d62a17ae 14979 struct bgp_table *table;
b54892e0
DS
14980 const struct prefix *p;
14981 const struct prefix_rd *prd;
d62a17ae 14982 struct bgp_static *bgp_static;
ff44f570 14983 char buf[PREFIX_STRLEN * 2];
d62a17ae 14984 char buf2[SU_ADDRSTRLEN];
14985 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14986 char esi_buf[ESI_BYTES];
d62a17ae 14987
14988 /* Network configuration. */
9bcb3eef
DS
14989 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14990 pdest = bgp_route_next(pdest)) {
14991 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14992 if (!table)
ea47320b 14993 continue;
d62a17ae 14994
9bcb3eef
DS
14995 for (dest = bgp_table_top(table); dest;
14996 dest = bgp_route_next(dest)) {
14997 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14998 if (bgp_static == NULL)
ea47320b 14999 continue;
d62a17ae 15000
ea47320b 15001 char *macrouter = NULL;
d62a17ae 15002
ea47320b
DL
15003 if (bgp_static->router_mac)
15004 macrouter = prefix_mac2str(
15005 bgp_static->router_mac, NULL, 0);
15006 if (bgp_static->eth_s_id)
0a50c248
AK
15007 esi_to_str(bgp_static->eth_s_id,
15008 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15009 p = bgp_dest_get_prefix(dest);
15010 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15011
ea47320b 15012 /* "network" configuration display. */
06b9f471 15013 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15014 if (p->u.prefix_evpn.route_type == 5) {
15015 char local_buf[PREFIX_STRLEN];
3714a385 15016 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15017 struct prefix_evpn *)p)
15018 ? AF_INET
15019 : AF_INET6;
3714a385 15020 inet_ntop(family,
15021 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15022 local_buf, PREFIX_STRLEN);
772270f3
QY
15023 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15024 p->u.prefix_evpn.prefix_addr
15025 .ip_prefix_length);
197cb530
PG
15026 } else {
15027 prefix2str(p, buf, sizeof(buf));
15028 }
ea47320b 15029
a4d82a8a
PZ
15030 if (bgp_static->gatewayIp.family == AF_INET
15031 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15032 inet_ntop(bgp_static->gatewayIp.family,
15033 &bgp_static->gatewayIp.u.prefix, buf2,
15034 sizeof(buf2));
ea47320b 15035 vty_out(vty,
7bcc8dac 15036 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15037 buf, rdbuf,
15038 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15039 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15040 macrouter);
15041
0a22ddfb 15042 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15043 }
15044 }
3da6fcd5
PG
15045}
15046
718e3744 15047/* Configuration of static route announcement and aggregate
15048 information. */
2b791107
DL
15049void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15050 safi_t safi)
d62a17ae 15051{
9bcb3eef 15052 struct bgp_dest *dest;
b54892e0 15053 const struct prefix *p;
d62a17ae 15054 struct bgp_static *bgp_static;
15055 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15056
2b791107
DL
15057 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15058 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15059 return;
15060 }
d62a17ae 15061
2b791107
DL
15062 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15063 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15064 return;
15065 }
d62a17ae 15066
15067 /* Network configuration. */
9bcb3eef
DS
15068 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15069 dest = bgp_route_next(dest)) {
15070 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15071 if (bgp_static == NULL)
ea47320b 15072 continue;
d62a17ae 15073
9bcb3eef 15074 p = bgp_dest_get_prefix(dest);
d62a17ae 15075
8228a9a7 15076 vty_out(vty, " network %pFX", p);
d62a17ae 15077
ea47320b
DL
15078 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15079 vty_out(vty, " label-index %u",
15080 bgp_static->label_index);
d62a17ae 15081
ea47320b
DL
15082 if (bgp_static->rmap.name)
15083 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15084
15085 if (bgp_static->backdoor)
15086 vty_out(vty, " backdoor");
718e3744 15087
ea47320b
DL
15088 vty_out(vty, "\n");
15089 }
15090
d62a17ae 15091 /* Aggregate-address configuration. */
9bcb3eef
DS
15092 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15093 dest = bgp_route_next(dest)) {
15094 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15095 if (bgp_aggregate == NULL)
ea47320b 15096 continue;
d62a17ae 15097
9bcb3eef 15098 p = bgp_dest_get_prefix(dest);
d62a17ae 15099
8228a9a7 15100 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15101
ea47320b
DL
15102 if (bgp_aggregate->as_set)
15103 vty_out(vty, " as-set");
d62a17ae 15104
ea47320b
DL
15105 if (bgp_aggregate->summary_only)
15106 vty_out(vty, " summary-only");
718e3744 15107
20894f50
DA
15108 if (bgp_aggregate->rmap.name)
15109 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15110
229757f1
DA
15111 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15112 vty_out(vty, " origin %s",
15113 bgp_origin2str(bgp_aggregate->origin));
15114
6aabb15d
RZ
15115 if (bgp_aggregate->match_med)
15116 vty_out(vty, " matching-MED-only");
15117
365ab2e7
RZ
15118 if (bgp_aggregate->suppress_map_name)
15119 vty_out(vty, " suppress-map %s",
15120 bgp_aggregate->suppress_map_name);
15121
ea47320b
DL
15122 vty_out(vty, "\n");
15123 }
d62a17ae 15124}
734b349e 15125
2b791107 15126void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15127 safi_t safi)
d62a17ae 15128{
9bcb3eef 15129 struct bgp_dest *dest;
d62a17ae 15130 struct bgp_distance *bdistance;
15131
15132 /* Distance configuration. */
15133 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15134 && bgp->distance_local[afi][safi]
15135 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15136 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15137 || bgp->distance_local[afi][safi]
15138 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15139 vty_out(vty, " distance bgp %d %d %d\n",
15140 bgp->distance_ebgp[afi][safi],
15141 bgp->distance_ibgp[afi][safi],
15142 bgp->distance_local[afi][safi]);
15143 }
734b349e 15144
9bcb3eef
DS
15145 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15146 dest = bgp_route_next(dest)) {
15147 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15148 if (bdistance != NULL)
56ca3b5b 15149 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15150 bdistance->distance, dest,
d62a17ae 15151 bdistance->access_list ? bdistance->access_list
15152 : "");
ca2e160d 15153 }
718e3744 15154}
15155
15156/* Allocate routing table structure and install commands. */
d62a17ae 15157void bgp_route_init(void)
15158{
15159 afi_t afi;
15160 safi_t safi;
15161
15162 /* Init BGP distance table. */
05c7a1cc 15163 FOREACH_AFI_SAFI (afi, safi)
960035b2 15164 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15165
15166 /* IPv4 BGP commands. */
15167 install_element(BGP_NODE, &bgp_table_map_cmd);
15168 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15169 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15170
554b3b10 15171 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15172
15173 /* IPv4 unicast configuration. */
15174 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15175 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15176 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15177
554b3b10 15178 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15179
15180 /* IPv4 multicast configuration. */
15181 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15182 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15183 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15184 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15185
15186 /* IPv4 labeled-unicast configuration. */
fb985e0c 15187 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15188 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15189
d62a17ae 15190 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15191 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15192 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15193 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15194 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15195 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15196 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15197 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15198
15199 install_element(VIEW_NODE,
15200 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15201 install_element(VIEW_NODE,
15202 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15203 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15204 install_element(VIEW_NODE,
15205 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15206#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15207 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15208#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15209 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15210 install_element(VIEW_NODE,
44c69747 15211 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15212
d62a17ae 15213 /* BGP dampening clear commands */
15214 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15215 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15216
d62a17ae 15217 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15218 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15219
15220 /* prefix count */
15221 install_element(ENABLE_NODE,
15222 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15223#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15224 install_element(ENABLE_NODE,
15225 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15226#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15227
d62a17ae 15228 /* New config IPv6 BGP commands. */
15229 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15230 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15231 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15232
554b3b10 15233 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15234
15235 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15236
fb985e0c
DA
15237 /* IPv6 labeled unicast address family. */
15238 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15239 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15240
d62a17ae 15241 install_element(BGP_NODE, &bgp_distance_cmd);
15242 install_element(BGP_NODE, &no_bgp_distance_cmd);
15243 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15244 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15245 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15246 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15247 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15248 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15249 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15250 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15251 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15252 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15253 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15254 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15255 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15256 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15257 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15258 install_element(BGP_IPV4M_NODE,
15259 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15260 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15261 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15262 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15263 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15264 install_element(BGP_IPV6_NODE,
15265 &ipv6_bgp_distance_source_access_list_cmd);
15266 install_element(BGP_IPV6_NODE,
15267 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15268 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15269 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15270 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15271 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15272 install_element(BGP_IPV6M_NODE,
15273 &ipv6_bgp_distance_source_access_list_cmd);
15274 install_element(BGP_IPV6M_NODE,
15275 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15276
ef5f4b23 15277 /* BGP dampening */
585f1adc
IR
15278 install_element(BGP_NODE, &bgp_damp_set_cmd);
15279 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15280 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15281 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15282 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15283 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15284 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15285 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15286 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15287 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15288 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15289 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15290 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15291 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15292
15293 /* Large Communities */
15294 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15295 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15296
15297 /* show bgp ipv4 flowspec detailed */
15298 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15299
2a0e69ae 15300 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15301 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15302}
15303
15304void bgp_route_finish(void)
15305{
15306 afi_t afi;
15307 safi_t safi;
15308
05c7a1cc
QY
15309 FOREACH_AFI_SAFI (afi, safi) {
15310 bgp_table_unlock(bgp_distance_table[afi][safi]);
15311 bgp_distance_table[afi][safi] = NULL;
15312 }
228da428 15313}