]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #8065 from donaldsharp/foo_master
[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"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
6401252f 73#include "bgpd/bgp_trace.h"
718e3744 74
49e5a4a0 75#ifdef ENABLE_BGP_VNC
f8b6f499
LB
76#include "bgpd/rfapi/rfapi_backend.h"
77#include "bgpd/rfapi/vnc_import_bgp.h"
78#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 79#endif
aee875b5
PG
80#include "bgpd/bgp_encap_types.h"
81#include "bgpd/bgp_encap_tlv.h"
684a7227 82#include "bgpd/bgp_evpn.h"
0a50c248 83#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 84#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 85#include "bgpd/bgp_flowspec.h"
98a9dbc7 86#include "bgpd/bgp_flowspec_util.h"
45918cfb 87#include "bgpd/bgp_pbr.h"
37a87b8f
CS
88#include "northbound.h"
89#include "northbound_cli.h"
90#include "bgpd/bgp_nb.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),
98 (rn, pi, added))
99
718e3744 100/* Extern from bgp_dump.c */
dde72586
SH
101extern const char *bgp_origin_str[];
102extern const char *bgp_origin_long_str[];
3742de8d 103
b7d08f5a 104/* PMSI strings. */
105#define PMSI_TNLTYPE_STR_NO_INFO "No info"
106#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
107static const struct message bgp_pmsi_tnltype_str[] = {
108 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
109 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
110 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
111 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
112 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
113 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
114 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
115 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 116 {0}
117};
b7d08f5a 118
9df8b37c
PZ
119#define VRFID_NONE_STR "-"
120
4a11bf2c 121DEFINE_HOOK(bgp_process,
9bcb3eef
DS
122 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
123 struct peer *peer, bool withdraw),
124 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c 125
4056a5f6
RZ
126/** Test if path is suppressed. */
127static bool bgp_path_suppressed(struct bgp_path_info *pi)
128{
129 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
130 return false;
131
132 return listcount(pi->extra->aggr_suppressors) > 0;
133}
4a11bf2c 134
9bcb3eef 135struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 136 safi_t safi, const struct prefix *p,
d62a17ae 137 struct prefix_rd *prd)
138{
9bcb3eef
DS
139 struct bgp_dest *dest;
140 struct bgp_dest *pdest = NULL;
d62a17ae 141
142 assert(table);
d62a17ae 143
144 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
145 || (safi == SAFI_EVPN)) {
9bcb3eef 146 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 147
9bcb3eef
DS
148 if (!bgp_dest_has_bgp_path_info_data(pdest))
149 bgp_dest_set_bgp_table_info(
150 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 151 else
9bcb3eef
DS
152 bgp_dest_unlock_node(pdest);
153 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 154 }
718e3744 155
9bcb3eef 156 dest = bgp_node_get(table, p);
718e3744 157
d62a17ae 158 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
159 || (safi == SAFI_EVPN))
9bcb3eef 160 dest->pdest = pdest;
718e3744 161
9bcb3eef 162 return dest;
718e3744 163}
6b0655a2 164
9bcb3eef 165struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 166 safi_t safi, const struct prefix *p,
d62a17ae 167 struct prefix_rd *prd)
128ea8ab 168{
9bcb3eef
DS
169 struct bgp_dest *dest;
170 struct bgp_dest *pdest = NULL;
128ea8ab 171
d62a17ae 172 if (!table)
173 return NULL;
128ea8ab 174
d62a17ae 175 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
176 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
177 pdest = bgp_node_lookup(table, (struct prefix *)prd);
178 if (!pdest)
d62a17ae 179 return NULL;
128ea8ab 180
9bcb3eef
DS
181 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
182 bgp_dest_unlock_node(pdest);
d62a17ae 183 return NULL;
184 }
128ea8ab 185
9bcb3eef 186 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 187 }
128ea8ab 188
9bcb3eef 189 dest = bgp_node_lookup(table, p);
128ea8ab 190
9bcb3eef 191 return dest;
128ea8ab 192}
193
18ee8310
DS
194/* Allocate bgp_path_info_extra */
195static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 196{
4b7e6066
DS
197 struct bgp_path_info_extra *new;
198 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
199 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
200 new->label[0] = MPLS_INVALID_LABEL;
201 new->num_labels = 0;
3e3708cb
PG
202 new->bgp_fs_pbr = NULL;
203 new->bgp_fs_iprule = NULL;
d62a17ae 204 return new;
fb982c25
PJ
205}
206
a2e219fe 207void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 208{
4b7e6066 209 struct bgp_path_info_extra *e;
d62a17ae 210
c93a3b77
DS
211 if (!extra || !*extra)
212 return;
d62a17ae 213
c93a3b77 214 e = *extra;
d62a17ae 215
c93a3b77
DS
216 e->damp_info = NULL;
217 if (e->parent) {
40381db7 218 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 219
40381db7 220 if (bpi->net) {
0e70e6c8
DL
221 /* FIXME: since multiple e may have the same e->parent
222 * and e->parent->net is holding a refcount for each
223 * of them, we need to do some fudging here.
224 *
40381db7
DS
225 * WARNING: if bpi->net->lock drops to 0, bpi may be
226 * freed as well (because bpi->net was holding the
227 * last reference to bpi) => write after free!
0e70e6c8
DL
228 */
229 unsigned refcount;
230
40381db7 231 bpi = bgp_path_info_lock(bpi);
c10e14e9 232 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 233 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 234 if (!refcount)
40381db7
DS
235 bpi->net = NULL;
236 bgp_path_info_unlock(bpi);
0e70e6c8 237 }
18ee8310 238 bgp_path_info_unlock(e->parent);
c93a3b77 239 e->parent = NULL;
d62a17ae 240 }
c93a3b77
DS
241
242 if (e->bgp_orig)
243 bgp_unlock(e->bgp_orig);
c26edcda 244
ff3bf9a4
DS
245 if (e->aggr_suppressors)
246 list_delete(&e->aggr_suppressors);
247
26c03e43
AK
248 if (e->es_info)
249 bgp_evpn_path_es_info_free(e->es_info);
250
ce3c0614
PG
251 if ((*extra)->bgp_fs_iprule)
252 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 253 if ((*extra)->bgp_fs_pbr)
6a154c88 254 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 255 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
256}
257
18ee8310
DS
258/* Get bgp_path_info extra information for the given bgp_path_info, lazy
259 * allocated if required.
fb982c25 260 */
40381db7 261struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 262{
40381db7
DS
263 if (!pi->extra)
264 pi->extra = bgp_path_info_extra_new();
265 return pi->extra;
fb982c25
PJ
266}
267
718e3744 268/* Free bgp route information. */
9b6d8fcf 269static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 270{
05864da7 271 bgp_attr_unintern(&path->attr);
fb018d25 272
9b6d8fcf
DS
273 bgp_unlink_nexthop(path);
274 bgp_path_info_extra_free(&path->extra);
275 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
276 if (path->net)
277 bgp_addpath_free_info_data(&path->tx_addpath,
278 &path->net->tx_addpath);
718e3744 279
9b6d8fcf 280 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 281
9b6d8fcf 282 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 283}
284
9b6d8fcf 285struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 286{
9b6d8fcf
DS
287 path->lock++;
288 return path;
200df115 289}
290
9b6d8fcf 291struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 292{
9b6d8fcf
DS
293 assert(path && path->lock > 0);
294 path->lock--;
d62a17ae 295
9b6d8fcf 296 if (path->lock == 0) {
200df115 297#if 0
298 zlog_debug ("%s: unlocked and freeing", __func__);
299 zlog_backtrace (LOG_DEBUG);
300#endif
9b6d8fcf 301 bgp_path_info_free(path);
d62a17ae 302 return NULL;
303 }
200df115 304
305#if 0
9b6d8fcf 306 if (path->lock == 1)
200df115 307 {
308 zlog_debug ("%s: unlocked to 1", __func__);
309 zlog_backtrace (LOG_DEBUG);
310 }
311#endif
d62a17ae 312
9b6d8fcf 313 return path;
200df115 314}
315
f009ff26 316/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 317static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 318{
319 struct peer *peer;
320 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 321 bool set_flag = false;
f009ff26 322 struct bgp *bgp = NULL;
323 struct bgp_table *table = NULL;
324 afi_t afi = 0;
325 safi_t safi = 0;
f009ff26 326
327 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
328 * then the route selection is deferred
329 */
9bcb3eef 330 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 331 return 0;
332
9bcb3eef 333 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 334 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 335 zlog_debug(
56ca3b5b
DL
336 "Route %pBD is in workqueue and being processed, not deferred.",
337 dest);
b54892e0 338
5f9c1aa2 339 return 0;
340 }
341
9bcb3eef 342 table = bgp_dest_table(dest);
f009ff26 343 if (table) {
344 bgp = table->bgp;
345 afi = table->afi;
346 safi = table->safi;
347 }
348
9bcb3eef 349 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 350 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
351 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
352 continue;
353
354 /* Route selection is deferred if there is a stale path which
355 * which indicates peer is in restart mode
356 */
36235319
QY
357 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
358 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 359 set_flag = true;
f009ff26 360 } else {
361 /* If the peer is graceful restart capable and peer is
362 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
363 */
364 peer = old_pi->peer;
36235319
QY
365 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
366 && BGP_PEER_RESTARTING_MODE(peer)
367 && (old_pi
368 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 369 set_flag = true;
f009ff26 370 }
371 }
372 if (set_flag)
373 break;
374 }
375
376 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
377 * is active
378 */
2ba1fe69 379 if (set_flag && table) {
f009ff26 380 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
381 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
382 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 383 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 384 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
385 zlog_debug("DEFER route %pBD, dest %p", dest,
386 dest);
f009ff26 387 return 0;
388 }
389 }
390 return -1;
391}
392
9bcb3eef 393void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 394{
4b7e6066 395 struct bgp_path_info *top;
718e3744 396
9bcb3eef 397 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 398
6f94b685 399 pi->next = top;
40381db7 400 pi->prev = NULL;
d62a17ae 401 if (top)
40381db7 402 top->prev = pi;
9bcb3eef 403 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 404
40381db7 405 bgp_path_info_lock(pi);
9bcb3eef 406 bgp_dest_lock_node(dest);
40381db7 407 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 408 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 409 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 410}
411
d62a17ae 412/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 413 completion callback *only* */
9bcb3eef 414void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 415{
40381db7
DS
416 if (pi->next)
417 pi->next->prev = pi->prev;
418 if (pi->prev)
419 pi->prev->next = pi->next;
d62a17ae 420 else
9bcb3eef 421 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 422
40381db7
DS
423 bgp_path_info_mpath_dequeue(pi);
424 bgp_path_info_unlock(pi);
7fd28dd2 425 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 426 bgp_dest_unlock_node(dest);
718e3744 427}
428
9bcb3eef 429void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 430{
9bcb3eef 431 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 432 /* set of previous already took care of pcount */
40381db7 433 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 434}
435
18ee8310 436/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
437 called when a route is deleted and then quickly re-added before the
438 deletion has been processed */
9bcb3eef 439void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 440{
9bcb3eef 441 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 442 /* unset of previous already took care of pcount */
40381db7 443 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
444}
445
d62a17ae 446/* Adjust pcount as required */
9bcb3eef 447static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 448{
d62a17ae 449 struct bgp_table *table;
67174041 450
9bcb3eef 451 assert(dest && bgp_dest_table(dest));
40381db7 452 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 453
9bcb3eef 454 table = bgp_dest_table(dest);
67174041 455
40381db7 456 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 457 return;
458
40381db7
DS
459 if (!BGP_PATH_COUNTABLE(pi)
460 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 461
40381db7 462 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 463
464 /* slight hack, but more robust against errors. */
40381db7
DS
465 if (pi->peer->pcount[table->afi][table->safi])
466 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 467 else
450971aa 468 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 469 "Asked to decrement 0 prefix count for peer");
40381db7
DS
470 } else if (BGP_PATH_COUNTABLE(pi)
471 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
472 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
473 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 474 }
1a392d46
PJ
475}
476
40381db7
DS
477static int bgp_label_index_differs(struct bgp_path_info *pi1,
478 struct bgp_path_info *pi2)
28d58fd7 479{
40381db7 480 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 481}
1a392d46 482
18ee8310 483/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
484 * This is here primarily to keep prefix-count in check.
485 */
9bcb3eef 486void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 487 uint32_t flag)
1a392d46 488{
40381db7 489 SET_FLAG(pi->flags, flag);
d62a17ae 490
491 /* early bath if we know it's not a flag that changes countability state
492 */
493 if (!CHECK_FLAG(flag,
1defdda8 494 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 495 return;
496
9bcb3eef 497 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
498}
499
9bcb3eef 500void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 501 uint32_t flag)
1a392d46 502{
40381db7 503 UNSET_FLAG(pi->flags, flag);
d62a17ae 504
505 /* early bath if we know it's not a flag that changes countability state
506 */
507 if (!CHECK_FLAG(flag,
1defdda8 508 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 509 return;
510
9bcb3eef 511 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
512}
513
718e3744 514/* Get MED value. If MED value is missing and "bgp bestpath
515 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 516static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 517{
518 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
519 return attr->med;
520 else {
892fedb6 521 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 522 return BGP_MED_MAX;
523 else
524 return 0;
525 }
718e3744 526}
527
40381db7 528void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 529{
40381db7
DS
530 if (pi->addpath_rx_id)
531 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
532 pi->addpath_rx_id);
d62a17ae 533 else
40381db7 534 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 535}
9fbdd100 536
d62a17ae 537/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
538 */
18ee8310
DS
539static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
540 struct bgp_path_info *exist, int *paths_eq,
541 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
542 char *pfx_buf, afi_t afi, safi_t safi,
543 enum bgp_path_selection_reason *reason)
d62a17ae 544{
545 struct attr *newattr, *existattr;
546 bgp_peer_sort_t new_sort;
547 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
548 uint32_t new_pref;
549 uint32_t exist_pref;
550 uint32_t new_med;
551 uint32_t exist_med;
552 uint32_t new_weight;
553 uint32_t exist_weight;
d62a17ae 554 uint32_t newm, existm;
555 struct in_addr new_id;
556 struct in_addr exist_id;
557 int new_cluster;
558 int exist_cluster;
559 int internal_as_route;
560 int confed_as_route;
04d14c8b 561 int ret = 0;
d62a17ae 562 char new_buf[PATH_ADDPATH_STR_BUFFER];
563 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
564 uint32_t new_mm_seq;
565 uint32_t exist_mm_seq;
6d8c603a 566 int nh_cmp;
d071f237
AK
567 esi_t *exist_esi;
568 esi_t *new_esi;
569 bool same_esi;
570 bool old_proxy;
571 bool new_proxy;
33c6e933 572 bool new_origin, exist_origin;
d62a17ae 573
574 *paths_eq = 0;
575
576 /* 0. Null check. */
577 if (new == NULL) {
fdf81fa0 578 *reason = bgp_path_selection_none;
d62a17ae 579 if (debug)
580 zlog_debug("%s: new is NULL", pfx_buf);
581 return 0;
582 }
2ec1e66f 583
d62a17ae 584 if (debug)
18ee8310 585 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 586
d62a17ae 587 if (exist == NULL) {
fdf81fa0 588 *reason = bgp_path_selection_first;
d62a17ae 589 if (debug)
590 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
591 new_buf);
592 return 1;
593 }
2ec1e66f 594
d62a17ae 595 if (debug) {
18ee8310 596 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 597 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
598 pfx_buf, new_buf, new->flags, exist_buf,
599 exist->flags);
600 }
8ff56318 601
d62a17ae 602 newattr = new->attr;
603 existattr = exist->attr;
604
605 /* For EVPN routes, we cannot just go by local vs remote, we have to
606 * look at the MAC mobility sequence number, if present.
607 */
608 if (safi == SAFI_EVPN) {
609 /* This is an error condition described in RFC 7432 Section
610 * 15.2. The RFC
611 * states that in this scenario "the PE MUST alert the operator"
612 * but it
613 * does not state what other action to take. In order to provide
614 * some
615 * consistency in this scenario we are going to prefer the path
616 * with the
617 * sticky flag.
618 */
619 if (newattr->sticky != existattr->sticky) {
620 if (!debug) {
9bcb3eef
DS
621 prefix2str(
622 bgp_dest_get_prefix(new->net), pfx_buf,
623 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
624 bgp_path_info_path_with_addpath_rx_str(new,
625 new_buf);
626 bgp_path_info_path_with_addpath_rx_str(
627 exist, exist_buf);
d62a17ae 628 }
629
630 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 631 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
632 if (debug)
633 zlog_debug(
634 "%s: %s wins over %s due to sticky MAC flag",
635 pfx_buf, new_buf, exist_buf);
d62a17ae 636 return 1;
637 }
638
639 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 640 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
641 if (debug)
642 zlog_debug(
643 "%s: %s loses to %s due to sticky MAC flag",
644 pfx_buf, new_buf, exist_buf);
d62a17ae 645 return 0;
646 }
647 }
128ea8ab 648
d071f237
AK
649 new_esi = bgp_evpn_attr_get_esi(newattr);
650 exist_esi = bgp_evpn_attr_get_esi(existattr);
651 if (bgp_evpn_is_esi_valid(new_esi) &&
652 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
653 same_esi = true;
654 } else {
655 same_esi = false;
656 }
657
658 /* If both paths have the same non-zero ES and
659 * one path is local it wins.
660 * PS: Note the local path wins even if the remote
661 * has the higher MM seq. The local path's
662 * MM seq will be fixed up to match the highest
663 * rem seq, subsequently.
664 */
665 if (same_esi) {
666 char esi_buf[ESI_STR_LEN];
667
668 if (bgp_evpn_is_path_local(bgp, new)) {
669 *reason = bgp_path_selection_evpn_local_path;
670 if (debug)
671 zlog_debug(
672 "%s: %s wins over %s as ES %s is same and local",
673 pfx_buf, new_buf, exist_buf,
674 esi_to_str(new_esi, esi_buf,
675 sizeof(esi_buf)));
676 return 1;
677 }
678 if (bgp_evpn_is_path_local(bgp, exist)) {
679 *reason = bgp_path_selection_evpn_local_path;
680 if (debug)
681 zlog_debug(
682 "%s: %s loses to %s as ES %s is same and local",
683 pfx_buf, new_buf, exist_buf,
684 esi_to_str(new_esi, esi_buf,
685 sizeof(esi_buf)));
686 return 0;
687 }
688 }
689
d62a17ae 690 new_mm_seq = mac_mobility_seqnum(newattr);
691 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 692
d62a17ae 693 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 694 *reason = bgp_path_selection_evpn_seq;
d62a17ae 695 if (debug)
696 zlog_debug(
697 "%s: %s wins over %s due to MM seq %u > %u",
698 pfx_buf, new_buf, exist_buf, new_mm_seq,
699 exist_mm_seq);
700 return 1;
701 }
8ff56318 702
d62a17ae 703 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 704 *reason = bgp_path_selection_evpn_seq;
d62a17ae 705 if (debug)
706 zlog_debug(
707 "%s: %s loses to %s due to MM seq %u < %u",
708 pfx_buf, new_buf, exist_buf, new_mm_seq,
709 exist_mm_seq);
710 return 0;
711 }
6d8c603a 712
d071f237
AK
713 /* if the sequence numbers and ESI are the same and one path
714 * is non-proxy it wins (over proxy)
715 */
716 new_proxy = bgp_evpn_attr_is_proxy(newattr);
717 old_proxy = bgp_evpn_attr_is_proxy(existattr);
718 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
719 old_proxy != new_proxy) {
720 if (!new_proxy) {
721 *reason = bgp_path_selection_evpn_non_proxy;
722 if (debug)
723 zlog_debug(
724 "%s: %s wins over %s, same seq/es and non-proxy",
725 pfx_buf, new_buf, exist_buf);
726 return 1;
727 }
728
729 *reason = bgp_path_selection_evpn_non_proxy;
730 if (debug)
731 zlog_debug(
732 "%s: %s loses to %s, same seq/es and non-proxy",
733 pfx_buf, new_buf, exist_buf);
734 return 0;
735 }
736
6d8c603a
AK
737 /*
738 * if sequence numbers are the same path with the lowest IP
739 * wins
740 */
741 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
742 if (nh_cmp < 0) {
fdf81fa0 743 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
744 if (debug)
745 zlog_debug(
23d0a753 746 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 747 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 748 &new->attr->nexthop);
6d8c603a
AK
749 return 1;
750 }
751 if (nh_cmp > 0) {
fdf81fa0 752 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
753 if (debug)
754 zlog_debug(
23d0a753 755 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 756 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 757 &new->attr->nexthop);
6d8c603a
AK
758 return 0;
759 }
d62a17ae 760 }
9fbdd100 761
d62a17ae 762 /* 1. Weight check. */
d62a17ae 763 new_weight = newattr->weight;
764 exist_weight = existattr->weight;
8ff56318 765
d62a17ae 766 if (new_weight > exist_weight) {
fdf81fa0 767 *reason = bgp_path_selection_weight;
d62a17ae 768 if (debug)
769 zlog_debug("%s: %s wins over %s due to weight %d > %d",
770 pfx_buf, new_buf, exist_buf, new_weight,
771 exist_weight);
772 return 1;
773 }
718e3744 774
d62a17ae 775 if (new_weight < exist_weight) {
fdf81fa0 776 *reason = bgp_path_selection_weight;
d62a17ae 777 if (debug)
778 zlog_debug("%s: %s loses to %s due to weight %d < %d",
779 pfx_buf, new_buf, exist_buf, new_weight,
780 exist_weight);
781 return 0;
782 }
9fbdd100 783
d62a17ae 784 /* 2. Local preference check. */
785 new_pref = exist_pref = bgp->default_local_pref;
786
787 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
788 new_pref = newattr->local_pref;
789 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
790 exist_pref = existattr->local_pref;
791
792 if (new_pref > exist_pref) {
fdf81fa0 793 *reason = bgp_path_selection_local_pref;
d62a17ae 794 if (debug)
795 zlog_debug(
796 "%s: %s wins over %s due to localpref %d > %d",
797 pfx_buf, new_buf, exist_buf, new_pref,
798 exist_pref);
799 return 1;
800 }
718e3744 801
d62a17ae 802 if (new_pref < exist_pref) {
fdf81fa0 803 *reason = bgp_path_selection_local_pref;
d62a17ae 804 if (debug)
805 zlog_debug(
806 "%s: %s loses to %s due to localpref %d < %d",
807 pfx_buf, new_buf, exist_buf, new_pref,
808 exist_pref);
809 return 0;
810 }
9fbdd100 811
d62a17ae 812 /* 3. Local route check. We prefer:
813 * - BGP_ROUTE_STATIC
814 * - BGP_ROUTE_AGGREGATE
815 * - BGP_ROUTE_REDISTRIBUTE
816 */
33c6e933
DS
817 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
818 new->sub_type == BGP_ROUTE_IMPORTED);
819 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
820 exist->sub_type == BGP_ROUTE_IMPORTED);
821
822 if (new_origin && !exist_origin) {
fdf81fa0 823 *reason = bgp_path_selection_local_route;
d62a17ae 824 if (debug)
825 zlog_debug(
826 "%s: %s wins over %s due to preferred BGP_ROUTE type",
827 pfx_buf, new_buf, exist_buf);
828 return 1;
829 }
718e3744 830
33c6e933 831 if (!new_origin && exist_origin) {
fdf81fa0 832 *reason = bgp_path_selection_local_route;
d62a17ae 833 if (debug)
834 zlog_debug(
835 "%s: %s loses to %s due to preferred BGP_ROUTE type",
836 pfx_buf, new_buf, exist_buf);
837 return 0;
6811845b 838 }
718e3744 839
d62a17ae 840 /* 4. AS path length check. */
892fedb6 841 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 842 int exist_hops = aspath_count_hops(existattr->aspath);
843 int exist_confeds = aspath_count_confeds(existattr->aspath);
844
892fedb6 845 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 846 int aspath_hops;
847
848 aspath_hops = aspath_count_hops(newattr->aspath);
849 aspath_hops += aspath_count_confeds(newattr->aspath);
850
851 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 852 *reason = bgp_path_selection_confed_as_path;
d62a17ae 853 if (debug)
854 zlog_debug(
855 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
856 pfx_buf, new_buf, exist_buf,
857 aspath_hops,
858 (exist_hops + exist_confeds));
859 return 1;
860 }
861
862 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 863 *reason = bgp_path_selection_confed_as_path;
d62a17ae 864 if (debug)
865 zlog_debug(
866 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
867 pfx_buf, new_buf, exist_buf,
868 aspath_hops,
869 (exist_hops + exist_confeds));
870 return 0;
871 }
872 } else {
873 int newhops = aspath_count_hops(newattr->aspath);
874
875 if (newhops < exist_hops) {
fdf81fa0 876 *reason = bgp_path_selection_as_path;
d62a17ae 877 if (debug)
878 zlog_debug(
879 "%s: %s wins over %s due to aspath hopcount %d < %d",
880 pfx_buf, new_buf, exist_buf,
881 newhops, exist_hops);
882 return 1;
883 }
884
885 if (newhops > exist_hops) {
fdf81fa0 886 *reason = bgp_path_selection_as_path;
d62a17ae 887 if (debug)
888 zlog_debug(
889 "%s: %s loses to %s due to aspath hopcount %d > %d",
890 pfx_buf, new_buf, exist_buf,
891 newhops, exist_hops);
892 return 0;
893 }
894 }
895 }
9fbdd100 896
d62a17ae 897 /* 5. Origin check. */
898 if (newattr->origin < existattr->origin) {
fdf81fa0 899 *reason = bgp_path_selection_origin;
d62a17ae 900 if (debug)
901 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
902 pfx_buf, new_buf, exist_buf,
903 bgp_origin_long_str[newattr->origin],
904 bgp_origin_long_str[existattr->origin]);
905 return 1;
906 }
718e3744 907
d62a17ae 908 if (newattr->origin > existattr->origin) {
fdf81fa0 909 *reason = bgp_path_selection_origin;
d62a17ae 910 if (debug)
911 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
912 pfx_buf, new_buf, exist_buf,
913 bgp_origin_long_str[newattr->origin],
914 bgp_origin_long_str[existattr->origin]);
915 return 0;
916 }
718e3744 917
d62a17ae 918 /* 6. MED check. */
919 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
920 && aspath_count_hops(existattr->aspath) == 0);
921 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
922 && aspath_count_confeds(existattr->aspath) > 0
923 && aspath_count_hops(newattr->aspath) == 0
924 && aspath_count_hops(existattr->aspath) == 0);
925
892fedb6
DA
926 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
927 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 928 || aspath_cmp_left(newattr->aspath, existattr->aspath)
929 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
930 || internal_as_route) {
931 new_med = bgp_med_value(new->attr, bgp);
932 exist_med = bgp_med_value(exist->attr, bgp);
933
934 if (new_med < exist_med) {
fdf81fa0 935 *reason = bgp_path_selection_med;
d62a17ae 936 if (debug)
937 zlog_debug(
938 "%s: %s wins over %s due to MED %d < %d",
939 pfx_buf, new_buf, exist_buf, new_med,
940 exist_med);
941 return 1;
942 }
8ff56318 943
d62a17ae 944 if (new_med > exist_med) {
fdf81fa0 945 *reason = bgp_path_selection_med;
d62a17ae 946 if (debug)
947 zlog_debug(
948 "%s: %s loses to %s due to MED %d > %d",
949 pfx_buf, new_buf, exist_buf, new_med,
950 exist_med);
951 return 0;
952 }
953 }
9fbdd100 954
d62a17ae 955 /* 7. Peer type check. */
956 new_sort = new->peer->sort;
957 exist_sort = exist->peer->sort;
958
959 if (new_sort == BGP_PEER_EBGP
960 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 961 *reason = bgp_path_selection_peer;
d62a17ae 962 if (debug)
963 zlog_debug(
964 "%s: %s wins over %s due to eBGP peer > iBGP peer",
965 pfx_buf, new_buf, exist_buf);
966 return 1;
967 }
718e3744 968
d62a17ae 969 if (exist_sort == BGP_PEER_EBGP
970 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 971 *reason = bgp_path_selection_peer;
d62a17ae 972 if (debug)
973 zlog_debug(
974 "%s: %s loses to %s due to iBGP peer < eBGP peer",
975 pfx_buf, new_buf, exist_buf);
976 return 0;
977 }
8ff56318 978
d62a17ae 979 /* 8. IGP metric check. */
980 newm = existm = 0;
8ff56318 981
d62a17ae 982 if (new->extra)
983 newm = new->extra->igpmetric;
984 if (exist->extra)
985 existm = exist->extra->igpmetric;
9fbdd100 986
d62a17ae 987 if (newm < existm) {
988 if (debug)
989 zlog_debug(
990 "%s: %s wins over %s due to IGP metric %d < %d",
991 pfx_buf, new_buf, exist_buf, newm, existm);
992 ret = 1;
993 }
718e3744 994
d62a17ae 995 if (newm > existm) {
996 if (debug)
997 zlog_debug(
998 "%s: %s loses to %s due to IGP metric %d > %d",
999 pfx_buf, new_buf, exist_buf, newm, existm);
1000 ret = 0;
5e242b0d 1001 }
5e242b0d 1002
d62a17ae 1003 /* 9. Same IGP metric. Compare the cluster list length as
1004 representative of IGP hops metric. Rewrite the metric value
1005 pair (newm, existm) with the cluster list length. Prefer the
1006 path with smaller cluster list length. */
1007 if (newm == existm) {
bf0d28dc
DS
1008 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1009 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1010 && (mpath_cfg == NULL
1011 || CHECK_FLAG(
1012 mpath_cfg->ibgp_flags,
1013 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1014 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1015 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1016
1017 if (newm < existm) {
1018 if (debug)
1019 zlog_debug(
1020 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1021 pfx_buf, new_buf, exist_buf,
1022 newm, existm);
1023 ret = 1;
1024 }
1025
1026 if (newm > existm) {
1027 if (debug)
1028 zlog_debug(
1029 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1030 pfx_buf, new_buf, exist_buf,
1031 newm, existm);
1032 ret = 0;
1033 }
1034 }
1035 }
31a4638f 1036
d62a17ae 1037 /* 10. confed-external vs. confed-internal */
1038 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1039 if (new_sort == BGP_PEER_CONFED
1040 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1041 *reason = bgp_path_selection_confed;
d62a17ae 1042 if (debug)
1043 zlog_debug(
1044 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1045 pfx_buf, new_buf, exist_buf);
1046 return 1;
1047 }
718e3744 1048
d62a17ae 1049 if (exist_sort == BGP_PEER_CONFED
1050 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1051 *reason = bgp_path_selection_confed;
d62a17ae 1052 if (debug)
1053 zlog_debug(
1054 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1055 pfx_buf, new_buf, exist_buf);
1056 return 0;
1057 }
1058 }
718e3744 1059
d62a17ae 1060 /* 11. Maximum path check. */
1061 if (newm == existm) {
1062 /* If one path has a label but the other does not, do not treat
1063 * them as equals for multipath
1064 */
a4d82a8a 1065 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1066 != (exist->extra
b57ba6d2 1067 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1068 if (debug)
1069 zlog_debug(
1070 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1071 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1072 } else if (CHECK_FLAG(bgp->flags,
1073 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1074
1075 /*
1076 * For the two paths, all comparison steps till IGP
1077 * metric
1078 * have succeeded - including AS_PATH hop count. Since
1079 * 'bgp
1080 * bestpath as-path multipath-relax' knob is on, we
1081 * don't need
1082 * an exact match of AS_PATH. Thus, mark the paths are
1083 * equal.
1084 * That will trigger both these paths to get into the
1085 * multipath
1086 * array.
1087 */
1088 *paths_eq = 1;
1089
1090 if (debug)
1091 zlog_debug(
1092 "%s: %s and %s are equal via multipath-relax",
1093 pfx_buf, new_buf, exist_buf);
1094 } else if (new->peer->sort == BGP_PEER_IBGP) {
1095 if (aspath_cmp(new->attr->aspath,
1096 exist->attr->aspath)) {
1097 *paths_eq = 1;
1098
1099 if (debug)
1100 zlog_debug(
1101 "%s: %s and %s are equal via matching aspaths",
1102 pfx_buf, new_buf, exist_buf);
1103 }
1104 } else if (new->peer->as == exist->peer->as) {
1105 *paths_eq = 1;
1106
1107 if (debug)
1108 zlog_debug(
1109 "%s: %s and %s are equal via same remote-as",
1110 pfx_buf, new_buf, exist_buf);
1111 }
1112 } else {
1113 /*
1114 * TODO: If unequal cost ibgp multipath is enabled we can
1115 * mark the paths as equal here instead of returning
1116 */
1117 if (debug) {
1118 if (ret == 1)
1119 zlog_debug(
1120 "%s: %s wins over %s after IGP metric comparison",
1121 pfx_buf, new_buf, exist_buf);
1122 else
1123 zlog_debug(
1124 "%s: %s loses to %s after IGP metric comparison",
1125 pfx_buf, new_buf, exist_buf);
1126 }
fdf81fa0 1127 *reason = bgp_path_selection_igp_metric;
d62a17ae 1128 return ret;
1129 }
718e3744 1130
d62a17ae 1131 /* 12. If both paths are external, prefer the path that was received
1132 first (the oldest one). This step minimizes route-flap, since a
1133 newer path won't displace an older one, even if it was the
1134 preferred route based on the additional decision criteria below. */
892fedb6 1135 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1136 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1137 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1138 *reason = bgp_path_selection_older;
d62a17ae 1139 if (debug)
1140 zlog_debug(
1141 "%s: %s wins over %s due to oldest external",
1142 pfx_buf, new_buf, exist_buf);
1143 return 1;
1144 }
9fbdd100 1145
1defdda8 1146 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1147 *reason = bgp_path_selection_older;
d62a17ae 1148 if (debug)
1149 zlog_debug(
1150 "%s: %s loses to %s due to oldest external",
1151 pfx_buf, new_buf, exist_buf);
1152 return 0;
1153 }
1154 }
718e3744 1155
d62a17ae 1156 /* 13. Router-ID comparision. */
1157 /* If one of the paths is "stale", the corresponding peer router-id will
1158 * be 0 and would always win over the other path. If originator id is
1159 * used for the comparision, it will decide which path is better.
1160 */
1161 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1162 new_id.s_addr = newattr->originator_id.s_addr;
1163 else
1164 new_id.s_addr = new->peer->remote_id.s_addr;
1165 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1166 exist_id.s_addr = existattr->originator_id.s_addr;
1167 else
1168 exist_id.s_addr = exist->peer->remote_id.s_addr;
1169
1170 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1171 *reason = bgp_path_selection_router_id;
d62a17ae 1172 if (debug)
1173 zlog_debug(
1174 "%s: %s wins over %s due to Router-ID comparison",
1175 pfx_buf, new_buf, exist_buf);
1176 return 1;
1177 }
718e3744 1178
d62a17ae 1179 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1180 *reason = bgp_path_selection_router_id;
d62a17ae 1181 if (debug)
1182 zlog_debug(
1183 "%s: %s loses to %s due to Router-ID comparison",
1184 pfx_buf, new_buf, exist_buf);
1185 return 0;
1186 }
9fbdd100 1187
d62a17ae 1188 /* 14. Cluster length comparision. */
1189 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1190 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1191
1192 if (new_cluster < exist_cluster) {
fdf81fa0 1193 *reason = bgp_path_selection_cluster_length;
d62a17ae 1194 if (debug)
1195 zlog_debug(
1196 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1197 pfx_buf, new_buf, exist_buf, new_cluster,
1198 exist_cluster);
1199 return 1;
1200 }
718e3744 1201
d62a17ae 1202 if (new_cluster > exist_cluster) {
fdf81fa0 1203 *reason = bgp_path_selection_cluster_length;
d62a17ae 1204 if (debug)
1205 zlog_debug(
1206 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1207 pfx_buf, new_buf, exist_buf, new_cluster,
1208 exist_cluster);
1209 return 0;
1210 }
9fbdd100 1211
d62a17ae 1212 /* 15. Neighbor address comparision. */
1213 /* Do this only if neither path is "stale" as stale paths do not have
1214 * valid peer information (as the connection may or may not be up).
1215 */
1defdda8 1216 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1217 *reason = bgp_path_selection_stale;
d62a17ae 1218 if (debug)
1219 zlog_debug(
1220 "%s: %s wins over %s due to latter path being STALE",
1221 pfx_buf, new_buf, exist_buf);
1222 return 1;
1223 }
0de5153c 1224
1defdda8 1225 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1226 *reason = bgp_path_selection_stale;
d62a17ae 1227 if (debug)
1228 zlog_debug(
1229 "%s: %s loses to %s due to former path being STALE",
1230 pfx_buf, new_buf, exist_buf);
1231 return 0;
1232 }
718e3744 1233
d62a17ae 1234 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1235 if (new->peer->su_remote == NULL) {
1236 *reason = bgp_path_selection_local_configured;
d62a17ae 1237 return 0;
fdf81fa0
DS
1238 }
1239 if (exist->peer->su_remote == NULL) {
1240 *reason = bgp_path_selection_local_configured;
d62a17ae 1241 return 1;
fdf81fa0 1242 }
9fbdd100 1243
d62a17ae 1244 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1245
1246 if (ret == 1) {
fdf81fa0 1247 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1248 if (debug)
1249 zlog_debug(
1250 "%s: %s loses to %s due to Neighor IP comparison",
1251 pfx_buf, new_buf, exist_buf);
1252 return 0;
1253 }
1254
1255 if (ret == -1) {
fdf81fa0 1256 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1257 if (debug)
1258 zlog_debug(
1259 "%s: %s wins over %s due to Neighor IP comparison",
1260 pfx_buf, new_buf, exist_buf);
1261 return 1;
1262 }
9fbdd100 1263
fdf81fa0 1264 *reason = bgp_path_selection_default;
d62a17ae 1265 if (debug)
1266 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1267 pfx_buf, new_buf, exist_buf);
718e3744 1268
d62a17ae 1269 return 1;
718e3744 1270}
1271
d071f237
AK
1272
1273int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1274 struct bgp_path_info *exist, int *paths_eq)
1275{
1276 enum bgp_path_selection_reason reason;
1277 char pfx_buf[PREFIX2STR_BUFFER];
1278
1279 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1280 AFI_L2VPN, SAFI_EVPN, &reason);
1281}
1282
65efcfce
LB
1283/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1284 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1285 * multipath is enabled
65efcfce 1286 * This version is compatible with */
18ee8310
DS
1287int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1288 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1289 afi_t afi, safi_t safi,
1290 enum bgp_path_selection_reason *reason)
d62a17ae 1291{
1292 int paths_eq;
1293 int ret;
18ee8310 1294 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1295 afi, safi, reason);
d62a17ae 1296
1297 if (paths_eq)
1298 ret = 0;
1299 else {
1300 if (ret == 1)
1301 ret = -1;
1302 else
1303 ret = 1;
1304 }
1305 return ret;
65efcfce
LB
1306}
1307
5a1ae2c2
DS
1308static enum filter_type bgp_input_filter(struct peer *peer,
1309 const struct prefix *p,
d62a17ae 1310 struct attr *attr, afi_t afi,
1311 safi_t safi)
718e3744 1312{
d62a17ae 1313 struct bgp_filter *filter;
6401252f 1314 enum filter_type ret = FILTER_PERMIT;
718e3744 1315
d62a17ae 1316 filter = &peer->filter[afi][safi];
718e3744 1317
d62a17ae 1318#define FILTER_EXIST_WARN(F, f, filter) \
1319 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1320 zlog_debug("%s: Could not find configured input %s-list %s!", \
1321 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1322
1323 if (DISTRIBUTE_IN_NAME(filter)) {
1324 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1325
6401252f
QY
1326 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1327 == FILTER_DENY) {
1328 ret = FILTER_DENY;
1329 goto done;
1330 }
d62a17ae 1331 }
1332
1333 if (PREFIX_LIST_IN_NAME(filter)) {
1334 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1335
6401252f
QY
1336 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1337 == PREFIX_DENY) {
1338 ret = FILTER_DENY;
1339 goto done;
1340 }
d62a17ae 1341 }
1342
1343 if (FILTER_LIST_IN_NAME(filter)) {
1344 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1345
1346 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1347 == AS_FILTER_DENY) {
1348 ret = FILTER_DENY;
1349 goto done;
1350 }
d62a17ae 1351 }
1352
6401252f 1353done:
c7bb4f00 1354 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1355 char pfxprint[PREFIX2STR_BUFFER];
1356
1357 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1358 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1359 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1360 }
1361
1362 return ret;
650f76c2 1363#undef FILTER_EXIST_WARN
718e3744 1364}
1365
b8685f9b
DS
1366static enum filter_type bgp_output_filter(struct peer *peer,
1367 const struct prefix *p,
d62a17ae 1368 struct attr *attr, afi_t afi,
1369 safi_t safi)
718e3744 1370{
d62a17ae 1371 struct bgp_filter *filter;
6401252f 1372 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1373
1374 filter = &peer->filter[afi][safi];
1375
1376#define FILTER_EXIST_WARN(F, f, filter) \
1377 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1378 zlog_debug("%s: Could not find configured output %s-list %s!", \
1379 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1380
d62a17ae 1381 if (DISTRIBUTE_OUT_NAME(filter)) {
1382 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1383
6401252f
QY
1384 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1385 == FILTER_DENY) {
1386 ret = FILTER_DENY;
1387 goto done;
1388 }
d62a17ae 1389 }
1390
1391 if (PREFIX_LIST_OUT_NAME(filter)) {
1392 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1393
d62a17ae 1394 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1395 == PREFIX_DENY) {
1396 ret = FILTER_DENY;
1397 goto done;
1398 }
d62a17ae 1399 }
718e3744 1400
d62a17ae 1401 if (FILTER_LIST_OUT_NAME(filter)) {
1402 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1403
d62a17ae 1404 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1405 == AS_FILTER_DENY) {
1406 ret = FILTER_DENY;
1407 goto done;
1408 }
1409 }
1410
c7bb4f00 1411 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1412 char pfxprint[PREFIX2STR_BUFFER];
1413
1414 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1415 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1416 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1417 }
718e3744 1418
6401252f
QY
1419done:
1420 return ret;
650f76c2 1421#undef FILTER_EXIST_WARN
718e3744 1422}
1423
1424/* If community attribute includes no_export then return 1. */
3dc339cd 1425static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1426{
1427 if (attr->community) {
1428 /* NO_ADVERTISE check. */
1429 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1430 return true;
d62a17ae 1431
1432 /* NO_EXPORT check. */
1433 if (peer->sort == BGP_PEER_EBGP
1434 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1435 return true;
d62a17ae 1436
1437 /* NO_EXPORT_SUBCONFED check. */
1438 if (peer->sort == BGP_PEER_EBGP
1439 || peer->sort == BGP_PEER_CONFED)
1440 if (community_include(attr->community,
1441 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1442 return true;
d62a17ae 1443 }
3dc339cd 1444 return false;
718e3744 1445}
1446
1447/* Route reflection loop check. */
3dc339cd 1448static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1449{
d62a17ae 1450 struct in_addr cluster_id;
779fee93 1451 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1452
779fee93 1453 if (cluster) {
d62a17ae 1454 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1455 cluster_id = peer->bgp->cluster_id;
1456 else
1457 cluster_id = peer->bgp->router_id;
1458
779fee93 1459 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1460 return true;
d62a17ae 1461 }
3dc339cd 1462 return false;
718e3744 1463}
6b0655a2 1464
5a1ae2c2 1465static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1466 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1467 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1468 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1469{
d62a17ae 1470 struct bgp_filter *filter;
82b692c0
LK
1471 struct bgp_path_info rmap_path = { 0 };
1472 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1473 route_map_result_t ret;
1474 struct route_map *rmap = NULL;
718e3744 1475
d62a17ae 1476 filter = &peer->filter[afi][safi];
718e3744 1477
d62a17ae 1478 /* Apply default weight value. */
1479 if (peer->weight[afi][safi])
1480 attr->weight = peer->weight[afi][safi];
718e3744 1481
d62a17ae 1482 if (rmap_name) {
1483 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1484
d62a17ae 1485 if (rmap == NULL)
1486 return RMAP_DENY;
1487 } else {
1488 if (ROUTE_MAP_IN_NAME(filter)) {
1489 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1490
d62a17ae 1491 if (rmap == NULL)
1492 return RMAP_DENY;
1493 }
1494 }
0b16f239 1495
d62a17ae 1496 /* Route map apply. */
1497 if (rmap) {
40381db7 1498 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1499 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1500 rmap_path.peer = peer;
1501 rmap_path.attr = attr;
82b692c0 1502 rmap_path.extra = &extra;
9bcb3eef 1503 rmap_path.net = dest;
196c6b09 1504
82b692c0
LK
1505 extra.num_labels = num_labels;
1506 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1507 memcpy(extra.label, label,
1508 num_labels * sizeof(mpls_label_t));
718e3744 1509
d62a17ae 1510 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1511
d62a17ae 1512 /* Apply BGP route map to the attribute. */
1782514f 1513 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1514
d62a17ae 1515 peer->rmap_type = 0;
0b16f239 1516
1f2263be 1517 if (ret == RMAP_DENYMATCH)
d62a17ae 1518 return RMAP_DENY;
0b16f239 1519 }
d62a17ae 1520 return RMAP_PERMIT;
0b16f239
DS
1521}
1522
5f040085 1523static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1524 struct attr *attr, afi_t afi, safi_t safi,
1525 const char *rmap_name)
0b16f239 1526{
40381db7 1527 struct bgp_path_info rmap_path;
d62a17ae 1528 route_map_result_t ret;
1529 struct route_map *rmap = NULL;
d7c0a89a 1530 uint8_t rmap_type;
0b16f239 1531
b787157a
DS
1532 /*
1533 * So if we get to this point and have no rmap_name
1534 * we want to just show the output as it currently
1535 * exists.
1536 */
1537 if (!rmap_name)
1538 return RMAP_PERMIT;
0b16f239 1539
d62a17ae 1540 /* Apply default weight value. */
1541 if (peer->weight[afi][safi])
1542 attr->weight = peer->weight[afi][safi];
0b16f239 1543
b787157a 1544 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1545
b787157a
DS
1546 /*
1547 * If we have a route map name and we do not find
1548 * the routemap that means we have an implicit
1549 * deny.
1550 */
1551 if (rmap == NULL)
1552 return RMAP_DENY;
0b16f239 1553
40381db7 1554 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1555 /* Route map apply. */
b787157a 1556 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1557 rmap_path.peer = peer;
1558 rmap_path.attr = attr;
0b16f239 1559
0f672529 1560 rmap_type = peer->rmap_type;
b787157a 1561 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1562
b787157a 1563 /* Apply BGP route map to the attribute. */
1782514f 1564 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1565
0f672529 1566 peer->rmap_type = rmap_type;
b787157a
DS
1567
1568 if (ret == RMAP_DENYMATCH)
1569 /*
1570 * caller has multiple error paths with bgp_attr_flush()
1571 */
1572 return RMAP_DENY;
ac41b2a2 1573
d62a17ae 1574 return RMAP_PERMIT;
718e3744 1575}
6b0655a2 1576
5000f21c 1577/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1578static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1579 struct peer *peer, struct attr *attr)
1580{
1581 if (peer->sort == BGP_PEER_EBGP
1582 && (peer_af_flag_check(peer, afi, safi,
1583 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1584 || peer_af_flag_check(peer, afi, safi,
1585 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1586 || peer_af_flag_check(peer, afi, safi,
1587 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1588 || peer_af_flag_check(peer, afi, safi,
1589 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1590 // Take action on the entire aspath
1591 if (peer_af_flag_check(peer, afi, safi,
1592 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1593 || peer_af_flag_check(peer, afi, safi,
1594 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1595 if (peer_af_flag_check(
1596 peer, afi, safi,
1597 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1598 attr->aspath = aspath_replace_private_asns(
bf26b80e 1599 attr->aspath, bgp->as, peer->as);
d62a17ae 1600
1601 // The entire aspath consists of private ASNs so create
1602 // an empty aspath
1603 else if (aspath_private_as_check(attr->aspath))
1604 attr->aspath = aspath_empty_get();
1605
1606 // There are some public and some private ASNs, remove
1607 // the private ASNs
1608 else
1609 attr->aspath = aspath_remove_private_asns(
bf26b80e 1610 attr->aspath, peer->as);
d62a17ae 1611 }
1612
1613 // 'all' was not specified so the entire aspath must be private
1614 // ASNs
1615 // for us to do anything
1616 else if (aspath_private_as_check(attr->aspath)) {
1617 if (peer_af_flag_check(
1618 peer, afi, safi,
1619 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1620 attr->aspath = aspath_replace_private_asns(
bf26b80e 1621 attr->aspath, bgp->as, peer->as);
d62a17ae 1622 else
1623 attr->aspath = aspath_empty_get();
1624 }
1625 }
5000f21c
DS
1626}
1627
c7122e14 1628/* If this is an EBGP peer with as-override */
d62a17ae 1629static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1630 struct peer *peer, struct attr *attr)
1631{
1632 if (peer->sort == BGP_PEER_EBGP
1633 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1634 if (aspath_single_asn_check(attr->aspath, peer->as))
1635 attr->aspath = aspath_replace_specific_asn(
1636 attr->aspath, peer->as, bgp->as);
1637 }
1638}
1639
7f323236
DW
1640void bgp_attr_add_gshut_community(struct attr *attr)
1641{
1642 struct community *old;
1643 struct community *new;
1644 struct community *merge;
1645 struct community *gshut;
1646
1647 old = attr->community;
1648 gshut = community_str2com("graceful-shutdown");
1649
990f4f91 1650 assert(gshut);
1651
7f323236
DW
1652 if (old) {
1653 merge = community_merge(community_dup(old), gshut);
1654
a4d82a8a 1655 if (old->refcnt == 0)
3c1f53de 1656 community_free(&old);
7f323236
DW
1657
1658 new = community_uniq_sort(merge);
3c1f53de 1659 community_free(&merge);
7f323236
DW
1660 } else {
1661 new = community_dup(gshut);
1662 }
1663
3c1f53de 1664 community_free(&gshut);
7f323236
DW
1665 attr->community = new;
1666 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1667
1668 /* When we add the graceful-shutdown community we must also
1669 * lower the local-preference */
1670 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1671 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1672}
1673
1674
e73c112e
MK
1675/* Notify BGP Conditional advertisement scanner process. */
1676void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1677{
1678 struct peer *temp_peer;
1679 struct peer *peer = SUBGRP_PEER(subgrp);
1680 struct listnode *temp_node, *temp_nnode = NULL;
1681 afi_t afi = SUBGRP_AFI(subgrp);
1682 safi_t safi = SUBGRP_SAFI(subgrp);
1683 struct bgp *bgp = SUBGRP_INST(subgrp);
1684 struct bgp_filter *filter = &peer->filter[afi][safi];
1685
1686 if (!ADVERTISE_MAP_NAME(filter))
1687 return;
1688
1689 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1690 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1691 continue;
1692
1693 if (peer != temp_peer)
1694 continue;
1695
1696 temp_peer->advmap_table_change = true;
1697 break;
1698 }
1699}
1700
1701
f2ee6d5c 1702void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1703{
960035b2 1704 if (family == AF_INET) {
975a328e
DA
1705 attr->nexthop.s_addr = INADDR_ANY;
1706 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1707 }
d62a17ae 1708 if (family == AF_INET6)
1709 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1710 if (family == AF_EVPN)
1711 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1712}
1713
9bcb3eef 1714bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1715 struct update_subgroup *subgrp,
7f7940e6
MK
1716 const struct prefix *p, struct attr *attr,
1717 bool skip_rmap_check)
d62a17ae 1718{
1719 struct bgp_filter *filter;
1720 struct peer *from;
1721 struct peer *peer;
1722 struct peer *onlypeer;
1723 struct bgp *bgp;
40381db7 1724 struct attr *piattr;
b68885f9 1725 route_map_result_t ret;
d62a17ae 1726 int transparent;
1727 int reflect;
1728 afi_t afi;
1729 safi_t safi;
1730 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1731 bool nh_reset = false;
1732 uint64_t cum_bw;
d62a17ae 1733
1734 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1735 return false;
d62a17ae 1736
1737 afi = SUBGRP_AFI(subgrp);
1738 safi = SUBGRP_SAFI(subgrp);
1739 peer = SUBGRP_PEER(subgrp);
1740 onlypeer = NULL;
1741 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1742 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1743
40381db7 1744 from = pi->peer;
d62a17ae 1745 filter = &peer->filter[afi][safi];
1746 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1747 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1748 : pi->attr;
3f9c7369 1749
49e5a4a0 1750#ifdef ENABLE_BGP_VNC
d62a17ae 1751 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1752 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1753 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1754
1755 /*
1756 * direct and direct_ext type routes originate internally even
1757 * though they can have peer pointers that reference other
1758 * systems
1759 */
8228a9a7
DS
1760 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1761 __func__, p);
d62a17ae 1762 samepeer_safe = 1;
1763 }
65efcfce
LB
1764#endif
1765
ddb5b488
PZ
1766 if (((afi == AFI_IP) || (afi == AFI_IP6))
1767 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1768 && (pi->type == ZEBRA_ROUTE_BGP)
1769 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1770
1771 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1772
1773 samepeer_safe = 1;
1774 }
1775
d62a17ae 1776 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1777 * pi is valid */
1778 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1779 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1780 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1781 return false;
d62a17ae 1782 }
adbac85e 1783
d62a17ae 1784 /* If this is not the bestpath then check to see if there is an enabled
1785 * addpath
1786 * feature that requires us to advertise it */
40381db7 1787 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1788 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1789 return false;
d62a17ae 1790 }
1791 }
06370dac 1792
d62a17ae 1793 /* Aggregate-address suppress check. */
4056a5f6
RZ
1794 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1795 return false;
3f9c7369 1796
13b7e7f0
DS
1797 /*
1798 * If we are doing VRF 2 VRF leaking via the import
1799 * statement, we want to prevent the route going
1800 * off box as that the RT and RD created are localy
1801 * significant and globaly useless.
1802 */
40381db7
DS
1803 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1804 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1805 return false;
13b7e7f0 1806
d62a17ae 1807 /* If it's labeled safi, make sure the route has a valid label. */
1808 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1809 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1810 if (!bgp_is_valid_label(&label)) {
1811 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1812 zlog_debug("u%" PRIu64 ":s%" PRIu64
1813 " %pFX is filtered - no label (%p)",
d62a17ae 1814 subgrp->update_group->id, subgrp->id,
8228a9a7 1815 p, &label);
3dc339cd 1816 return false;
d62a17ae 1817 }
1818 }
cd1964ff 1819
d62a17ae 1820 /* Do not send back route to sender. */
1821 if (onlypeer && from == onlypeer) {
3dc339cd 1822 return false;
d62a17ae 1823 }
3f9c7369 1824
d62a17ae 1825 /* Do not send the default route in the BGP table if the neighbor is
1826 * configured for default-originate */
1827 if (CHECK_FLAG(peer->af_flags[afi][safi],
1828 PEER_FLAG_DEFAULT_ORIGINATE)) {
1829 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1830 return false;
d62a17ae 1831 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1832 return false;
d62a17ae 1833 }
4125bb67 1834
d62a17ae 1835 /* Transparency check. */
1836 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1837 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1838 transparent = 1;
1839 else
1840 transparent = 0;
1841
1842 /* If community is not disabled check the no-export and local. */
40381db7 1843 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1844 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1845 zlog_debug("%s: community filter check fail for %pFX",
1846 __func__, p);
3dc339cd 1847 return false;
d62a17ae 1848 }
3f9c7369 1849
d62a17ae 1850 /* If the attribute has originator-id and it is same as remote
1851 peer's id. */
40381db7
DS
1852 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1853 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1854 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1855 zlog_debug(
8228a9a7
DS
1856 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1857 onlypeer->host, p);
3dc339cd 1858 return false;
d62a17ae 1859 }
3f9c7369 1860
d62a17ae 1861 /* ORF prefix-list filter check */
1862 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1863 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1864 || CHECK_FLAG(peer->af_cap[afi][safi],
1865 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1866 if (peer->orf_plist[afi][safi]) {
1867 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1868 == PREFIX_DENY) {
1869 if (bgp_debug_update(NULL, p,
1870 subgrp->update_group, 0))
1871 zlog_debug(
8228a9a7
DS
1872 "%s [Update:SEND] %pFX is filtered via ORF",
1873 peer->host, p);
3dc339cd 1874 return false;
d62a17ae 1875 }
1876 }
1877
1878 /* Output filter check. */
40381db7 1879 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1880 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1881 zlog_debug("%s [Update:SEND] %pFX is filtered",
1882 peer->host, p);
3dc339cd 1883 return false;
d62a17ae 1884 }
3f9c7369 1885
d62a17ae 1886 /* AS path loop check. */
2b31007c
RZ
1887 if (onlypeer && onlypeer->as_path_loop_detection
1888 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1889 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1890 zlog_debug(
3efd0893 1891 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1892 onlypeer->host, onlypeer->as);
3dc339cd 1893 return false;
d62a17ae 1894 }
3f9c7369 1895
d62a17ae 1896 /* If we're a CONFED we need to loop check the CONFED ID too */
1897 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1898 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1899 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1900 zlog_debug(
3efd0893 1901 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1902 peer->host, bgp->confed_id);
3dc339cd 1903 return false;
d62a17ae 1904 }
3f9c7369 1905 }
3f9c7369 1906
d62a17ae 1907 /* Route-Reflect check. */
1908 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1909 reflect = 1;
1910 else
1911 reflect = 0;
1912
1913 /* IBGP reflection check. */
1914 if (reflect && !samepeer_safe) {
1915 /* A route from a Client peer. */
1916 if (CHECK_FLAG(from->af_flags[afi][safi],
1917 PEER_FLAG_REFLECTOR_CLIENT)) {
1918 /* Reflect to all the Non-Client peers and also to the
1919 Client peers other than the originator. Originator
1920 check
1921 is already done. So there is noting to do. */
1922 /* no bgp client-to-client reflection check. */
892fedb6
DA
1923 if (CHECK_FLAG(bgp->flags,
1924 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1925 if (CHECK_FLAG(peer->af_flags[afi][safi],
1926 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1927 return false;
d62a17ae 1928 } else {
1929 /* A route from a Non-client peer. Reflect to all other
1930 clients. */
1931 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1932 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1933 return false;
d62a17ae 1934 }
1935 }
3f9c7369 1936
d62a17ae 1937 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1938 *attr = *piattr;
d62a17ae 1939
1940 /* If local-preference is not set. */
1941 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1942 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1943 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1944 attr->local_pref = bgp->default_local_pref;
3f9c7369 1945 }
3f9c7369 1946
d62a17ae 1947 /* If originator-id is not set and the route is to be reflected,
1948 set the originator id */
1949 if (reflect
1950 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1951 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1952 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1953 }
3f9c7369 1954
d62a17ae 1955 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1956 */
1957 if (peer->sort == BGP_PEER_EBGP
1958 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1959 if (from != bgp->peer_self && !transparent
1960 && !CHECK_FLAG(peer->af_flags[afi][safi],
1961 PEER_FLAG_MED_UNCHANGED))
1962 attr->flag &=
1963 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1964 }
3f9c7369 1965
d62a17ae 1966 /* Since the nexthop attribute can vary per peer, it is not explicitly
1967 * set
1968 * in announce check, only certain flags and length (or number of
1969 * nexthops
1970 * -- for IPv6/MP_REACH) are set here in order to guide the update
1971 * formation
1972 * code in setting the nexthop(s) on a per peer basis in
1973 * reformat_peer().
1974 * Typically, the source nexthop in the attribute is preserved but in
1975 * the
1976 * scenarios where we know it will always be overwritten, we reset the
1977 * nexthop to "0" in an attempt to achieve better Update packing. An
1978 * example of this is when a prefix from each of 2 IBGP peers needs to
1979 * be
1980 * announced to an EBGP peer (and they have the same attributes barring
1981 * their nexthop).
1982 */
1983 if (reflect)
1984 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1985
1986#define NEXTHOP_IS_V6 \
1987 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1988 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1989 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1990 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1991
1992 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1993 * if
1994 * the peer (group) is configured to receive link-local nexthop
1995 * unchanged
c728d027
DA
1996 * and it is available in the prefix OR we're not reflecting the route,
1997 * link-local nexthop address is valid and
d62a17ae 1998 * the peer (group) to whom we're going to announce is on a shared
1999 * network
2000 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2001 * By checking if nexthop LL address is valid we are sure that
2002 * we do not announce LL address as `::`.
d62a17ae 2003 */
2004 if (NEXTHOP_IS_V6) {
2005 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2006 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2007 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2008 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2009 || (!reflect
2010 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2011 && peer->shared_network
d62a17ae 2012 && (from == bgp->peer_self
2013 || peer->sort == BGP_PEER_EBGP))) {
2014 attr->mp_nexthop_len =
2015 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2016 }
3f9c7369 2017
d62a17ae 2018 /* Clear off link-local nexthop in source, whenever it is not
2019 * needed to
2020 * ensure more prefixes share the same attribute for
2021 * announcement.
2022 */
2023 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2024 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2025 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2026 }
3f9c7369 2027
d62a17ae 2028 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2029 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2030
2031 /* Route map & unsuppress-map apply. */
7f7940e6 2032 if (!skip_rmap_check
e73c112e 2033 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2034 struct bgp_path_info rmap_path = {0};
2035 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2036 struct attr dummy_attr = {0};
d62a17ae 2037
e34291b8 2038 /* Fill temp path_info */
9bcb3eef
DS
2039 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2040 pi, peer, attr);
16f7ce2b 2041
d62a17ae 2042 /* don't confuse inbound and outbound setting */
2043 RESET_FLAG(attr->rmap_change_flags);
2044
2045 /*
2046 * The route reflector is not allowed to modify the attributes
2047 * of the reflected IBGP routes unless explicitly allowed.
2048 */
2049 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2050 && !CHECK_FLAG(bgp->flags,
2051 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2052 dummy_attr = *attr;
40381db7 2053 rmap_path.attr = &dummy_attr;
d62a17ae 2054 }
3f9c7369 2055
d62a17ae 2056 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2057
4056a5f6 2058 if (bgp_path_suppressed(pi))
d62a17ae 2059 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2060 &rmap_path);
d62a17ae 2061 else
2062 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2063 &rmap_path);
d62a17ae 2064
2065 peer->rmap_type = 0;
2066
2067 if (ret == RMAP_DENYMATCH) {
778048bf 2068 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2069 zlog_debug(
2070 "%s [Update:SEND] %pFX is filtered by route-map",
2071 peer->host, p);
778048bf 2072
d62a17ae 2073 bgp_attr_flush(attr);
3dc339cd 2074 return false;
d62a17ae 2075 }
3f9c7369 2076 }
3f9c7369 2077
9dac9fc8
DA
2078 /* RFC 8212 to prevent route leaks.
2079 * This specification intends to improve this situation by requiring the
2080 * explicit configuration of both BGP Import and Export Policies for any
2081 * External BGP (EBGP) session such as customers, peers, or
2082 * confederation boundaries for all enabled address families. Through
2083 * codification of the aforementioned requirement, operators will
2084 * benefit from consistent behavior across different BGP
2085 * implementations.
2086 */
1d3fdccf 2087 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2088 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2089 return false;
9dac9fc8 2090
fb29348a
DA
2091 /* draft-ietf-idr-deprecate-as-set-confed-set
2092 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2093 * Eventually, This document (if approved) updates RFC 4271
2094 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2095 * and obsoletes RFC 6472.
2096 */
7f972cd8 2097 if (peer->bgp->reject_as_sets)
fb29348a 2098 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2099 return false;
fb29348a 2100
33d022bc
DA
2101 /* Codification of AS 0 Processing */
2102 if (aspath_check_as_zero(attr->aspath))
e2369003 2103 return false;
33d022bc 2104
637e5ba4 2105 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2106 if (peer->sort == BGP_PEER_IBGP
2107 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2108 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2109 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2110 } else {
2111 bgp_attr_add_gshut_community(attr);
2112 }
2113 }
2114
d62a17ae 2115 /* After route-map has been applied, we check to see if the nexthop to
2116 * be carried in the attribute (that is used for the announcement) can
2117 * be cleared off or not. We do this in all cases where we would be
2118 * setting the nexthop to "ourselves". For IPv6, we only need to
2119 * consider
2120 * the global nexthop here; the link-local nexthop would have been
2121 * cleared
2122 * already, and if not, it is required by the update formation code.
2123 * Also see earlier comments in this function.
2124 */
2125 /*
2126 * If route-map has performed some operation on the nexthop or the peer
2127 * configuration says to pass it unchanged, we cannot reset the nexthop
2128 * here, so only attempt to do it if these aren't true. Note that the
2129 * route-map handler itself might have cleared the nexthop, if for
2130 * example,
2131 * it is configured as 'peer-address'.
2132 */
2133 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2134 piattr->rmap_change_flags)
d62a17ae 2135 && !transparent
2136 && !CHECK_FLAG(peer->af_flags[afi][safi],
2137 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2138 /* We can reset the nexthop, if setting (or forcing) it to
2139 * 'self' */
2140 if (CHECK_FLAG(peer->af_flags[afi][safi],
2141 PEER_FLAG_NEXTHOP_SELF)
2142 || CHECK_FLAG(peer->af_flags[afi][safi],
2143 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2144 if (!reflect
2145 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2146 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2147 subgroup_announce_reset_nhop(
2148 (peer_cap_enhe(peer, afi, safi)
2149 ? AF_INET6
2150 : p->family),
2151 attr);
7b651a32 2152 nh_reset = true;
2153 }
d62a17ae 2154 } else if (peer->sort == BGP_PEER_EBGP) {
2155 /* Can also reset the nexthop if announcing to EBGP, but
2156 * only if
2157 * no peer in the subgroup is on a shared subnet.
2158 * Note: 3rd party nexthop currently implemented for
2159 * IPv4 only.
2160 */
737af885
BS
2161 if ((p->family == AF_INET) &&
2162 (!bgp_subgrp_multiaccess_check_v4(
2163 piattr->nexthop,
7b651a32 2164 subgrp, from))) {
d62a17ae 2165 subgroup_announce_reset_nhop(
2166 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2167 ? AF_INET6
2168 : p->family),
737af885 2169 attr);
7b651a32 2170 nh_reset = true;
2171 }
737af885
BS
2172
2173 if ((p->family == AF_INET6) &&
2174 (!bgp_subgrp_multiaccess_check_v6(
2175 piattr->mp_nexthop_global,
7b651a32 2176 subgrp, from))) {
737af885
BS
2177 subgroup_announce_reset_nhop(
2178 (peer_cap_enhe(peer, afi, safi)
2179 ? AF_INET6
2180 : p->family),
2181 attr);
7b651a32 2182 nh_reset = true;
2183 }
737af885
BS
2184
2185
2186
40381db7 2187 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2188 /*
2189 * This flag is used for leaked vpn-vrf routes
2190 */
2191 int family = p->family;
2192
2193 if (peer_cap_enhe(peer, afi, safi))
2194 family = AF_INET6;
2195
2196 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2197 zlog_debug(
1defdda8 2198 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2199 __func__, family2str(family));
2200 subgroup_announce_reset_nhop(family, attr);
7b651a32 2201 nh_reset = true;
d62a17ae 2202 }
63696f1d 2203 }
960035b2 2204
63696f1d 2205 /* If IPv6/MP and nexthop does not have any override and happens
2206 * to
2207 * be a link-local address, reset it so that we don't pass along
2208 * the
2209 * source's link-local IPv6 address to recipients who may not be
2210 * on
2211 * the same interface.
2212 */
2213 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2214 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2215 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2216 nh_reset = true;
2217 }
d62a17ae 2218 }
3f9c7369 2219
7b651a32 2220 /*
2221 * When the next hop is set to ourselves, if all multipaths have
2222 * link-bandwidth announce the cumulative bandwidth as that makes
2223 * the most sense. However, don't modify if the link-bandwidth has
2224 * been explicitly set by user policy.
2225 */
2226 if (nh_reset &&
f7e1c681 2227 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2228 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2229 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2230 attr->ecommunity = ecommunity_replace_linkbw(
2231 bgp->as, attr->ecommunity, cum_bw);
2232
3dc339cd 2233 return true;
3f9c7369
DS
2234}
2235
f009ff26 2236static int bgp_route_select_timer_expire(struct thread *thread)
2237{
2238 struct afi_safi_info *info;
2239 afi_t afi;
2240 safi_t safi;
2241 struct bgp *bgp;
2242
2243 info = THREAD_ARG(thread);
2244 afi = info->afi;
2245 safi = info->safi;
2246 bgp = info->bgp;
2247
2248 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2249 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2250 safi);
f009ff26 2251
2252 bgp->gr_info[afi][safi].t_route_select = NULL;
2253
2254 XFREE(MTYPE_TMP, info);
2255
2256 /* Best path selection */
2257 return bgp_best_path_select_defer(bgp, afi, safi);
2258}
2259
9bcb3eef 2260void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2261 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2262 struct bgp_path_info_pair *result, afi_t afi,
2263 safi_t safi)
2264{
2265 struct bgp_path_info *new_select;
2266 struct bgp_path_info *old_select;
40381db7
DS
2267 struct bgp_path_info *pi;
2268 struct bgp_path_info *pi1;
2269 struct bgp_path_info *pi2;
2270 struct bgp_path_info *nextpi = NULL;
d62a17ae 2271 int paths_eq, do_mpath, debug;
2272 struct list mp_list;
2273 char pfx_buf[PREFIX2STR_BUFFER];
2274 char path_buf[PATH_ADDPATH_STR_BUFFER];
2275
2276 bgp_mp_list_init(&mp_list);
2277 do_mpath =
2278 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2279
9bcb3eef 2280 debug = bgp_debug_bestpath(dest);
d62a17ae 2281
2282 if (debug)
9bcb3eef 2283 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2284
9bcb3eef 2285 dest->reason = bgp_path_selection_none;
d62a17ae 2286 /* bgp deterministic-med */
2287 new_select = NULL;
892fedb6 2288 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2289
1defdda8 2290 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2291 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2292 pi1 = pi1->next)
9bcb3eef 2293 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2294 BGP_PATH_DMED_SELECTED);
d62a17ae 2295
9bcb3eef 2296 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2297 pi1 = pi1->next) {
40381db7 2298 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2299 continue;
40381db7 2300 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2301 continue;
ea8b2282 2302 if (pi1->peer != bgp->peer_self)
40381db7 2303 if (pi1->peer->status != Established)
d62a17ae 2304 continue;
2305
40381db7
DS
2306 new_select = pi1;
2307 if (pi1->next) {
2308 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2309 if (CHECK_FLAG(pi2->flags,
1defdda8 2310 BGP_PATH_DMED_CHECK))
d62a17ae 2311 continue;
40381db7 2312 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2313 continue;
ea8b2282 2314 if (pi2->peer != bgp->peer_self
d62a17ae 2315 && !CHECK_FLAG(
ea8b2282
DS
2316 pi2->peer->sflags,
2317 PEER_STATUS_NSF_WAIT))
40381db7 2318 if (pi2->peer->status
d62a17ae 2319 != Established)
2320 continue;
2321
121e245d
DS
2322 if (!aspath_cmp_left(pi1->attr->aspath,
2323 pi2->attr->aspath)
2324 && !aspath_cmp_left_confed(
40381db7 2325 pi1->attr->aspath,
121e245d
DS
2326 pi2->attr->aspath))
2327 continue;
d62a17ae 2328
121e245d
DS
2329 if (bgp_path_info_cmp(
2330 bgp, pi2, new_select,
2331 &paths_eq, mpath_cfg, debug,
fdf81fa0 2332 pfx_buf, afi, safi,
9bcb3eef 2333 &dest->reason)) {
121e245d 2334 bgp_path_info_unset_flag(
9bcb3eef 2335 dest, new_select,
121e245d
DS
2336 BGP_PATH_DMED_SELECTED);
2337 new_select = pi2;
d62a17ae 2338 }
121e245d
DS
2339
2340 bgp_path_info_set_flag(
9bcb3eef 2341 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2342 }
2343 }
9bcb3eef 2344 bgp_path_info_set_flag(dest, new_select,
18ee8310 2345 BGP_PATH_DMED_CHECK);
9bcb3eef 2346 bgp_path_info_set_flag(dest, new_select,
18ee8310 2347 BGP_PATH_DMED_SELECTED);
d62a17ae 2348
2349 if (debug) {
18ee8310
DS
2350 bgp_path_info_path_with_addpath_rx_str(
2351 new_select, path_buf);
8228a9a7
DS
2352 zlog_debug(
2353 "%pBD: %s is the bestpath from AS %u",
2354 dest, path_buf,
2355 aspath_get_first_as(
2356 new_select->attr->aspath));
d62a17ae 2357 }
2358 }
2359 }
96450faf 2360
d62a17ae 2361 /* Check old selected route and new selected route. */
2362 old_select = NULL;
2363 new_select = NULL;
9bcb3eef 2364 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2365 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2366 enum bgp_path_selection_reason reason;
2367
40381db7
DS
2368 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2369 old_select = pi;
d62a17ae 2370
40381db7 2371 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2372 /* reap REMOVED routes, if needs be
2373 * selected route must stay for a while longer though
2374 */
40381db7
DS
2375 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2376 && (pi != old_select))
9bcb3eef 2377 bgp_path_info_reap(dest, pi);
d62a17ae 2378
ddb5b488 2379 if (debug)
40381db7
DS
2380 zlog_debug("%s: pi %p in holddown", __func__,
2381 pi);
ddb5b488 2382
d62a17ae 2383 continue;
2384 }
96450faf 2385
40381db7
DS
2386 if (pi->peer && pi->peer != bgp->peer_self
2387 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2388 if (pi->peer->status != Established) {
ddb5b488
PZ
2389
2390 if (debug)
2391 zlog_debug(
40381db7
DS
2392 "%s: pi %p non self peer %s not estab state",
2393 __func__, pi, pi->peer->host);
ddb5b488 2394
d62a17ae 2395 continue;
ddb5b488 2396 }
9fbdd100 2397
892fedb6 2398 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2399 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2400 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2401 if (debug)
40381db7 2402 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2403 continue;
2404 }
9fbdd100 2405
9bcb3eef 2406 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2407
9bcb3eef 2408 reason = dest->reason;
40381db7 2409 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2410 debug, pfx_buf, afi, safi,
2411 &dest->reason)) {
19ea4cec
DS
2412 if (new_select == NULL &&
2413 reason != bgp_path_selection_none)
9bcb3eef 2414 dest->reason = reason;
40381db7 2415 new_select = pi;
d62a17ae 2416 }
2417 }
718e3744 2418
d62a17ae 2419 /* Now that we know which path is the bestpath see if any of the other
2420 * paths
2421 * qualify as multipaths
2422 */
2423 if (debug) {
2424 if (new_select)
18ee8310
DS
2425 bgp_path_info_path_with_addpath_rx_str(new_select,
2426 path_buf);
d62a17ae 2427 else
772270f3 2428 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2429 zlog_debug(
8228a9a7
DS
2430 "%pBD: After path selection, newbest is %s oldbest was %s",
2431 dest, path_buf,
d62a17ae 2432 old_select ? old_select->peer->host : "NONE");
96450faf 2433 }
9fbdd100 2434
d62a17ae 2435 if (do_mpath && new_select) {
9bcb3eef 2436 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2437 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2438
2439 if (debug)
18ee8310 2440 bgp_path_info_path_with_addpath_rx_str(
40381db7 2441 pi, path_buf);
d62a17ae 2442
40381db7 2443 if (pi == new_select) {
d62a17ae 2444 if (debug)
2445 zlog_debug(
8228a9a7
DS
2446 "%pBD: %s is the bestpath, add to the multipath list",
2447 dest, path_buf);
40381db7 2448 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2449 continue;
2450 }
2451
40381db7 2452 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2453 continue;
2454
40381db7
DS
2455 if (pi->peer && pi->peer != bgp->peer_self
2456 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2457 PEER_STATUS_NSF_WAIT))
40381db7 2458 if (pi->peer->status != Established)
d62a17ae 2459 continue;
2460
40381db7 2461 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2462 if (debug)
2463 zlog_debug(
8228a9a7
DS
2464 "%pBD: %s has the same nexthop as the bestpath, skip it",
2465 dest, path_buf);
d62a17ae 2466 continue;
2467 }
2468
40381db7 2469 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2470 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2471 &dest->reason);
d62a17ae 2472
2473 if (paths_eq) {
2474 if (debug)
2475 zlog_debug(
8228a9a7
DS
2476 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2477 dest, path_buf);
40381db7 2478 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2479 }
2480 }
2481 }
fee0f4c6 2482
9bcb3eef 2483 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2484 mpath_cfg);
2485 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2486 bgp_mp_list_clear(&mp_list);
96450faf 2487
9bcb3eef 2488 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2489
d62a17ae 2490 result->old = old_select;
2491 result->new = new_select;
96450faf 2492
d62a17ae 2493 return;
fee0f4c6 2494}
2495
3f9c7369
DS
2496/*
2497 * A new route/change in bestpath of an existing route. Evaluate the path
2498 * for advertisement to the subgroup.
2499 */
3dc339cd
DA
2500void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2501 struct bgp_path_info *selected,
9bcb3eef 2502 struct bgp_dest *dest,
3dc339cd 2503 uint32_t addpath_tx_id)
d62a17ae 2504{
b54892e0 2505 const struct prefix *p;
d62a17ae 2506 struct peer *onlypeer;
2507 struct attr attr;
2508 afi_t afi;
2509 safi_t safi;
a77e2f4b
S
2510 struct bgp *bgp;
2511 bool advertise;
adbac85e 2512
9bcb3eef 2513 p = bgp_dest_get_prefix(dest);
d62a17ae 2514 afi = SUBGRP_AFI(subgrp);
2515 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2516 bgp = SUBGRP_INST(subgrp);
d62a17ae 2517 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2518 : NULL);
2519
2dbe669b
DA
2520 if (BGP_DEBUG(update, UPDATE_OUT))
2521 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2522
d62a17ae 2523 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2524 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2525 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2526 return;
d62a17ae 2527
2528 memset(&attr, 0, sizeof(struct attr));
2529 /* It's initialized in bgp_announce_check() */
2530
a77e2f4b
S
2531 /* Announcement to the subgroup. If the route is filtered withdraw it.
2532 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2533 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2534 * route
d62a17ae 2535 */
a77e2f4b
S
2536 advertise = bgp_check_advertise(bgp, dest);
2537
d62a17ae 2538 if (selected) {
7f7940e6 2539 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2540 false)) {
2541 /* Route is selected, if the route is already installed
2542 * in FIB, then it is advertised
2543 */
2544 if (advertise)
2545 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2546 selected);
2547 } else
9bcb3eef 2548 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2549 addpath_tx_id);
d62a17ae 2550 }
2551
2552 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2553 else {
9bcb3eef 2554 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2555 }
200df115 2556}
fee0f4c6 2557
3064bf43 2558/*
e1072051 2559 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2560 * This is called at the end of route processing.
3064bf43 2561 */
9bcb3eef 2562void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2563{
40381db7 2564 struct bgp_path_info *pi;
3064bf43 2565
9bcb3eef 2566 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2567 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2568 continue;
40381db7
DS
2569 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2570 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2571 }
3064bf43 2572}
2573
2574/*
2575 * Has the route changed from the RIB's perspective? This is invoked only
2576 * if the route selection returns the same best route as earlier - to
2577 * determine if we need to update zebra or not.
2578 */
9bcb3eef 2579bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2580{
4b7e6066 2581 struct bgp_path_info *mpinfo;
d62a17ae 2582
2bb9eff4
DS
2583 /* If this is multipath, check all selected paths for any nexthop
2584 * change or attribute change. Some attribute changes (e.g., community)
2585 * aren't of relevance to the RIB, but we'll update zebra to ensure
2586 * we handle the case of BGP nexthop change. This is the behavior
2587 * when the best path has an attribute change anyway.
d62a17ae 2588 */
1defdda8 2589 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2590 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2591 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2592 return true;
d62a17ae 2593
2bb9eff4
DS
2594 /*
2595 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2596 */
18ee8310
DS
2597 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2598 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2599 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2600 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2601 return true;
d62a17ae 2602 }
3064bf43 2603
d62a17ae 2604 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2605 return false;
3064bf43 2606}
2607
d62a17ae 2608struct bgp_process_queue {
2609 struct bgp *bgp;
9bcb3eef 2610 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2611#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2612 unsigned int flags;
2613 unsigned int queued;
200df115 2614};
2615
3b0c17e1 2616static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2617 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2618 struct bgp_path_info *new_select,
2619 struct bgp_path_info *old_select)
2620{
9bcb3eef 2621 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2622
2623 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2624 return;
2625
2626 if (advertise_type5_routes(bgp, afi) && new_select
2627 && is_route_injectable_into_evpn(new_select)) {
2628
2629 /* apply the route-map */
2630 if (bgp->adv_cmd_rmap[afi][safi].map) {
2631 route_map_result_t ret;
2632 struct bgp_path_info rmap_path;
2633 struct bgp_path_info_extra rmap_path_extra;
2634 struct attr dummy_attr;
2635
2636 dummy_attr = *new_select->attr;
2637
2638 /* Fill temp path_info */
9bcb3eef 2639 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2640 new_select, new_select->peer,
2641 &dummy_attr);
2642
2643 RESET_FLAG(dummy_attr.rmap_change_flags);
2644
2645 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2646 p, &rmap_path);
3b0c17e1 2647
2648 if (ret == RMAP_DENYMATCH) {
2649 bgp_attr_flush(&dummy_attr);
2650 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2651 safi);
2652 } else
2653 bgp_evpn_advertise_type5_route(
2654 bgp, p, &dummy_attr, afi, safi);
2655 } else {
2656 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2657 afi, safi);
2658 }
2659 } else if (advertise_type5_routes(bgp, afi) && old_select
2660 && is_route_injectable_into_evpn(old_select))
2661 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2662}
2663
3103e8d2
DS
2664/*
2665 * old_select = The old best path
2666 * new_select = the new best path
2667 *
2668 * if (!old_select && new_select)
2669 * We are sending new information on.
2670 *
2671 * if (old_select && new_select) {
2672 * if (new_select != old_select)
2673 * We have a new best path send a change
2674 * else
2675 * We've received a update with new attributes that needs
2676 * to be passed on.
2677 * }
2678 *
2679 * if (old_select && !new_select)
2680 * We have no eligible route that we can announce or the rn
2681 * is being removed.
2682 */
9bcb3eef 2683static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2684 afi_t afi, safi_t safi)
d62a17ae 2685{
4b7e6066
DS
2686 struct bgp_path_info *new_select;
2687 struct bgp_path_info *old_select;
2688 struct bgp_path_info_pair old_and_new;
ddb5b488 2689 int debug = 0;
d62a17ae 2690
892fedb6 2691 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2692 if (dest)
2693 debug = bgp_debug_bestpath(dest);
b54892e0 2694 if (debug)
f4c713ae 2695 zlog_debug(
56ca3b5b 2696 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2697 __func__, dest);
f4c713ae
LB
2698 return;
2699 }
d62a17ae 2700 /* Is it end of initial update? (after startup) */
9bcb3eef 2701 if (!dest) {
d62a17ae 2702 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2703 sizeof(bgp->update_delay_zebra_resume_time));
2704
2705 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2706 FOREACH_AFI_SAFI (afi, safi) {
2707 if (bgp_fibupd_safi(safi))
2708 bgp_zebra_announce_table(bgp, afi, safi);
2709 }
d62a17ae 2710 bgp->main_peers_update_hold = 0;
2711
2712 bgp_start_routeadv(bgp);
aac24838 2713 return;
d62a17ae 2714 }
cb1faec9 2715
9bcb3eef 2716 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2717
9bcb3eef 2718 debug = bgp_debug_bestpath(dest);
b54892e0 2719 if (debug)
56ca3b5b 2720 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2721 afi2str(afi), safi2str(safi));
ddb5b488 2722
f009ff26 2723 /* The best path calculation for the route is deferred if
2724 * BGP_NODE_SELECT_DEFER is set
2725 */
9bcb3eef 2726 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2727 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2728 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2729 return;
2730 }
2731
d62a17ae 2732 /* Best path selection. */
9bcb3eef 2733 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2734 afi, safi);
2735 old_select = old_and_new.old;
2736 new_select = old_and_new.new;
2737
2738 /* Do we need to allocate or free labels?
2739 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2740 * necessary to do this upon changes to best path. Exceptions:
2741 * - label index has changed -> recalculate resulting label
2742 * - path_info sub_type changed -> switch to/from implicit-null
2743 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2744 */
318cac96 2745 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2746 if (new_select) {
2747 if (!old_select
2748 || bgp_label_index_differs(new_select, old_select)
57592a53 2749 || new_select->sub_type != old_select->sub_type
9bcb3eef 2750 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2751 /* Enforced penultimate hop popping:
2752 * implicit-null for local routes, aggregate
2753 * and redistributed routes
2754 */
d62a17ae 2755 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2756 || new_select->sub_type
2757 == BGP_ROUTE_AGGREGATE
2758 || new_select->sub_type
2759 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2760 if (CHECK_FLAG(
9bcb3eef 2761 dest->flags,
992dd67e
PR
2762 BGP_NODE_REGISTERED_FOR_LABEL)
2763 || CHECK_FLAG(
2764 dest->flags,
2765 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2766 bgp_unregister_for_label(dest);
70e98a7f 2767 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2768 &dest->local_label);
2769 bgp_set_valid_label(&dest->local_label);
d62a17ae 2770 } else
9bcb3eef
DS
2771 bgp_register_for_label(dest,
2772 new_select);
d62a17ae 2773 }
9bcb3eef 2774 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2775 BGP_NODE_REGISTERED_FOR_LABEL)
2776 || CHECK_FLAG(dest->flags,
2777 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2778 bgp_unregister_for_label(dest);
318cac96 2779 }
992dd67e
PR
2780 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2781 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2782 bgp_unregister_for_label(dest);
d62a17ae 2783 }
cd1964ff 2784
b54892e0 2785 if (debug)
ddb5b488 2786 zlog_debug(
56ca3b5b 2787 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2788 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2789 old_select, new_select);
ddb5b488 2790
d62a17ae 2791 /* If best route remains the same and this is not due to user-initiated
2792 * clear, see exactly what needs to be done.
2793 */
d62a17ae 2794 if (old_select && old_select == new_select
9bcb3eef 2795 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2796 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2797 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2798 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2799#ifdef ENABLE_BGP_VNC
d62a17ae 2800 vnc_import_bgp_add_route(bgp, p, old_select);
2801 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2802#endif
bb744275 2803 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2804 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2805
2806 if (new_select->type == ZEBRA_ROUTE_BGP
2807 && (new_select->sub_type == BGP_ROUTE_NORMAL
2808 || new_select->sub_type
2809 == BGP_ROUTE_IMPORTED))
2810
9bcb3eef 2811 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2812 bgp, afi, safi);
2813 }
d62a17ae 2814 }
d62a17ae 2815
2816 /* If there is a change of interest to peers, reannounce the
2817 * route. */
1defdda8 2818 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2819 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2820 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2821 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2822
2823 /* unicast routes must also be annouced to
2824 * labeled-unicast update-groups */
2825 if (safi == SAFI_UNICAST)
2826 group_announce_route(bgp, afi,
9bcb3eef 2827 SAFI_LABELED_UNICAST, dest,
d62a17ae 2828 new_select);
2829
1defdda8 2830 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2831 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2832 }
fee0f4c6 2833
3b0c17e1 2834 /* advertise/withdraw type-5 routes */
2835 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2836 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2837 bgp_process_evpn_route_injection(
9bcb3eef 2838 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2839
b1875e65 2840 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2841 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2842 bgp_zebra_clear_route_change_flags(dest);
2843 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2844 return;
d62a17ae 2845 }
8ad7271d 2846
d62a17ae 2847 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2848 */
9bcb3eef 2849 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2850
2851 /* bestpath has changed; bump version */
2852 if (old_select || new_select) {
9bcb3eef 2853 bgp_bump_version(dest);
d62a17ae 2854
2855 if (!bgp->t_rmap_def_originate_eval) {
2856 bgp_lock(bgp);
2857 thread_add_timer(
2858 bm->master,
2859 update_group_refresh_default_originate_route_map,
2860 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2861 &bgp->t_rmap_def_originate_eval);
2862 }
2863 }
3f9c7369 2864
d62a17ae 2865 if (old_select)
9bcb3eef 2866 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2867 if (new_select) {
ddb5b488
PZ
2868 if (debug)
2869 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2870 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2871 bgp_path_info_unset_flag(dest, new_select,
2872 BGP_PATH_ATTR_CHANGED);
1defdda8 2873 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2874 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2875 }
338b3424 2876
49e5a4a0 2877#ifdef ENABLE_BGP_VNC
d62a17ae 2878 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2879 if (old_select != new_select) {
2880 if (old_select) {
2881 vnc_import_bgp_exterior_del_route(bgp, p,
2882 old_select);
2883 vnc_import_bgp_del_route(bgp, p, old_select);
2884 }
2885 if (new_select) {
2886 vnc_import_bgp_exterior_add_route(bgp, p,
2887 new_select);
2888 vnc_import_bgp_add_route(bgp, p, new_select);
2889 }
2890 }
2891 }
65efcfce
LB
2892#endif
2893
9bcb3eef 2894 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2895
2896 /* unicast routes must also be annouced to labeled-unicast update-groups
2897 */
2898 if (safi == SAFI_UNICAST)
9bcb3eef 2899 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2900 new_select);
2901
2902 /* FIB update. */
2903 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2904 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2905 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2906 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2907 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2908 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2909
2910 /* if this is an evpn imported type-5 prefix,
2911 * we need to withdraw the route first to clear
2912 * the nh neigh and the RMAC entry.
2913 */
2914 if (old_select &&
2915 is_route_parent_evpn(old_select))
2916 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2917
9bcb3eef 2918 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2919 } else {
d62a17ae 2920 /* Withdraw the route from the kernel. */
2921 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2922 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2923 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2924 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2925
568e10ca 2926 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2927 }
718e3744 2928 }
3064bf43 2929
9bcb3eef 2930 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2931 old_select);
5424b7ba 2932
d62a17ae 2933 /* Clear any route change flags. */
9bcb3eef 2934 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2935
18ee8310 2936 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2937 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2938 bgp_path_info_reap(dest, old_select);
d62a17ae 2939
9bcb3eef 2940 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2941 return;
718e3744 2942}
2943
f009ff26 2944/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2945int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2946{
9bcb3eef 2947 struct bgp_dest *dest;
f009ff26 2948 int cnt = 0;
2949 struct afi_safi_info *thread_info;
f009ff26 2950
56c226e7
DS
2951 if (bgp->gr_info[afi][safi].t_route_select) {
2952 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2953
2954 thread_info = THREAD_ARG(t);
2955 XFREE(MTYPE_TMP, thread_info);
f009ff26 2956 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2957 }
f009ff26 2958
2959 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2960 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2961 get_afi_safi_str(afi, safi, false),
26742171 2962 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2963 }
2964
2965 /* Process the route list */
6338d242
DS
2966 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2967 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2968 dest = bgp_route_next(dest)) {
2969 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2970 continue;
2971
2972 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2973 bgp->gr_info[afi][safi].gr_deferred--;
2974 bgp_process_main_one(bgp, dest, afi, safi);
2975 cnt++;
2976 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2977 bgp_dest_unlock_node(dest);
2978 break;
f009ff26 2979 }
f009ff26 2980 }
2981
9e3b51a7 2982 /* Send EOR message when all routes are processed */
6338d242 2983 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2984 bgp_send_delayed_eor(bgp);
8c48b3b6 2985 /* Send route processing complete message to RIB */
2986 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2987 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2988 return 0;
9e3b51a7 2989 }
f009ff26 2990
2991 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2992
2993 thread_info->afi = afi;
2994 thread_info->safi = safi;
2995 thread_info->bgp = bgp;
2996
2997 /* If there are more routes to be processed, start the
2998 * selection timer
2999 */
3000 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3001 BGP_ROUTE_SELECT_DELAY,
3002 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3003 return 0;
3004}
3005
aac24838 3006static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3007{
aac24838
JB
3008 struct bgp_process_queue *pqnode = data;
3009 struct bgp *bgp = pqnode->bgp;
d62a17ae 3010 struct bgp_table *table;
9bcb3eef 3011 struct bgp_dest *dest;
aac24838
JB
3012
3013 /* eoiu marker */
3014 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3015 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3016 /* should always have dedicated wq call */
3017 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3018 return WQ_SUCCESS;
3019 }
3020
ac021f40 3021 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3022 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3023 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3024 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3025 table = bgp_dest_table(dest);
3026 /* note, new DESTs may be added as part of processing */
3027 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3028
9bcb3eef 3029 bgp_dest_unlock_node(dest);
d62a17ae 3030 bgp_table_unlock(table);
3031 }
aac24838
JB
3032
3033 return WQ_SUCCESS;
3034}
3035
3036static void bgp_processq_del(struct work_queue *wq, void *data)
3037{
3038 struct bgp_process_queue *pqnode = data;
3039
3040 bgp_unlock(pqnode->bgp);
3041
3042 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3043}
3044
b6c386bb 3045void bgp_process_queue_init(struct bgp *bgp)
200df115 3046{
b6c386bb
DS
3047 if (!bgp->process_queue) {
3048 char name[BUFSIZ];
3049
3050 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3051 bgp->process_queue = work_queue_new(bm->master, name);
3052 }
3053
3054 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3055 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3056 bgp->process_queue->spec.max_retries = 0;
3057 bgp->process_queue->spec.hold = 50;
d62a17ae 3058 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3059 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3060}
3061
cfe8d15a 3062static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3063{
3064 struct bgp_process_queue *pqnode;
3065
a4d82a8a
PZ
3066 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3067 sizeof(struct bgp_process_queue));
aac24838
JB
3068
3069 /* unlocked in bgp_processq_del */
3070 pqnode->bgp = bgp_lock(bgp);
3071 STAILQ_INIT(&pqnode->pqueue);
3072
aac24838
JB
3073 return pqnode;
3074}
3075
9bcb3eef 3076void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3077{
aac24838 3078#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3079 struct work_queue *wq = bgp->process_queue;
d62a17ae 3080 struct bgp_process_queue *pqnode;
cfe8d15a 3081 int pqnode_reuse = 0;
495f0b13 3082
d62a17ae 3083 /* already scheduled for processing? */
9bcb3eef 3084 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3085 return;
2e02b9b2 3086
f009ff26 3087 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3088 * the workqueue
3089 */
9bcb3eef 3090 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3091 if (BGP_DEBUG(update, UPDATE_OUT))
3092 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3093 dest);
f009ff26 3094 return;
3095 }
3096
aac24838 3097 if (wq == NULL)
d62a17ae 3098 return;
3099
aac24838 3100 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3101 limit only if is from the same BGP view and it's not an EOIU marker
3102 */
aac24838
JB
3103 if (work_queue_item_count(wq)) {
3104 struct work_queue_item *item = work_queue_last_item(wq);
3105 pqnode = item->data;
228da428 3106
a4d82a8a
PZ
3107 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3108 || pqnode->bgp != bgp
3109 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3110 pqnode = bgp_processq_alloc(bgp);
3111 else
3112 pqnode_reuse = 1;
aac24838 3113 } else
cfe8d15a 3114 pqnode = bgp_processq_alloc(bgp);
aac24838 3115 /* all unlocked in bgp_process_wq */
9bcb3eef 3116 bgp_table_lock(bgp_dest_table(dest));
aac24838 3117
9bcb3eef
DS
3118 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3119 bgp_dest_lock_node(dest);
aac24838 3120
60466a63 3121 /* can't be enqueued twice */
9bcb3eef
DS
3122 assert(STAILQ_NEXT(dest, pq) == NULL);
3123 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3124 pqnode->queued++;
3125
cfe8d15a
LB
3126 if (!pqnode_reuse)
3127 work_queue_add(wq, pqnode);
3128
d62a17ae 3129 return;
fee0f4c6 3130}
0a486e5f 3131
d62a17ae 3132void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3133{
d62a17ae 3134 struct bgp_process_queue *pqnode;
cb1faec9 3135
b6c386bb 3136 if (bgp->process_queue == NULL)
d62a17ae 3137 return;
2e02b9b2 3138
cfe8d15a 3139 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3140
aac24838 3141 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3142 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3143}
3144
d62a17ae 3145static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3146{
d62a17ae 3147 struct peer *peer;
0a486e5f 3148
d62a17ae 3149 peer = THREAD_ARG(thread);
3150 peer->t_pmax_restart = NULL;
0a486e5f 3151
d62a17ae 3152 if (bgp_debug_neighbor_events(peer))
3153 zlog_debug(
3154 "%s Maximum-prefix restart timer expired, restore peering",
3155 peer->host);
0a486e5f 3156
a9bafa95 3157 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3158 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3159
d62a17ae 3160 return 0;
0a486e5f 3161}
3162
9cbd06e0
DA
3163static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3164 safi_t safi)
3165{
3166 uint32_t count = 0;
f41b0459 3167 bool filtered = false;
9cbd06e0
DA
3168 struct bgp_dest *dest;
3169 struct bgp_adj_in *ain;
40bb2ccf 3170 struct attr attr = {};
9cbd06e0
DA
3171 struct bgp_table *table = peer->bgp->rib[afi][safi];
3172
3173 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3174 for (ain = dest->adj_in; ain; ain = ain->next) {
3175 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3176
3177 attr = *ain->attr;
9cbd06e0
DA
3178
3179 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3180 == FILTER_DENY)
f41b0459
DA
3181 filtered = true;
3182
3183 if (bgp_input_modifier(
3184 peer, rn_p, &attr, afi, safi,
3185 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3186 NULL, 0, NULL)
3187 == RMAP_DENY)
3188 filtered = true;
3189
3190 if (filtered)
9cbd06e0 3191 count++;
f41b0459
DA
3192
3193 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3194 }
3195 }
3196
3197 return count;
3198}
3199
3dc339cd
DA
3200bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3201 int always)
718e3744 3202{
d62a17ae 3203 iana_afi_t pkt_afi;
5c525538 3204 iana_safi_t pkt_safi;
9cbd06e0
DA
3205 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3206 PEER_FLAG_MAX_PREFIX_FORCE))
3207 ? bgp_filtered_routes_count(peer, afi, safi)
3208 + peer->pcount[afi][safi]
3209 : peer->pcount[afi][safi];
9cabb64b 3210
d62a17ae 3211 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3212 return false;
e0701b79 3213
9cbd06e0 3214 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3215 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3216 PEER_STATUS_PREFIX_LIMIT)
3217 && !always)
3dc339cd 3218 return false;
e0701b79 3219
d62a17ae 3220 zlog_info(
6cde4b45 3221 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3222 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3223 peer->pmax[afi][safi]);
d62a17ae 3224 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3225
3226 if (CHECK_FLAG(peer->af_flags[afi][safi],
3227 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3228 return false;
d62a17ae 3229
3230 /* Convert AFI, SAFI to values for packet. */
3231 pkt_afi = afi_int2iana(afi);
3232 pkt_safi = safi_int2iana(safi);
3233 {
d7c0a89a 3234 uint8_t ndata[7];
d62a17ae 3235
3236 ndata[0] = (pkt_afi >> 8);
3237 ndata[1] = pkt_afi;
3238 ndata[2] = pkt_safi;
3239 ndata[3] = (peer->pmax[afi][safi] >> 24);
3240 ndata[4] = (peer->pmax[afi][safi] >> 16);
3241 ndata[5] = (peer->pmax[afi][safi] >> 8);
3242 ndata[6] = (peer->pmax[afi][safi]);
3243
3244 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3245 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3246 BGP_NOTIFY_CEASE_MAX_PREFIX,
3247 ndata, 7);
3248 }
3249
3250 /* Dynamic peers will just close their connection. */
3251 if (peer_dynamic_neighbor(peer))
3dc339cd 3252 return true;
d62a17ae 3253
3254 /* restart timer start */
3255 if (peer->pmax_restart[afi][safi]) {
3256 peer->v_pmax_restart =
3257 peer->pmax_restart[afi][safi] * 60;
3258
3259 if (bgp_debug_neighbor_events(peer))
3260 zlog_debug(
3261 "%s Maximum-prefix restart timer started for %d secs",
3262 peer->host, peer->v_pmax_restart);
3263
3264 BGP_TIMER_ON(peer->t_pmax_restart,
3265 bgp_maximum_prefix_restart_timer,
3266 peer->v_pmax_restart);
3267 }
3268
3dc339cd 3269 return true;
d62a17ae 3270 } else
3271 UNSET_FLAG(peer->af_sflags[afi][safi],
3272 PEER_STATUS_PREFIX_LIMIT);
3273
b1823b69
DS
3274 if (pcount
3275 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3276 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3277 PEER_STATUS_PREFIX_THRESHOLD)
3278 && !always)
3dc339cd 3279 return false;
d62a17ae 3280
3281 zlog_info(
6cde4b45 3282 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3283 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3284 peer->pmax[afi][safi]);
d62a17ae 3285 SET_FLAG(peer->af_sflags[afi][safi],
3286 PEER_STATUS_PREFIX_THRESHOLD);
3287 } else
3288 UNSET_FLAG(peer->af_sflags[afi][safi],
3289 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3290 return false;
718e3744 3291}
3292
b40d939b 3293/* Unconditionally remove the route from the RIB, without taking
3294 * damping into consideration (eg, because the session went down)
3295 */
9bcb3eef 3296void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3297 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3298{
f009ff26 3299
3300 struct bgp *bgp = NULL;
3301 bool delete_route = false;
3302
9bcb3eef
DS
3303 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3304 safi);
d62a17ae 3305
f009ff26 3306 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3307 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3308
f009ff26 3309 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3310 * flag
3311 */
3312 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3313 delete_route = true;
9bcb3eef 3314 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3315 delete_route = true;
f009ff26 3316 if (delete_route) {
9bcb3eef
DS
3317 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3318 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3319 bgp = pi->peer->bgp;
26742171 3320 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3321 }
3322 }
3323 }
4a11bf2c 3324
9bcb3eef
DS
3325 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3326 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3327}
3328
9bcb3eef 3329static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3330 struct peer *peer, afi_t afi, safi_t safi,
3331 struct prefix_rd *prd)
3332{
9bcb3eef 3333 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3334
d62a17ae 3335 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3336 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3337 */
40ec3340
DS
3338 if (peer->sort == BGP_PEER_EBGP) {
3339 if (get_active_bdc_from_pi(pi, afi, safi)) {
3340 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3341 == BGP_DAMP_SUPPRESSED) {
3342 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3343 safi);
3344 return;
3345 }
d62a17ae 3346 }
40ec3340 3347 }
d62a17ae 3348
49e5a4a0 3349#ifdef ENABLE_BGP_VNC
d62a17ae 3350 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3351 struct bgp_dest *pdest = NULL;
d62a17ae 3352 struct bgp_table *table = NULL;
3353
9bcb3eef
DS
3354 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3355 (struct prefix *)prd);
3356 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3357 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3358
3359 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3360 peer->bgp, prd, table, p, pi);
d62a17ae 3361 }
9bcb3eef 3362 bgp_dest_unlock_node(pdest);
d62a17ae 3363 }
3364 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3365 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3366
b54892e0
DS
3367 vnc_import_bgp_del_route(peer->bgp, p, pi);
3368 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3369 }
65efcfce 3370 }
d62a17ae 3371#endif
128ea8ab 3372
d62a17ae 3373 /* If this is an EVPN route, process for un-import. */
3374 if (safi == SAFI_EVPN)
b54892e0 3375 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3376
9bcb3eef 3377 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3378}
3379
4b7e6066
DS
3380struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3381 struct peer *peer, struct attr *attr,
9bcb3eef 3382 struct bgp_dest *dest)
fb018d25 3383{
4b7e6066 3384 struct bgp_path_info *new;
fb018d25 3385
d62a17ae 3386 /* Make new BGP info. */
4b7e6066 3387 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3388 new->type = type;
3389 new->instance = instance;
3390 new->sub_type = sub_type;
3391 new->peer = peer;
3392 new->attr = attr;
3393 new->uptime = bgp_clock();
9bcb3eef 3394 new->net = dest;
d62a17ae 3395 return new;
fb018d25
DS
3396}
3397
d62a17ae 3398static void overlay_index_update(struct attr *attr,
d62a17ae 3399 union gw_addr *gw_ip)
684a7227 3400{
d62a17ae 3401 if (!attr)
3402 return;
d62a17ae 3403 if (gw_ip == NULL) {
6c924775
DS
3404 struct bgp_route_evpn eo;
3405
3406 memset(&eo, 0, sizeof(eo));
3407 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3408 } else {
6c924775
DS
3409 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3410
3411 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3412 }
684a7227
PG
3413}
3414
40381db7 3415static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3416 union gw_addr *gw_ip)
3417{
6c924775
DS
3418 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3419 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3420 union {
0a50c248 3421 esi_t esi;
11ebf4ed
DS
3422 union gw_addr ip;
3423 } temp;
d62a17ae 3424
3425 if (afi != AFI_L2VPN)
3426 return true;
11ebf4ed 3427
6c924775 3428 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3429
3430 if (gw_ip == NULL) {
3431 memset(&temp, 0, sizeof(temp));
40381db7 3432 path_gw_ip_remote = &temp.ip;
11ebf4ed 3433 } else
40381db7 3434 path_gw_ip_remote = gw_ip;
11ebf4ed 3435
6c924775 3436 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3437}
3438
c265ee22 3439/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3440bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3441 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3442 struct bgp_dest *dest)
d62a17ae 3443{
2dbe3fa9 3444 bool ret = false;
b099a5c8
DA
3445 bool is_bgp_static_route =
3446 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3447 : false;
d62a17ae 3448
e8442016
DS
3449 /*
3450 * Only validated for unicast and multicast currently.
3451 * Also valid for EVPN where the nexthop is an IP address.
3452 * If we are a bgp static route being checked then there is
3453 * no need to check to see if the nexthop is martian as
3454 * that it should be ok.
3455 */
3456 if (is_bgp_static_route ||
3457 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3458 return false;
d62a17ae 3459
3460 /* If NEXT_HOP is present, validate it. */
3461 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3462 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3463 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3464 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3465 return true;
d62a17ae 3466 }
c265ee22 3467
d62a17ae 3468 /* If MP_NEXTHOP is present, validate it. */
3469 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3470 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3471 * it is not an IPv6 link-local address.
0355b41d
DA
3472 *
3473 * If we receive an UPDATE with nexthop length set to 32 bytes
3474 * we shouldn't discard an UPDATE if it's set to (::).
3475 * The link-local (2st) is validated along the code path later.
d62a17ae 3476 */
3477 if (attr->mp_nexthop_len) {
3478 switch (attr->mp_nexthop_len) {
3479 case BGP_ATTR_NHLEN_IPV4:
3480 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3481 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3482 || IPV4_CLASS_DE(
3483 ntohl(attr->mp_nexthop_global_in.s_addr))
3484 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3485 dest));
d62a17ae 3486 break;
3487
3488 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3489 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3490 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3491 &attr->mp_nexthop_global)
d62a17ae 3492 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3493 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3494 &attr->mp_nexthop_global)
3495 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3496 dest));
d62a17ae 3497 break;
0355b41d
DA
3498 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3499 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3500 || IN6_IS_ADDR_MULTICAST(
3501 &attr->mp_nexthop_global)
3502 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3503 dest));
0355b41d 3504 break;
d62a17ae 3505
3506 default:
3dc339cd 3507 ret = true;
d62a17ae 3508 break;
3509 }
3510 }
c265ee22 3511
d62a17ae 3512 return ret;
3513}
3514
aade37d7 3515static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3516{
3517 struct community *old;
3518 struct community *new;
3519 struct community *merge;
aade37d7 3520 struct community *no_export;
2721dd61
DA
3521
3522 old = attr->community;
aade37d7 3523 no_export = community_str2com("no-export");
2721dd61 3524
b4efa101
DA
3525 assert(no_export);
3526
2721dd61 3527 if (old) {
aade37d7 3528 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3529
3530 if (!old->refcnt)
3531 community_free(&old);
3532
3533 new = community_uniq_sort(merge);
3534 community_free(&merge);
3535 } else {
aade37d7 3536 new = community_dup(no_export);
2721dd61
DA
3537 }
3538
aade37d7 3539 community_free(&no_export);
2721dd61
DA
3540
3541 attr->community = new;
3542 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3543}
3544
5a1ae2c2 3545int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3546 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3547 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3548 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3549 struct bgp_route_evpn *evpn)
d62a17ae 3550{
3551 int ret;
3552 int aspath_loop_count = 0;
9bcb3eef 3553 struct bgp_dest *dest;
d62a17ae 3554 struct bgp *bgp;
3555 struct attr new_attr;
3556 struct attr *attr_new;
40381db7 3557 struct bgp_path_info *pi;
4b7e6066
DS
3558 struct bgp_path_info *new;
3559 struct bgp_path_info_extra *extra;
d62a17ae 3560 const char *reason;
3561 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3562 int connected = 0;
3563 int do_loop_check = 1;
3564 int has_valid_label = 0;
7c312383 3565 afi_t nh_afi;
949b0f24 3566 uint8_t pi_type = 0;
3567 uint8_t pi_sub_type = 0;
3568
c7bb4f00 3569 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3570 char pfxprint[PREFIX2STR_BUFFER];
3571
3572 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3573 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3574 afi, safi, attr);
6401252f
QY
3575 }
3576
49e5a4a0 3577#ifdef ENABLE_BGP_VNC
d62a17ae 3578 int vnc_implicit_withdraw = 0;
65efcfce 3579#endif
d62a17ae 3580 int same_attr = 0;
718e3744 3581
d62a17ae 3582 memset(&new_attr, 0, sizeof(struct attr));
3583 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3584 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3585
d62a17ae 3586 bgp = peer->bgp;
9bcb3eef 3587 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3588 /* TODO: Check to see if we can get rid of "is_valid_label" */
3589 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3590 has_valid_label = (num_labels > 0) ? 1 : 0;
3591 else
3592 has_valid_label = bgp_is_valid_label(label);
718e3744 3593
28f66de2
MS
3594 if (has_valid_label)
3595 assert(label != NULL);
3596
a77e2f4b
S
3597 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3598 * condition :
3599 * Suppress fib is enabled
3600 * BGP_OPT_NO_FIB is not enabled
3601 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3602 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3603 */
3604 if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
3605 (sub_type == BGP_ROUTE_NORMAL) &&
3606 (!bgp_option_check(BGP_OPT_NO_FIB)) &&
3607 (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3608 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3609
d62a17ae 3610 /* When peer's soft reconfiguration enabled. Record input packet in
3611 Adj-RIBs-In. */
3612 if (!soft_reconfig
3613 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3614 && peer != bgp->peer_self)
9bcb3eef 3615 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3616
3617 /* Check previously received route. */
9bcb3eef 3618 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3619 if (pi->peer == peer && pi->type == type
3620 && pi->sub_type == sub_type
3621 && pi->addpath_rx_id == addpath_id)
d62a17ae 3622 break;
3623
3624 /* AS path local-as loop check. */
3625 if (peer->change_local_as) {
c4368918
DW
3626 if (peer->allowas_in[afi][safi])
3627 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3628 else if (!CHECK_FLAG(peer->flags,
3629 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3630 aspath_loop_count = 1;
3631
3632 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3633 > aspath_loop_count) {
b4d46cc9 3634 peer->stat_pfx_aspath_loop++;
9bcb3eef 3635 reason = "as-path contains our own AS A;";
d62a17ae 3636 goto filtered;
3637 }
718e3744 3638 }
718e3744 3639
d62a17ae 3640 /* If the peer is configured for "allowas-in origin" and the last ASN in
3641 * the
3642 * as-path is our ASN then we do not need to call aspath_loop_check
3643 */
3644 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3645 if (aspath_get_last_as(attr->aspath) == bgp->as)
3646 do_loop_check = 0;
3647
3648 /* AS path loop check. */
3649 if (do_loop_check) {
3650 if (aspath_loop_check(attr->aspath, bgp->as)
3651 > peer->allowas_in[afi][safi]
3652 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3653 && aspath_loop_check(attr->aspath, bgp->confed_id)
3654 > peer->allowas_in[afi][safi])) {
b4d46cc9 3655 peer->stat_pfx_aspath_loop++;
d62a17ae 3656 reason = "as-path contains our own AS;";
3657 goto filtered;
3658 }
3659 }
aac9ef6c 3660
d62a17ae 3661 /* Route reflector originator ID check. */
3662 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3663 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3664 peer->stat_pfx_originator_loop++;
d62a17ae 3665 reason = "originator is us;";
3666 goto filtered;
3667 }
718e3744 3668
d62a17ae 3669 /* Route reflector cluster ID check. */
3670 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3671 peer->stat_pfx_cluster_loop++;
d62a17ae 3672 reason = "reflected from the same cluster;";
3673 goto filtered;
3674 }
718e3744 3675
d62a17ae 3676 /* Apply incoming filter. */
3677 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3678 peer->stat_pfx_filter++;
d62a17ae 3679 reason = "filter;";
3680 goto filtered;
3681 }
718e3744 3682
a8b72dc6
DA
3683 /* RFC 8212 to prevent route leaks.
3684 * This specification intends to improve this situation by requiring the
3685 * explicit configuration of both BGP Import and Export Policies for any
3686 * External BGP (EBGP) session such as customers, peers, or
3687 * confederation boundaries for all enabled address families. Through
3688 * codification of the aforementioned requirement, operators will
3689 * benefit from consistent behavior across different BGP
3690 * implementations.
3691 */
1d3fdccf 3692 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3693 if (!bgp_inbound_policy_exists(peer,
3694 &peer->filter[afi][safi])) {
3695 reason = "inbound policy missing";
3696 goto filtered;
3697 }
3698
fb29348a
DA
3699 /* draft-ietf-idr-deprecate-as-set-confed-set
3700 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3701 * Eventually, This document (if approved) updates RFC 4271
3702 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3703 * and obsoletes RFC 6472.
3704 */
7f972cd8 3705 if (peer->bgp->reject_as_sets)
fb29348a
DA
3706 if (aspath_check_as_sets(attr->aspath)) {
3707 reason =
3708 "as-path contains AS_SET or AS_CONFED_SET type;";
3709 goto filtered;
3710 }
3711
6f4f49b2 3712 new_attr = *attr;
d62a17ae 3713
3714 /* Apply incoming route-map.
3715 * NB: new_attr may now contain newly allocated values from route-map
3716 * "set"
3717 * commands, so we need bgp_attr_flush in the error paths, until we
3718 * intern
3719 * the attr (which takes over the memory references) */
9bcb3eef
DS
3720 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3721 num_labels, dest)
3722 == RMAP_DENY) {
b4d46cc9 3723 peer->stat_pfx_filter++;
d62a17ae 3724 reason = "route-map;";
3725 bgp_attr_flush(&new_attr);
3726 goto filtered;
3727 }
718e3744 3728
05864da7 3729 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3730 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3731 /* remove from RIB previous entry */
3732 bgp_zebra_withdraw(p, pi, bgp, safi);
3733 }
3734
7f323236
DW
3735 if (peer->sort == BGP_PEER_EBGP) {
3736
2721dd61
DA
3737 /* rfc7999:
3738 * A BGP speaker receiving an announcement tagged with the
3739 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3740 * NO_EXPORT community as defined in RFC1997, or a
3741 * similar community, to prevent propagation of the
3742 * prefix outside the local AS. The community to prevent
3743 * propagation SHOULD be chosen according to the operator's
3744 * routing policy.
3745 */
3746 if (new_attr.community
3747 && community_include(new_attr.community,
3748 COMMUNITY_BLACKHOLE))
aade37d7 3749 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3750
a4d82a8a
PZ
3751 /* If we receive the graceful-shutdown community from an eBGP
3752 * peer we must lower local-preference */
3753 if (new_attr.community
3754 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3755 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3756 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3757
a4d82a8a
PZ
3758 /* If graceful-shutdown is configured then add the GSHUT
3759 * community to all paths received from eBGP peers */
637e5ba4 3760 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3761 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3762 }
3763
949b0f24 3764 if (pi) {
3765 pi_type = pi->type;
3766 pi_sub_type = pi->sub_type;
3767 }
3768
d62a17ae 3769 /* next hop check. */
a4d82a8a 3770 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3771 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3772 &new_attr, dest)) {
b4d46cc9 3773 peer->stat_pfx_nh_invalid++;
d62a17ae 3774 reason = "martian or self next-hop;";
3775 bgp_attr_flush(&new_attr);
3776 goto filtered;
3777 }
718e3744 3778
5c14a191 3779 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3780 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3781 reason = "self mac;";
3782 goto filtered;
3783 }
3784
1e9be514
QY
3785 /* Update Overlay Index */
3786 if (afi == AFI_L2VPN) {
3787 overlay_index_update(&new_attr,
3788 evpn == NULL ? NULL : &evpn->gw_ip);
3789 }
3790
d62a17ae 3791 attr_new = bgp_attr_intern(&new_attr);
3792
9cbd06e0
DA
3793 /* If maximum prefix count is configured and current prefix
3794 * count exeed it.
3795 */
3796 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3797 return -1;
3798
d62a17ae 3799 /* If the update is implicit withdraw. */
40381db7
DS
3800 if (pi) {
3801 pi->uptime = bgp_clock();
3802 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3803
9bcb3eef 3804 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3805
d62a17ae 3806 /* Same attribute comes in. */
40381db7 3807 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3808 && same_attr
d62a17ae 3809 && (!has_valid_label
40381db7 3810 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3811 num_labels * sizeof(mpls_label_t))
d62a17ae 3812 == 0)
3813 && (overlay_index_equal(
0a50c248 3814 afi, pi,
d62a17ae 3815 evpn == NULL ? NULL : &evpn->gw_ip))) {
40ec3340 3816 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3817 && peer->sort == BGP_PEER_EBGP
40381db7 3818 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3819 if (bgp_debug_update(peer, p, NULL, 1)) {
3820 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3821 afi, safi, prd, p, label,
3822 num_labels, addpath_id ? 1 : 0,
3823 addpath_id, pfx_buf,
3824 sizeof(pfx_buf));
d62a17ae 3825 zlog_debug("%s rcvd %s", peer->host,
3826 pfx_buf);
3827 }
3828
9bcb3eef 3829 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3830 != BGP_DAMP_SUPPRESSED) {
40381db7 3831 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3832 safi);
9bcb3eef 3833 bgp_process(bgp, dest, afi, safi);
d62a17ae 3834 }
3835 } else /* Duplicate - odd */
3836 {
3837 if (bgp_debug_update(peer, p, NULL, 1)) {
3838 if (!peer->rcvd_attr_printed) {
3839 zlog_debug(
3840 "%s rcvd UPDATE w/ attr: %s",
3841 peer->host,
3842 peer->rcvd_attr_str);
3843 peer->rcvd_attr_printed = 1;
3844 }
3845
3846 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3847 afi, safi, prd, p, label,
3848 num_labels, addpath_id ? 1 : 0,
3849 addpath_id, pfx_buf,
3850 sizeof(pfx_buf));
d62a17ae 3851 zlog_debug(
3852 "%s rcvd %s...duplicate ignored",
3853 peer->host, pfx_buf);
3854 }
3855
3856 /* graceful restart STALE flag unset. */
40381db7 3857 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3858 bgp_path_info_unset_flag(
9bcb3eef
DS
3859 dest, pi, BGP_PATH_STALE);
3860 bgp_dest_set_defer_flag(dest, false);
3861 bgp_process(bgp, dest, afi, safi);
d62a17ae 3862 }
3863 }
3864
9bcb3eef 3865 bgp_dest_unlock_node(dest);
d62a17ae 3866 bgp_attr_unintern(&attr_new);
3867
3868 return 0;
3869 }
718e3744 3870
d62a17ae 3871 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3872 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3873 if (bgp_debug_update(peer, p, NULL, 1)) {
3874 bgp_debug_rdpfxpath2str(
a4d82a8a 3875 afi, safi, prd, p, label, num_labels,
d62a17ae 3876 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3877 sizeof(pfx_buf));
3878 zlog_debug(
3879 "%s rcvd %s, flapped quicker than processing",
3880 peer->host, pfx_buf);
3881 }
3882
9bcb3eef 3883 bgp_path_info_restore(dest, pi);
d62a17ae 3884 }
718e3744 3885
d62a17ae 3886 /* Received Logging. */
3887 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3888 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3889 num_labels, addpath_id ? 1 : 0,
3890 addpath_id, pfx_buf,
3891 sizeof(pfx_buf));
d62a17ae 3892 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3893 }
718e3744 3894
d62a17ae 3895 /* graceful restart STALE flag unset. */
f009ff26 3896 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3897 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3898 bgp_dest_set_defer_flag(dest, false);
f009ff26 3899 }
d62a17ae 3900
3901 /* The attribute is changed. */
9bcb3eef 3902 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3903
3904 /* implicit withdraw, decrement aggregate and pcount here.
3905 * only if update is accepted, they'll increment below.
3906 */
40381db7 3907 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3908
3909 /* Update bgp route dampening information. */
40ec3340 3910 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3911 && peer->sort == BGP_PEER_EBGP) {
3912 /* This is implicit withdraw so we should update
40ec3340
DS
3913 * dampening information.
3914 */
40381db7 3915 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3916 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3917 }
49e5a4a0 3918#ifdef ENABLE_BGP_VNC
d62a17ae 3919 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3920 struct bgp_dest *pdest = NULL;
d62a17ae 3921 struct bgp_table *table = NULL;
3922
9bcb3eef
DS
3923 pdest = bgp_node_get(bgp->rib[afi][safi],
3924 (struct prefix *)prd);
3925 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3926 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3927
3928 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3929 bgp, prd, table, p, pi);
d62a17ae 3930 }
9bcb3eef 3931 bgp_dest_unlock_node(pdest);
d62a17ae 3932 }
3933 if ((afi == AFI_IP || afi == AFI_IP6)
3934 && (safi == SAFI_UNICAST)) {
40381db7 3935 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3936 /*
3937 * Implicit withdraw case.
3938 */
3939 ++vnc_implicit_withdraw;
40381db7
DS
3940 vnc_import_bgp_del_route(bgp, p, pi);
3941 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3942 }
3943 }
65efcfce 3944#endif
128ea8ab 3945
d62a17ae 3946 /* Special handling for EVPN update of an existing route. If the
3947 * extended community attribute has changed, we need to
3948 * un-import
3949 * the route using its existing extended community. It will be
3950 * subsequently processed for import with the new extended
3951 * community.
3952 */
6f8c9c11
PR
3953 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3954 && !same_attr) {
40381db7 3955 if ((pi->attr->flag
d62a17ae 3956 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3957 && (attr_new->flag
3958 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3959 int cmp;
3960
40381db7 3961 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3962 attr_new->ecommunity);
3963 if (!cmp) {
3964 if (bgp_debug_update(peer, p, NULL, 1))
3965 zlog_debug(
3966 "Change in EXT-COMM, existing %s new %s",
3967 ecommunity_str(
40381db7 3968 pi->attr->ecommunity),
d62a17ae 3969 ecommunity_str(
3970 attr_new->ecommunity));
6f8c9c11
PR
3971 if (safi == SAFI_EVPN)
3972 bgp_evpn_unimport_route(
3973 bgp, afi, safi, p, pi);
3974 else /* SAFI_MPLS_VPN */
3975 vpn_leak_to_vrf_withdraw(bgp,
3976 pi);
d62a17ae 3977 }
3978 }
3979 }
718e3744 3980
d62a17ae 3981 /* Update to new attribute. */
40381db7
DS
3982 bgp_attr_unintern(&pi->attr);
3983 pi->attr = attr_new;
d62a17ae 3984
3985 /* Update MPLS label */
3986 if (has_valid_label) {
40381db7 3987 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3988 if (extra->label != label) {
3989 memcpy(&extra->label, label,
dbd587da 3990 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3991 extra->num_labels = num_labels;
3992 }
b57ba6d2
MK
3993 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3994 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3995 }
718e3744 3996
e496b420
HS
3997 /* Update SRv6 SID */
3998 if (attr->srv6_l3vpn) {
3999 extra = bgp_path_info_extra_get(pi);
4000 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4001 sid_copy(&extra->sid[0],
4002 &attr->srv6_l3vpn->sid);
4003 extra->num_sids = 1;
4004 }
4005 } else if (attr->srv6_vpn) {
4006 extra = bgp_path_info_extra_get(pi);
4007 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4008 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4009 extra->num_sids = 1;
4010 }
4011 }
4012
49e5a4a0 4013#ifdef ENABLE_BGP_VNC
d62a17ae 4014 if ((afi == AFI_IP || afi == AFI_IP6)
4015 && (safi == SAFI_UNICAST)) {
4016 if (vnc_implicit_withdraw) {
4017 /*
4018 * Add back the route with its new attributes
4019 * (e.g., nexthop).
4020 * The route is still selected, until the route
4021 * selection
4022 * queued by bgp_process actually runs. We have
4023 * to make this
4024 * update to the VNC side immediately to avoid
4025 * racing against
4026 * configuration changes (e.g., route-map
4027 * changes) which
4028 * trigger re-importation of the entire RIB.
4029 */
40381db7
DS
4030 vnc_import_bgp_add_route(bgp, p, pi);
4031 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4032 }
4033 }
65efcfce
LB
4034#endif
4035
d62a17ae 4036 /* Update bgp route dampening information. */
40ec3340 4037 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 4038 && peer->sort == BGP_PEER_EBGP) {
4039 /* Now we do normal update dampening. */
9bcb3eef 4040 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4041 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4042 bgp_dest_unlock_node(dest);
d62a17ae 4043 return 0;
4044 }
4045 }
128ea8ab 4046
d62a17ae 4047 /* Nexthop reachability check - for unicast and
4048 * labeled-unicast.. */
7c312383
AD
4049 if (((afi == AFI_IP || afi == AFI_IP6)
4050 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4051 || (safi == SAFI_EVPN &&
4052 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4053 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4054 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4055 && !CHECK_FLAG(peer->flags,
4056 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4057 && !CHECK_FLAG(bgp->flags,
4058 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4059 connected = 1;
4060 else
4061 connected = 0;
4062
960035b2
PZ
4063 struct bgp *bgp_nexthop = bgp;
4064
40381db7
DS
4065 if (pi->extra && pi->extra->bgp_orig)
4066 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4067
7c312383
AD
4068 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4069
4070 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4053e952 4071 safi, pi, NULL, connected)
a4d82a8a 4072 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4073 bgp_path_info_set_flag(dest, pi,
4074 BGP_PATH_VALID);
d62a17ae 4075 else {
4076 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4077 zlog_debug("%s(%pI4): NH unresolved",
4078 __func__,
4079 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4080 }
9bcb3eef 4081 bgp_path_info_unset_flag(dest, pi,
18ee8310 4082 BGP_PATH_VALID);
d62a17ae 4083 }
4084 } else
9bcb3eef 4085 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4086
49e5a4a0 4087#ifdef ENABLE_BGP_VNC
d62a17ae 4088 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4089 struct bgp_dest *pdest = NULL;
d62a17ae 4090 struct bgp_table *table = NULL;
4091
9bcb3eef
DS
4092 pdest = bgp_node_get(bgp->rib[afi][safi],
4093 (struct prefix *)prd);
4094 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4095 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4096
4097 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4098 bgp, prd, table, p, pi);
d62a17ae 4099 }
9bcb3eef 4100 bgp_dest_unlock_node(pdest);
d62a17ae 4101 }
4102#endif
718e3744 4103
d62a17ae 4104 /* If this is an EVPN route and some attribute has changed,
4105 * process
4106 * route for import. If the extended community has changed, we
4107 * would
4108 * have done the un-import earlier and the import would result
4109 * in the
4110 * route getting injected into appropriate L2 VNIs. If it is
4111 * just
4112 * some other attribute change, the import will result in
4113 * updating
4114 * the attributes for the route in the VNI(s).
4115 */
7c312383
AD
4116 if (safi == SAFI_EVPN && !same_attr &&
4117 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4118 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4119
4120 /* Process change. */
40381db7 4121 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4122
9bcb3eef
DS
4123 bgp_process(bgp, dest, afi, safi);
4124 bgp_dest_unlock_node(dest);
558d1fec 4125
ddb5b488
PZ
4126 if (SAFI_UNICAST == safi
4127 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4128 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4129
40381db7 4130 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4131 }
4132 if ((SAFI_MPLS_VPN == safi)
4133 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4134
40381db7 4135 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4136 }
4137
49e5a4a0 4138#ifdef ENABLE_BGP_VNC
d62a17ae 4139 if (SAFI_MPLS_VPN == safi) {
4140 mpls_label_t label_decoded = decode_label(label);
28070ee3 4141
d62a17ae 4142 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4143 type, sub_type, &label_decoded);
4144 }
4145 if (SAFI_ENCAP == safi) {
4146 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4147 type, sub_type, NULL);
4148 }
28070ee3
PZ
4149#endif
4150
d62a17ae 4151 return 0;
4152 } // End of implicit withdraw
718e3744 4153
d62a17ae 4154 /* Received Logging. */
4155 if (bgp_debug_update(peer, p, NULL, 1)) {
4156 if (!peer->rcvd_attr_printed) {
4157 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4158 peer->rcvd_attr_str);
4159 peer->rcvd_attr_printed = 1;
4160 }
718e3744 4161
a4d82a8a 4162 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4163 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4164 sizeof(pfx_buf));
4165 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4166 }
718e3744 4167
d62a17ae 4168 /* Make new BGP info. */
9bcb3eef 4169 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4170
d62a17ae 4171 /* Update MPLS label */
4172 if (has_valid_label) {
18ee8310 4173 extra = bgp_path_info_extra_get(new);
8ba71050 4174 if (extra->label != label) {
dbd587da
QY
4175 memcpy(&extra->label, label,
4176 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4177 extra->num_labels = num_labels;
4178 }
b57ba6d2
MK
4179 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4180 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4181 }
718e3744 4182
e496b420
HS
4183 /* Update SRv6 SID */
4184 if (safi == SAFI_MPLS_VPN) {
4185 extra = bgp_path_info_extra_get(new);
4186 if (attr->srv6_l3vpn) {
4187 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4188 extra->num_sids = 1;
4189 } else if (attr->srv6_vpn) {
4190 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4191 extra->num_sids = 1;
4192 }
4193 }
4194
d62a17ae 4195 /* Update Overlay Index */
4196 if (afi == AFI_L2VPN) {
4197 overlay_index_update(new->attr,
d62a17ae 4198 evpn == NULL ? NULL : &evpn->gw_ip);
4199 }
4200 /* Nexthop reachability check. */
7c312383
AD
4201 if (((afi == AFI_IP || afi == AFI_IP6)
4202 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4203 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4204 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4205 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4206 && !CHECK_FLAG(peer->flags,
4207 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4208 && !CHECK_FLAG(bgp->flags,
4209 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4210 connected = 1;
4211 else
4212 connected = 0;
4213
7c312383
AD
4214 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4215
4053e952 4216 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
7c312383 4217 connected)
a4d82a8a 4218 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4219 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4220 else {
4221 if (BGP_DEBUG(nht, NHT)) {
4222 char buf1[INET6_ADDRSTRLEN];
4223 inet_ntop(AF_INET,
4224 (const void *)&attr_new->nexthop,
4225 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4226 zlog_debug("%s(%s): NH unresolved", __func__,
4227 buf1);
d62a17ae 4228 }
9bcb3eef 4229 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4230 }
4231 } else
9bcb3eef 4232 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4233
d62a17ae 4234 /* Addpath ID */
4235 new->addpath_rx_id = addpath_id;
4236
4237 /* Increment prefix */
4238 bgp_aggregate_increment(bgp, p, new, afi, safi);
4239
4240 /* Register new BGP information. */
9bcb3eef 4241 bgp_path_info_add(dest, new);
d62a17ae 4242
4243 /* route_node_get lock */
9bcb3eef 4244 bgp_dest_unlock_node(dest);
558d1fec 4245
49e5a4a0 4246#ifdef ENABLE_BGP_VNC
d62a17ae 4247 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4248 struct bgp_dest *pdest = NULL;
d62a17ae 4249 struct bgp_table *table = NULL;
4250
9bcb3eef
DS
4251 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4252 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4253 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4254
4255 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4256 bgp, prd, table, p, new);
4257 }
9bcb3eef 4258 bgp_dest_unlock_node(pdest);
d62a17ae 4259 }
65efcfce
LB
4260#endif
4261
d62a17ae 4262 /* If this is an EVPN route, process for import. */
7c312383 4263 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4264 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4265
9bcb3eef 4266 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4267
d62a17ae 4268 /* Process change. */
9bcb3eef 4269 bgp_process(bgp, dest, afi, safi);
718e3744 4270
ddb5b488
PZ
4271 if (SAFI_UNICAST == safi
4272 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4273 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4274 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4275 }
4276 if ((SAFI_MPLS_VPN == safi)
4277 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4278
4279 vpn_leak_to_vrf_update(bgp, new);
4280 }
49e5a4a0 4281#ifdef ENABLE_BGP_VNC
d62a17ae 4282 if (SAFI_MPLS_VPN == safi) {
4283 mpls_label_t label_decoded = decode_label(label);
28070ee3 4284
d62a17ae 4285 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4286 sub_type, &label_decoded);
4287 }
4288 if (SAFI_ENCAP == safi) {
4289 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4290 sub_type, NULL);
4291 }
28070ee3
PZ
4292#endif
4293
d62a17ae 4294 return 0;
718e3744 4295
d62a17ae 4296/* This BGP update is filtered. Log the reason then update BGP
4297 entry. */
4298filtered:
9bcb3eef 4299 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4300
d62a17ae 4301 if (bgp_debug_update(peer, p, NULL, 1)) {
4302 if (!peer->rcvd_attr_printed) {
4303 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4304 peer->rcvd_attr_str);
4305 peer->rcvd_attr_printed = 1;
4306 }
718e3744 4307
a4d82a8a 4308 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4309 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4310 sizeof(pfx_buf));
4311 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4312 peer->host, pfx_buf, reason);
4313 }
128ea8ab 4314
40381db7 4315 if (pi) {
d62a17ae 4316 /* If this is an EVPN route, un-import it as it is now filtered.
4317 */
4318 if (safi == SAFI_EVPN)
40381db7 4319 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4320
ddb5b488
PZ
4321 if (SAFI_UNICAST == safi
4322 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4323 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4324
40381db7 4325 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4326 }
4327 if ((SAFI_MPLS_VPN == safi)
4328 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4329
40381db7 4330 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4331 }
4332
9bcb3eef 4333 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4334 }
4335
9bcb3eef 4336 bgp_dest_unlock_node(dest);
558d1fec 4337
49e5a4a0 4338#ifdef ENABLE_BGP_VNC
d62a17ae 4339 /*
4340 * Filtered update is treated as an implicit withdrawal (see
4341 * bgp_rib_remove()
4342 * a few lines above)
4343 */
4344 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4345 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4346 0);
4347 }
97736e32
PZ
4348#endif
4349
d62a17ae 4350 return 0;
718e3744 4351}
4352
26a3ffd6 4353int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4354 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4355 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4356 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4357{
d62a17ae 4358 struct bgp *bgp;
4359 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4360 struct bgp_dest *dest;
40381db7 4361 struct bgp_path_info *pi;
718e3744 4362
49e5a4a0 4363#ifdef ENABLE_BGP_VNC
d62a17ae 4364 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4365 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4366 0);
4367 }
28070ee3
PZ
4368#endif
4369
d62a17ae 4370 bgp = peer->bgp;
4371
4372 /* Lookup node. */
9bcb3eef 4373 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4374
4375 /* If peer is soft reconfiguration enabled. Record input packet for
4376 * further calculation.
4377 *
4378 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4379 * routes that are filtered. This tanks out Quagga RS pretty badly due
4380 * to
4381 * the iteration over all RS clients.
4382 * Since we need to remove the entry from adj_in anyway, do that first
4383 * and
4384 * if there was no entry, we don't need to do anything more.
4385 */
4386 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4387 && peer != bgp->peer_self)
9bcb3eef 4388 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4389 peer->stat_pfx_dup_withdraw++;
4390
d62a17ae 4391 if (bgp_debug_update(peer, p, NULL, 1)) {
4392 bgp_debug_rdpfxpath2str(
a4d82a8a 4393 afi, safi, prd, p, label, num_labels,
d62a17ae 4394 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4395 sizeof(pfx_buf));
4396 zlog_debug(
4397 "%s withdrawing route %s not in adj-in",
4398 peer->host, pfx_buf);
4399 }
9bcb3eef 4400 bgp_dest_unlock_node(dest);
d62a17ae 4401 return 0;
4402 }
cd808e74 4403
d62a17ae 4404 /* Lookup withdrawn route. */
9bcb3eef 4405 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4406 if (pi->peer == peer && pi->type == type
4407 && pi->sub_type == sub_type
4408 && pi->addpath_rx_id == addpath_id)
d62a17ae 4409 break;
4410
4411 /* Logging. */
4412 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4413 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4414 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4415 sizeof(pfx_buf));
4416 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4417 pfx_buf);
4418 }
718e3744 4419
d62a17ae 4420 /* Withdraw specified route from routing table. */
40381db7 4421 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4422 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4423 if (SAFI_UNICAST == safi
4424 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4425 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4426 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4427 }
4428 if ((SAFI_MPLS_VPN == safi)
4429 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4430
40381db7 4431 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4432 }
4433 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4434 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4435 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4436 sizeof(pfx_buf));
4437 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4438 }
718e3744 4439
d62a17ae 4440 /* Unlock bgp_node_get() lock. */
9bcb3eef 4441 bgp_dest_unlock_node(dest);
d62a17ae 4442
4443 return 0;
718e3744 4444}
6b0655a2 4445
d62a17ae 4446void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4447 int withdraw)
718e3744 4448{
d62a17ae 4449 struct update_subgroup *subgrp;
4450 subgrp = peer_subgroup(peer, afi, safi);
4451 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4452}
6182d65b 4453
718e3744 4454
3f9c7369
DS
4455/*
4456 * bgp_stop_announce_route_timer
4457 */
d62a17ae 4458void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4459{
d62a17ae 4460 if (!paf->t_announce_route)
4461 return;
4462
50478845 4463 thread_cancel(&paf->t_announce_route);
718e3744 4464}
6b0655a2 4465
3f9c7369
DS
4466/*
4467 * bgp_announce_route_timer_expired
4468 *
4469 * Callback that is invoked when the route announcement timer for a
4470 * peer_af expires.
4471 */
d62a17ae 4472static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4473{
d62a17ae 4474 struct peer_af *paf;
4475 struct peer *peer;
558d1fec 4476
d62a17ae 4477 paf = THREAD_ARG(t);
4478 peer = paf->peer;
718e3744 4479
d62a17ae 4480 if (peer->status != Established)
4481 return 0;
3f9c7369 4482
d62a17ae 4483 if (!peer->afc_nego[paf->afi][paf->safi])
4484 return 0;
3f9c7369 4485
d62a17ae 4486 peer_af_announce_route(paf, 1);
c5aec50b
MK
4487
4488 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4489 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4490
d62a17ae 4491 return 0;
718e3744 4492}
4493
3f9c7369
DS
4494/*
4495 * bgp_announce_route
4496 *
4497 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4498 */
d62a17ae 4499void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4500{
4501 struct peer_af *paf;
4502 struct update_subgroup *subgrp;
4503
4504 paf = peer_af_find(peer, afi, safi);
4505 if (!paf)
4506 return;
4507 subgrp = PAF_SUBGRP(paf);
4508
4509 /*
4510 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4511 * or a refresh has already been triggered.
4512 */
4513 if (!subgrp || paf->t_announce_route)
4514 return;
4515
4516 /*
4517 * Start a timer to stagger/delay the announce. This serves
4518 * two purposes - announcement can potentially be combined for
4519 * multiple peers and the announcement doesn't happen in the
4520 * vty context.
4521 */
4522 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4523 (subgrp->peer_count == 1)
4524 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4525 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4526 &paf->t_announce_route);
3f9c7369
DS
4527}
4528
4529/*
4530 * Announce routes from all AF tables to a peer.
4531 *
4532 * This should ONLY be called when there is a need to refresh the
4533 * routes to the peer based on a policy change for this peer alone
4534 * or a route refresh request received from the peer.
4535 * The operation will result in splitting the peer from its existing
4536 * subgroups and putting it in new subgroups.
4537 */
d62a17ae 4538void bgp_announce_route_all(struct peer *peer)
718e3744 4539{
d62a17ae 4540 afi_t afi;
4541 safi_t safi;
4542
05c7a1cc
QY
4543 FOREACH_AFI_SAFI (afi, safi)
4544 bgp_announce_route(peer, afi, safi);
718e3744 4545}
6b0655a2 4546
d62a17ae 4547static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4548 struct bgp_table *table,
4549 struct prefix_rd *prd)
718e3744 4550{
d62a17ae 4551 int ret;
9bcb3eef 4552 struct bgp_dest *dest;
d62a17ae 4553 struct bgp_adj_in *ain;
718e3744 4554
d62a17ae 4555 if (!table)
4556 table = peer->bgp->rib[afi][safi];
718e3744 4557
9bcb3eef
DS
4558 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4559 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4560 if (ain->peer != peer)
4561 continue;
8692c506 4562
d7d15889 4563 struct bgp_path_info *pi;
d7c0a89a 4564 uint32_t num_labels = 0;
b57ba6d2 4565 mpls_label_t *label_pnt = NULL;
8cb687c2 4566 struct bgp_route_evpn evpn;
b57ba6d2 4567
9bcb3eef 4568 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4569 pi = pi->next)
4570 if (pi->peer == peer)
4571 break;
4572
40381db7
DS
4573 if (pi && pi->extra)
4574 num_labels = pi->extra->num_labels;
b57ba6d2 4575 if (num_labels)
40381db7 4576 label_pnt = &pi->extra->label[0];
8cb687c2 4577 if (pi)
6c924775
DS
4578 memcpy(&evpn,
4579 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4580 sizeof(evpn));
4581 else
4582 memset(&evpn, 0, sizeof(evpn));
8692c506 4583
9bcb3eef
DS
4584 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4585 ain->addpath_rx_id, ain->attr, afi,
4586 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4587 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4588 num_labels, 1, &evpn);
ea47320b
DL
4589
4590 if (ret < 0) {
9bcb3eef 4591 bgp_dest_unlock_node(dest);
ea47320b 4592 return;
d62a17ae 4593 }
4594 }
718e3744 4595}
4596
d62a17ae 4597void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4598{
9bcb3eef 4599 struct bgp_dest *dest;
d62a17ae 4600 struct bgp_table *table;
718e3744 4601
d62a17ae 4602 if (peer->status != Established)
4603 return;
718e3744 4604
d62a17ae 4605 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4606 && (safi != SAFI_EVPN))
4607 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4608 else
9bcb3eef
DS
4609 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4610 dest = bgp_route_next(dest)) {
4611 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4612
b54892e0
DS
4613 if (table == NULL)
4614 continue;
8692c506 4615
9bcb3eef 4616 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4617 struct prefix_rd prd;
4618
4619 prd.family = AF_UNSPEC;
4620 prd.prefixlen = 64;
4621 memcpy(&prd.val, p->u.val, 8);
4622
4623 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4624 }
718e3744 4625}
6b0655a2 4626
228da428 4627
d62a17ae 4628struct bgp_clear_node_queue {
9bcb3eef 4629 struct bgp_dest *dest;
228da428
CC
4630};
4631
d62a17ae 4632static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4633{
d62a17ae 4634 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4635 struct bgp_dest *dest = cnq->dest;
d62a17ae 4636 struct peer *peer = wq->spec.data;
40381db7 4637 struct bgp_path_info *pi;
3103e8d2 4638 struct bgp *bgp;
9bcb3eef
DS
4639 afi_t afi = bgp_dest_table(dest)->afi;
4640 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4641
9bcb3eef 4642 assert(dest && peer);
3103e8d2 4643 bgp = peer->bgp;
d62a17ae 4644
4645 /* It is possible that we have multiple paths for a prefix from a peer
4646 * if that peer is using AddPath.
4647 */
9bcb3eef 4648 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4649 if (pi->peer != peer)
ea47320b
DL
4650 continue;
4651
4652 /* graceful restart STALE flag set. */
9af52ccf
DA
4653 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4654 && peer->nsf[afi][safi])
4655 || CHECK_FLAG(peer->af_sflags[afi][safi],
4656 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4657 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4658 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4659 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4660 else {
4661 /* If this is an EVPN route, process for
4662 * un-import. */
4663 if (safi == SAFI_EVPN)
9bcb3eef
DS
4664 bgp_evpn_unimport_route(
4665 bgp, afi, safi,
4666 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4667 /* Handle withdraw for VRF route-leaking and L3VPN */
4668 if (SAFI_UNICAST == safi
4669 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4670 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4671 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4672 bgp, pi);
960035b2 4673 }
3103e8d2 4674 if (SAFI_MPLS_VPN == safi &&
960035b2 4675 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4676 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4677 }
3103e8d2 4678
9bcb3eef 4679 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4680 }
ea47320b 4681 }
d62a17ae 4682 return WQ_SUCCESS;
200df115 4683}
4684
d62a17ae 4685static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4686{
d62a17ae 4687 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4688 struct bgp_dest *dest = cnq->dest;
4689 struct bgp_table *table = bgp_dest_table(dest);
228da428 4690
9bcb3eef 4691 bgp_dest_unlock_node(dest);
d62a17ae 4692 bgp_table_unlock(table);
4693 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4694}
4695
d62a17ae 4696static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4697{
d62a17ae 4698 struct peer *peer = wq->spec.data;
64e580a7 4699
d62a17ae 4700 /* Tickle FSM to start moving again */
4701 BGP_EVENT_ADD(peer, Clearing_Completed);
4702
4703 peer_unlock(peer); /* bgp_clear_route */
200df115 4704}
718e3744 4705
d62a17ae 4706static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4707{
d62a17ae 4708 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4709
4710 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4711#undef CLEAR_QUEUE_NAME_LEN
4712
0ce1ca80 4713 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4714 peer->clear_node_queue->spec.hold = 10;
4715 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4716 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4717 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4718 peer->clear_node_queue->spec.max_retries = 0;
4719
4720 /* we only 'lock' this peer reference when the queue is actually active
4721 */
4722 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4723}
4724
d62a17ae 4725static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4726 struct bgp_table *table)
65ca75e0 4727{
9bcb3eef 4728 struct bgp_dest *dest;
b6c386bb 4729 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4730
d62a17ae 4731 if (!table)
4732 table = peer->bgp->rib[afi][safi];
dc83d712 4733
d62a17ae 4734 /* If still no table => afi/safi isn't configured at all or smth. */
4735 if (!table)
4736 return;
dc83d712 4737
9bcb3eef 4738 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4739 struct bgp_path_info *pi, *next;
d62a17ae 4740 struct bgp_adj_in *ain;
4741 struct bgp_adj_in *ain_next;
4742
4743 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4744 * queued for every clearing peer, regardless of whether it is
4745 * relevant to the peer at hand.
4746 *
4747 * Overview: There are 3 different indices which need to be
4748 * scrubbed, potentially, when a peer is removed:
4749 *
4750 * 1 peer's routes visible via the RIB (ie accepted routes)
4751 * 2 peer's routes visible by the (optional) peer's adj-in index
4752 * 3 other routes visible by the peer's adj-out index
4753 *
4754 * 3 there is no hurry in scrubbing, once the struct peer is
4755 * removed from bgp->peer, we could just GC such deleted peer's
4756 * adj-outs at our leisure.
4757 *
4758 * 1 and 2 must be 'scrubbed' in some way, at least made
4759 * invisible via RIB index before peer session is allowed to be
4760 * brought back up. So one needs to know when such a 'search' is
4761 * complete.
4762 *
4763 * Ideally:
4764 *
4765 * - there'd be a single global queue or a single RIB walker
4766 * - rather than tracking which route_nodes still need to be
4767 * examined on a peer basis, we'd track which peers still
4768 * aren't cleared
4769 *
4770 * Given that our per-peer prefix-counts now should be reliable,
4771 * this may actually be achievable. It doesn't seem to be a huge
4772 * problem at this time,
4773 *
4774 * It is possible that we have multiple paths for a prefix from
4775 * a peer
4776 * if that peer is using AddPath.
4777 */
9bcb3eef 4778 ain = dest->adj_in;
d62a17ae 4779 while (ain) {
4780 ain_next = ain->next;
4781
4782 if (ain->peer == peer) {
9bcb3eef
DS
4783 bgp_adj_in_remove(dest, ain);
4784 bgp_dest_unlock_node(dest);
d62a17ae 4785 }
4786
4787 ain = ain_next;
4788 }
4789
9bcb3eef 4790 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4791 next = pi->next;
4792 if (pi->peer != peer)
d62a17ae 4793 continue;
4794
4795 if (force)
9bcb3eef 4796 bgp_path_info_reap(dest, pi);
d62a17ae 4797 else {
4798 struct bgp_clear_node_queue *cnq;
4799
4800 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4801 bgp_table_lock(bgp_dest_table(dest));
4802 bgp_dest_lock_node(dest);
d62a17ae 4803 cnq = XCALLOC(
4804 MTYPE_BGP_CLEAR_NODE_QUEUE,
4805 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4806 cnq->dest = dest;
d62a17ae 4807 work_queue_add(peer->clear_node_queue, cnq);
4808 break;
4809 }
4810 }
4811 }
4812 return;
4813}
4814
4815void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4816{
9bcb3eef 4817 struct bgp_dest *dest;
d62a17ae 4818 struct bgp_table *table;
4819
4820 if (peer->clear_node_queue == NULL)
4821 bgp_clear_node_queue_init(peer);
4822
4823 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4824 * Idle until it receives a Clearing_Completed event. This protects
4825 * against peers which flap faster than we can we clear, which could
4826 * lead to:
4827 *
4828 * a) race with routes from the new session being installed before
4829 * clear_route_node visits the node (to delete the route of that
4830 * peer)
4831 * b) resource exhaustion, clear_route_node likely leads to an entry
4832 * on the process_main queue. Fast-flapping could cause that queue
4833 * to grow and grow.
4834 */
4835
4836 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4837 * the unlock will happen upon work-queue completion; other wise, the
4838 * unlock happens at the end of this function.
4839 */
4840 if (!peer->clear_node_queue->thread)
4841 peer_lock(peer);
4842
4843 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4844 bgp_clear_route_table(peer, afi, safi, NULL);
4845 else
9bcb3eef
DS
4846 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4847 dest = bgp_route_next(dest)) {
4848 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4849 if (!table)
4850 continue;
4851
4852 bgp_clear_route_table(peer, afi, safi, table);
4853 }
d62a17ae 4854
4855 /* unlock if no nodes got added to the clear-node-queue. */
4856 if (!peer->clear_node_queue->thread)
4857 peer_unlock(peer);
718e3744 4858}
d62a17ae 4859
4860void bgp_clear_route_all(struct peer *peer)
718e3744 4861{
d62a17ae 4862 afi_t afi;
4863 safi_t safi;
718e3744 4864
05c7a1cc
QY
4865 FOREACH_AFI_SAFI (afi, safi)
4866 bgp_clear_route(peer, afi, safi);
65efcfce 4867
49e5a4a0 4868#ifdef ENABLE_BGP_VNC
d62a17ae 4869 rfapiProcessPeerDown(peer);
65efcfce 4870#endif
718e3744 4871}
4872
d62a17ae 4873void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4874{
d62a17ae 4875 struct bgp_table *table;
9bcb3eef 4876 struct bgp_dest *dest;
d62a17ae 4877 struct bgp_adj_in *ain;
4878 struct bgp_adj_in *ain_next;
718e3744 4879
d62a17ae 4880 table = peer->bgp->rib[afi][safi];
718e3744 4881
d62a17ae 4882 /* It is possible that we have multiple paths for a prefix from a peer
4883 * if that peer is using AddPath.
4884 */
9bcb3eef
DS
4885 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4886 ain = dest->adj_in;
43143c8f 4887
d62a17ae 4888 while (ain) {
4889 ain_next = ain->next;
43143c8f 4890
d62a17ae 4891 if (ain->peer == peer) {
9bcb3eef
DS
4892 bgp_adj_in_remove(dest, ain);
4893 bgp_dest_unlock_node(dest);
d62a17ae 4894 }
43143c8f 4895
d62a17ae 4896 ain = ain_next;
4897 }
4898 }
718e3744 4899}
93406d87 4900
d62a17ae 4901void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4902{
9bcb3eef 4903 struct bgp_dest *dest;
40381db7 4904 struct bgp_path_info *pi;
d62a17ae 4905 struct bgp_table *table;
4906
9af52ccf 4907 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
4908 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4909 dest = bgp_route_next(dest)) {
4910 struct bgp_dest *rm;
d62a17ae 4911
4912 /* look for neighbor in tables */
9bcb3eef 4913 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4914 if (!table)
ea47320b
DL
4915 continue;
4916
4917 for (rm = bgp_table_top(table); rm;
4918 rm = bgp_route_next(rm))
9bcb3eef 4919 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4920 pi = pi->next) {
40381db7 4921 if (pi->peer != peer)
ea47320b 4922 continue;
40381db7 4923 if (!CHECK_FLAG(pi->flags,
1defdda8 4924 BGP_PATH_STALE))
ea47320b
DL
4925 break;
4926
40381db7 4927 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4928 break;
4929 }
d62a17ae 4930 }
4931 } else {
9bcb3eef
DS
4932 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4933 dest = bgp_route_next(dest))
4934 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4935 pi = pi->next) {
40381db7 4936 if (pi->peer != peer)
ea47320b 4937 continue;
40381db7 4938 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4939 break;
9bcb3eef 4940 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4941 break;
4942 }
d62a17ae 4943 }
93406d87 4944}
6b0655a2 4945
9af52ccf
DA
4946void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4947{
4948 struct bgp_dest *dest, *ndest;
4949 struct bgp_path_info *pi;
4950 struct bgp_table *table;
4951
4952 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4953 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4954 dest = bgp_route_next(dest)) {
4955 table = bgp_dest_get_bgp_table_info(dest);
4956 if (!table)
4957 continue;
4958
4959 for (ndest = bgp_table_top(table); ndest;
4960 ndest = bgp_route_next(ndest)) {
4961 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
4962 pi = pi->next) {
4963 if (pi->peer != peer)
4964 continue;
4965
4966 if ((CHECK_FLAG(
4967 peer->af_sflags[afi][safi],
4968 PEER_STATUS_ENHANCED_REFRESH))
4969 && !CHECK_FLAG(pi->flags,
4970 BGP_PATH_STALE)
4971 && !CHECK_FLAG(
4972 pi->flags,
4973 BGP_PATH_UNUSEABLE)) {
4974 if (bgp_debug_neighbor_events(
4975 peer))
4976 zlog_debug(
4977 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4978 peer->host,
4979 afi2str(afi),
4980 safi2str(safi),
4981 bgp_dest_get_prefix(
4982 ndest));
4983
4984 bgp_path_info_set_flag(
4985 ndest, pi,
4986 BGP_PATH_STALE);
4987 }
4988 }
4989 }
4990 }
4991 } else {
4992 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4993 dest = bgp_route_next(dest)) {
4994 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4995 pi = pi->next) {
4996 if (pi->peer != peer)
4997 continue;
4998
4999 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5000 PEER_STATUS_ENHANCED_REFRESH))
5001 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5002 && !CHECK_FLAG(pi->flags,
5003 BGP_PATH_UNUSEABLE)) {
5004 if (bgp_debug_neighbor_events(peer))
5005 zlog_debug(
5006 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5007 peer->host,
5008 afi2str(afi),
5009 safi2str(safi),
5010 bgp_dest_get_prefix(
5011 dest));
5012
5013 bgp_path_info_set_flag(dest, pi,
5014 BGP_PATH_STALE);
5015 }
5016 }
5017 }
5018 }
5019}
5020
3dc339cd 5021bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5022{
e0df4c04 5023 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5024 return true;
e0df4c04 5025
9dac9fc8
DA
5026 if (peer->sort == BGP_PEER_EBGP
5027 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5028 || FILTER_LIST_OUT_NAME(filter)
5029 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5030 return true;
5031 return false;
9dac9fc8
DA
5032}
5033
3dc339cd 5034bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5035{
e0df4c04 5036 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5037 return true;
e0df4c04 5038
9dac9fc8
DA
5039 if (peer->sort == BGP_PEER_EBGP
5040 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5041 || FILTER_LIST_IN_NAME(filter)
5042 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5043 return true;
5044 return false;
9dac9fc8
DA
5045}
5046
568e10ca 5047static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5048 safi_t safi)
bb86c601 5049{
9bcb3eef 5050 struct bgp_dest *dest;
40381db7 5051 struct bgp_path_info *pi;
4b7e6066 5052 struct bgp_path_info *next;
bb86c601 5053
9bcb3eef
DS
5054 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5055 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5056 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5057
40381db7 5058 next = pi->next;
1b7bb747
CS
5059
5060 /* Unimport EVPN routes from VRFs */
5061 if (safi == SAFI_EVPN)
5062 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5063 SAFI_EVPN, p, pi);
1b7bb747 5064
40381db7
DS
5065 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5066 && pi->type == ZEBRA_ROUTE_BGP
5067 && (pi->sub_type == BGP_ROUTE_NORMAL
5068 || pi->sub_type == BGP_ROUTE_AGGREGATE
5069 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5070
d62a17ae 5071 if (bgp_fibupd_safi(safi))
b54892e0 5072 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5073 }
9514b37d 5074
9bcb3eef 5075 bgp_path_info_reap(dest, pi);
d62a17ae 5076 }
bb86c601
LB
5077}
5078
718e3744 5079/* Delete all kernel routes. */
d62a17ae 5080void bgp_cleanup_routes(struct bgp *bgp)
5081{
5082 afi_t afi;
9bcb3eef 5083 struct bgp_dest *dest;
67009e22 5084 struct bgp_table *table;
d62a17ae 5085
5086 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5087 if (afi == AFI_L2VPN)
5088 continue;
568e10ca 5089 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5090 SAFI_UNICAST);
d62a17ae 5091 /*
5092 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5093 */
5094 if (afi != AFI_L2VPN) {
5095 safi_t safi;
5096 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5097 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5098 dest = bgp_route_next(dest)) {
5099 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5100 if (table != NULL) {
5101 bgp_cleanup_table(bgp, table, safi);
5102 bgp_table_finish(&table);
9bcb3eef
DS
5103 bgp_dest_set_bgp_table_info(dest, NULL);
5104 bgp_dest_unlock_node(dest);
d62a17ae 5105 }
5106 }
5107 safi = SAFI_ENCAP;
9bcb3eef
DS
5108 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5109 dest = bgp_route_next(dest)) {
5110 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5111 if (table != NULL) {
5112 bgp_cleanup_table(bgp, table, safi);
5113 bgp_table_finish(&table);
9bcb3eef
DS
5114 bgp_dest_set_bgp_table_info(dest, NULL);
5115 bgp_dest_unlock_node(dest);
d62a17ae 5116 }
5117 }
5118 }
5119 }
9bcb3eef
DS
5120 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5121 dest = bgp_route_next(dest)) {
5122 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5123 if (table != NULL) {
5124 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5125 bgp_table_finish(&table);
9bcb3eef
DS
5126 bgp_dest_set_bgp_table_info(dest, NULL);
5127 bgp_dest_unlock_node(dest);
d62a17ae 5128 }
bb86c601 5129 }
718e3744 5130}
5131
d62a17ae 5132void bgp_reset(void)
718e3744 5133{
d62a17ae 5134 vty_reset();
5135 bgp_zclient_reset();
5136 access_list_reset();
5137 prefix_list_reset();
718e3744 5138}
6b0655a2 5139
d62a17ae 5140static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5141{
d62a17ae 5142 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5143 && CHECK_FLAG(peer->af_cap[afi][safi],
5144 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5145}
5146
718e3744 5147/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5148 value. */
d62a17ae 5149int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5150 struct bgp_nlri *packet)
5151{
d7c0a89a
QY
5152 uint8_t *pnt;
5153 uint8_t *lim;
d62a17ae 5154 struct prefix p;
5155 int psize;
5156 int ret;
5157 afi_t afi;
5158 safi_t safi;
5159 int addpath_encoded;
d7c0a89a 5160 uint32_t addpath_id;
d62a17ae 5161
d62a17ae 5162 pnt = packet->nlri;
5163 lim = pnt + packet->length;
5164 afi = packet->afi;
5165 safi = packet->safi;
5166 addpath_id = 0;
5167 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5168
5169 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5170 syntactic validity. If the field is syntactically incorrect,
5171 then the Error Subcode is set to Invalid Network Field. */
5172 for (; pnt < lim; pnt += psize) {
5173 /* Clear prefix structure. */
5174 memset(&p, 0, sizeof(struct prefix));
5175
5176 if (addpath_encoded) {
5177
5178 /* When packet overflow occurs return immediately. */
761ed665 5179 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5180 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5181
a3a850a1 5182 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5183 addpath_id = ntohl(addpath_id);
d62a17ae 5184 pnt += BGP_ADDPATH_ID_LEN;
5185 }
718e3744 5186
d62a17ae 5187 /* Fetch prefix length. */
5188 p.prefixlen = *pnt++;
5189 /* afi/safi validity already verified by caller,
5190 * bgp_update_receive */
5191 p.family = afi2family(afi);
5192
5193 /* Prefix length check. */
5194 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5195 flog_err(
e50f7cfd 5196 EC_BGP_UPDATE_RCV,
14454c9f 5197 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5198 peer->host, p.prefixlen, packet->afi);
513386b5 5199 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5200 }
6b0655a2 5201
d62a17ae 5202 /* Packet size overflow check. */
5203 psize = PSIZE(p.prefixlen);
5204
5205 /* When packet overflow occur return immediately. */
5206 if (pnt + psize > lim) {
af4c2728 5207 flog_err(
e50f7cfd 5208 EC_BGP_UPDATE_RCV,
d62a17ae 5209 "%s [Error] Update packet error (prefix length %d overflows packet)",
5210 peer->host, p.prefixlen);
513386b5 5211 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5212 }
5213
5214 /* Defensive coding, double-check the psize fits in a struct
5215 * prefix */
5216 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5217 flog_err(
e50f7cfd 5218 EC_BGP_UPDATE_RCV,
d62a17ae 5219 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5220 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5221 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5222 }
5223
5224 /* Fetch prefix from NLRI packet. */
a85297a7 5225 memcpy(p.u.val, pnt, psize);
d62a17ae 5226
5227 /* Check address. */
5228 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5229 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5230 /* From RFC4271 Section 6.3:
5231 *
5232 * If a prefix in the NLRI field is semantically
5233 * incorrect
5234 * (e.g., an unexpected multicast IP address),
5235 * an error SHOULD
5236 * be logged locally, and the prefix SHOULD be
5237 * ignored.
a4d82a8a 5238 */
af4c2728 5239 flog_err(
e50f7cfd 5240 EC_BGP_UPDATE_RCV,
23d0a753
DA
5241 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5242 peer->host, &p.u.prefix4);
d62a17ae 5243 continue;
5244 }
5245 }
5246
5247 /* Check address. */
5248 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5249 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5250 char buf[BUFSIZ];
5251
af4c2728 5252 flog_err(
e50f7cfd 5253 EC_BGP_UPDATE_RCV,
d62a17ae 5254 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5255 peer->host,
5256 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5257 BUFSIZ));
5258
5259 continue;
5260 }
5261 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5262 char buf[BUFSIZ];
5263
af4c2728 5264 flog_err(
e50f7cfd 5265 EC_BGP_UPDATE_RCV,
d62a17ae 5266 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5267 peer->host,
5268 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5269 BUFSIZ));
5270
5271 continue;
5272 }
5273 }
5274
5275 /* Normal process. */
5276 if (attr)
5277 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5278 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5279 NULL, NULL, 0, 0, NULL);
d62a17ae 5280 else
5281 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5282 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5283 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5284 NULL);
d62a17ae 5285
513386b5
DA
5286 /* Do not send BGP notification twice when maximum-prefix count
5287 * overflow. */
5288 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5289 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5290
5291 /* Address family configuration mismatch. */
d62a17ae 5292 if (ret < 0)
513386b5 5293 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5294 }
5295
5296 /* Packet length consistency check. */
5297 if (pnt != lim) {
af4c2728 5298 flog_err(
e50f7cfd 5299 EC_BGP_UPDATE_RCV,
d62a17ae 5300 "%s [Error] Update packet error (prefix length mismatch with total length)",
5301 peer->host);
513386b5 5302 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5303 }
6b0655a2 5304
513386b5 5305 return BGP_NLRI_PARSE_OK;
718e3744 5306}
5307
d62a17ae 5308static struct bgp_static *bgp_static_new(void)
718e3744 5309{
d62a17ae 5310 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5311}
5312
d62a17ae 5313static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5314{
0a22ddfb 5315 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5316 route_map_counter_decrement(bgp_static->rmap.map);
5317
0a22ddfb 5318 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5319 XFREE(MTYPE_BGP_STATIC, bgp_static);
5320}
5321
5f040085 5322void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5323 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5324{
9bcb3eef 5325 struct bgp_dest *dest;
40381db7 5326 struct bgp_path_info *pi;
4b7e6066 5327 struct bgp_path_info *new;
40381db7 5328 struct bgp_path_info rmap_path;
d62a17ae 5329 struct attr attr;
5330 struct attr *attr_new;
b68885f9 5331 route_map_result_t ret;
49e5a4a0 5332#ifdef ENABLE_BGP_VNC
d62a17ae 5333 int vnc_implicit_withdraw = 0;
65efcfce 5334#endif
fee0f4c6 5335
d62a17ae 5336 assert(bgp_static);
dd8103a9 5337
9bcb3eef 5338 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5339
d62a17ae 5340 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5341
d62a17ae 5342 attr.nexthop = bgp_static->igpnexthop;
5343 attr.med = bgp_static->igpmetric;
5344 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5345
d62a17ae 5346 if (bgp_static->atomic)
5347 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5348
d62a17ae 5349 /* Store label index, if required. */
5350 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5351 attr.label_index = bgp_static->label_index;
5352 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5353 }
718e3744 5354
d62a17ae 5355 /* Apply route-map. */
5356 if (bgp_static->rmap.name) {
5357 struct attr attr_tmp = attr;
80ced710 5358
40381db7
DS
5359 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5360 rmap_path.peer = bgp->peer_self;
5361 rmap_path.attr = &attr_tmp;
fee0f4c6 5362
d62a17ae 5363 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5364
1782514f 5365 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5366
d62a17ae 5367 bgp->peer_self->rmap_type = 0;
718e3744 5368
d62a17ae 5369 if (ret == RMAP_DENYMATCH) {
5370 /* Free uninterned attribute. */
5371 bgp_attr_flush(&attr_tmp);
718e3744 5372
d62a17ae 5373 /* Unintern original. */
5374 aspath_unintern(&attr.aspath);
5375 bgp_static_withdraw(bgp, p, afi, safi);
5376 return;
5377 }
7f323236 5378
637e5ba4 5379 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5380 bgp_attr_add_gshut_community(&attr_tmp);
5381
d62a17ae 5382 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5383 } else {
5384
637e5ba4 5385 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5386 bgp_attr_add_gshut_community(&attr);
5387
d62a17ae 5388 attr_new = bgp_attr_intern(&attr);
7f323236 5389 }
718e3744 5390
9bcb3eef 5391 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5392 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5393 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5394 break;
5395
40381db7
DS
5396 if (pi) {
5397 if (attrhash_cmp(pi->attr, attr_new)
5398 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5399 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5400 bgp_dest_unlock_node(dest);
d62a17ae 5401 bgp_attr_unintern(&attr_new);
5402 aspath_unintern(&attr.aspath);
5403 return;
5404 } else {
5405 /* The attribute is changed. */
9bcb3eef 5406 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5407
5408 /* Rewrite BGP route information. */
40381db7 5409 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5410 bgp_path_info_restore(dest, pi);
d62a17ae 5411 else
40381db7 5412 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5413#ifdef ENABLE_BGP_VNC
d62a17ae 5414 if ((afi == AFI_IP || afi == AFI_IP6)
5415 && (safi == SAFI_UNICAST)) {
40381db7 5416 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5417 /*
5418 * Implicit withdraw case.
40381db7 5419 * We have to do this before pi is
d62a17ae 5420 * changed
5421 */
5422 ++vnc_implicit_withdraw;
40381db7 5423 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5424 vnc_import_bgp_exterior_del_route(
40381db7 5425 bgp, p, pi);
d62a17ae 5426 }
5427 }
65efcfce 5428#endif
40381db7
DS
5429 bgp_attr_unintern(&pi->attr);
5430 pi->attr = attr_new;
5431 pi->uptime = bgp_clock();
49e5a4a0 5432#ifdef ENABLE_BGP_VNC
d62a17ae 5433 if ((afi == AFI_IP || afi == AFI_IP6)
5434 && (safi == SAFI_UNICAST)) {
5435 if (vnc_implicit_withdraw) {
40381db7 5436 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5437 vnc_import_bgp_exterior_add_route(
40381db7 5438 bgp, p, pi);
d62a17ae 5439 }
5440 }
65efcfce 5441#endif
718e3744 5442
d62a17ae 5443 /* Nexthop reachability check. */
892fedb6 5444 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5445 && (safi == SAFI_UNICAST
5446 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5447
5448 struct bgp *bgp_nexthop = bgp;
5449
40381db7
DS
5450 if (pi->extra && pi->extra->bgp_orig)
5451 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5452
5453 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952
PR
5454 afi, safi, pi, NULL,
5455 0))
9bcb3eef 5456 bgp_path_info_set_flag(dest, pi,
18ee8310 5457 BGP_PATH_VALID);
d62a17ae 5458 else {
5459 if (BGP_DEBUG(nht, NHT)) {
5460 char buf1[INET6_ADDRSTRLEN];
5461 inet_ntop(p->family,
5462 &p->u.prefix, buf1,
5463 INET6_ADDRSTRLEN);
5464 zlog_debug(
5465 "%s(%s): Route not in table, not advertising",
15569c58 5466 __func__, buf1);
d62a17ae 5467 }
18ee8310 5468 bgp_path_info_unset_flag(
9bcb3eef 5469 dest, pi, BGP_PATH_VALID);
d62a17ae 5470 }
5471 } else {
5472 /* Delete the NHT structure if any, if we're
5473 * toggling between
5474 * enabling/disabling import check. We
5475 * deregister the route
5476 * from NHT to avoid overloading NHT and the
5477 * process interaction
5478 */
40381db7 5479 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5480 bgp_path_info_set_flag(dest, pi,
5481 BGP_PATH_VALID);
d62a17ae 5482 }
5483 /* Process change. */
40381db7 5484 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5485 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5486
5487 if (SAFI_UNICAST == safi
5488 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5489 || bgp->inst_type
5490 == BGP_INSTANCE_TYPE_DEFAULT)) {
5491 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5492 pi);
ddb5b488
PZ
5493 }
5494
9bcb3eef 5495 bgp_dest_unlock_node(dest);
d62a17ae 5496 aspath_unintern(&attr.aspath);
5497 return;
5498 }
718e3744 5499 }
718e3744 5500
d62a17ae 5501 /* Make new BGP info. */
5502 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5503 attr_new, dest);
d62a17ae 5504 /* Nexthop reachability check. */
892fedb6 5505 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5506 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
4053e952 5507 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
9bcb3eef 5508 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5509 else {
5510 if (BGP_DEBUG(nht, NHT)) {
5511 char buf1[INET6_ADDRSTRLEN];
5512 inet_ntop(p->family, &p->u.prefix, buf1,
5513 INET6_ADDRSTRLEN);
5514 zlog_debug(
5515 "%s(%s): Route not in table, not advertising",
15569c58 5516 __func__, buf1);
d62a17ae 5517 }
9bcb3eef 5518 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5519 }
5520 } else {
5521 /* Delete the NHT structure if any, if we're toggling between
5522 * enabling/disabling import check. We deregister the route
5523 * from NHT to avoid overloading NHT and the process interaction
5524 */
5525 bgp_unlink_nexthop(new);
5526
9bcb3eef 5527 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5528 }
078430f6 5529
d62a17ae 5530 /* Aggregate address increment. */
5531 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5532
d62a17ae 5533 /* Register new BGP information. */
9bcb3eef 5534 bgp_path_info_add(dest, new);
718e3744 5535
d62a17ae 5536 /* route_node_get lock */
9bcb3eef 5537 bgp_dest_unlock_node(dest);
d62a17ae 5538
5539 /* Process change. */
9bcb3eef 5540 bgp_process(bgp, dest, afi, safi);
d62a17ae 5541
ddb5b488
PZ
5542 if (SAFI_UNICAST == safi
5543 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5544 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5545 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5546 }
5547
d62a17ae 5548 /* Unintern original. */
5549 aspath_unintern(&attr.aspath);
718e3744 5550}
5551
5f040085 5552void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5553 safi_t safi)
718e3744 5554{
9bcb3eef 5555 struct bgp_dest *dest;
40381db7 5556 struct bgp_path_info *pi;
718e3744 5557
9bcb3eef 5558 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5559
d62a17ae 5560 /* Check selected route and self inserted route. */
9bcb3eef 5561 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5562 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5563 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5564 break;
5565
5566 /* Withdraw static BGP route from routing table. */
40381db7 5567 if (pi) {
ddb5b488
PZ
5568 if (SAFI_UNICAST == safi
5569 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5570 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5571 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5572 }
40381db7
DS
5573 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5574 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5575 bgp_path_info_delete(dest, pi);
5576 bgp_process(bgp, dest, afi, safi);
d62a17ae 5577 }
718e3744 5578
d62a17ae 5579 /* Unlock bgp_node_lookup. */
9bcb3eef 5580 bgp_dest_unlock_node(dest);
718e3744 5581}
5582
137446f9
LB
5583/*
5584 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5585 */
5f040085 5586static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5587 afi_t afi, safi_t safi,
5588 struct prefix_rd *prd)
718e3744 5589{
9bcb3eef 5590 struct bgp_dest *dest;
40381db7 5591 struct bgp_path_info *pi;
718e3744 5592
9bcb3eef 5593 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5594
d62a17ae 5595 /* Check selected route and self inserted route. */
9bcb3eef 5596 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5597 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5598 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5599 break;
718e3744 5600
d62a17ae 5601 /* Withdraw static BGP route from routing table. */
40381db7 5602 if (pi) {
49e5a4a0 5603#ifdef ENABLE_BGP_VNC
d62a17ae 5604 rfapiProcessWithdraw(
40381db7 5605 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5606 1); /* Kill, since it is an administrative change */
65efcfce 5607#endif
ddb5b488
PZ
5608 if (SAFI_MPLS_VPN == safi
5609 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5610 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5611 }
40381db7 5612 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5613 bgp_path_info_delete(dest, pi);
5614 bgp_process(bgp, dest, afi, safi);
d62a17ae 5615 }
718e3744 5616
d62a17ae 5617 /* Unlock bgp_node_lookup. */
9bcb3eef 5618 bgp_dest_unlock_node(dest);
718e3744 5619}
5620
5f040085 5621static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5622 struct bgp_static *bgp_static, afi_t afi,
5623 safi_t safi)
137446f9 5624{
9bcb3eef 5625 struct bgp_dest *dest;
4b7e6066 5626 struct bgp_path_info *new;
d62a17ae 5627 struct attr *attr_new;
5628 struct attr attr = {0};
40381db7 5629 struct bgp_path_info *pi;
49e5a4a0 5630#ifdef ENABLE_BGP_VNC
d62a17ae 5631 mpls_label_t label = 0;
65efcfce 5632#endif
d7c0a89a 5633 uint32_t num_labels = 0;
d62a17ae 5634 union gw_addr add;
137446f9 5635
d62a17ae 5636 assert(bgp_static);
137446f9 5637
b57ba6d2
MK
5638 if (bgp_static->label != MPLS_INVALID_LABEL)
5639 num_labels = 1;
9bcb3eef
DS
5640 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5641 &bgp_static->prd);
137446f9 5642
d62a17ae 5643 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5644
d62a17ae 5645 attr.nexthop = bgp_static->igpnexthop;
5646 attr.med = bgp_static->igpmetric;
5647 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5648
d62a17ae 5649 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5650 || (safi == SAFI_ENCAP)) {
5651 if (afi == AFI_IP) {
5652 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5653 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5654 }
5655 }
5656 if (afi == AFI_L2VPN) {
5657 if (bgp_static->gatewayIp.family == AF_INET)
5658 add.ipv4.s_addr =
5659 bgp_static->gatewayIp.u.prefix4.s_addr;
5660 else if (bgp_static->gatewayIp.family == AF_INET6)
5661 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5662 sizeof(struct in6_addr));
0a50c248 5663 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5664 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5665 struct bgp_encap_type_vxlan bet;
5666 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5667 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5668 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5669 }
5670 if (bgp_static->router_mac) {
5671 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5672 }
5673 }
5674 /* Apply route-map. */
5675 if (bgp_static->rmap.name) {
5676 struct attr attr_tmp = attr;
40381db7 5677 struct bgp_path_info rmap_path;
b68885f9 5678 route_map_result_t ret;
137446f9 5679
40381db7
DS
5680 rmap_path.peer = bgp->peer_self;
5681 rmap_path.attr = &attr_tmp;
137446f9 5682
d62a17ae 5683 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5684
1782514f 5685 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5686
d62a17ae 5687 bgp->peer_self->rmap_type = 0;
137446f9 5688
d62a17ae 5689 if (ret == RMAP_DENYMATCH) {
5690 /* Free uninterned attribute. */
5691 bgp_attr_flush(&attr_tmp);
137446f9 5692
d62a17ae 5693 /* Unintern original. */
5694 aspath_unintern(&attr.aspath);
5695 bgp_static_withdraw_safi(bgp, p, afi, safi,
5696 &bgp_static->prd);
5697 return;
5698 }
137446f9 5699
d62a17ae 5700 attr_new = bgp_attr_intern(&attr_tmp);
5701 } else {
5702 attr_new = bgp_attr_intern(&attr);
5703 }
137446f9 5704
9bcb3eef 5705 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5706 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5707 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5708 break;
5709
40381db7 5710 if (pi) {
d62a17ae 5711 memset(&add, 0, sizeof(union gw_addr));
40381db7 5712 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5713 && overlay_index_equal(afi, pi, &add)
40381db7 5714 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5715 bgp_dest_unlock_node(dest);
d62a17ae 5716 bgp_attr_unintern(&attr_new);
5717 aspath_unintern(&attr.aspath);
5718 return;
5719 } else {
5720 /* The attribute is changed. */
9bcb3eef 5721 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5722
5723 /* Rewrite BGP route information. */
40381db7 5724 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5725 bgp_path_info_restore(dest, pi);
d62a17ae 5726 else
40381db7
DS
5727 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5728 bgp_attr_unintern(&pi->attr);
5729 pi->attr = attr_new;
5730 pi->uptime = bgp_clock();
49e5a4a0 5731#ifdef ENABLE_BGP_VNC
40381db7
DS
5732 if (pi->extra)
5733 label = decode_label(&pi->extra->label[0]);
65efcfce 5734#endif
137446f9 5735
d62a17ae 5736 /* Process change. */
40381db7 5737 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5738 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5739
5740 if (SAFI_MPLS_VPN == safi
5741 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5742 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5743 }
49e5a4a0 5744#ifdef ENABLE_BGP_VNC
40381db7
DS
5745 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5746 pi->attr, afi, safi, pi->type,
5747 pi->sub_type, &label);
65efcfce 5748#endif
9bcb3eef 5749 bgp_dest_unlock_node(dest);
d62a17ae 5750 aspath_unintern(&attr.aspath);
5751 return;
5752 }
5753 }
137446f9
LB
5754
5755
d62a17ae 5756 /* Make new BGP info. */
5757 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5758 attr_new, dest);
1defdda8 5759 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5760 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5761 if (num_labels) {
5762 new->extra->label[0] = bgp_static->label;
5763 new->extra->num_labels = num_labels;
5764 }
49e5a4a0 5765#ifdef ENABLE_BGP_VNC
d62a17ae 5766 label = decode_label(&bgp_static->label);
65efcfce 5767#endif
137446f9 5768
d62a17ae 5769 /* Aggregate address increment. */
5770 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5771
d62a17ae 5772 /* Register new BGP information. */
9bcb3eef 5773 bgp_path_info_add(dest, new);
d62a17ae 5774 /* route_node_get lock */
9bcb3eef 5775 bgp_dest_unlock_node(dest);
137446f9 5776
d62a17ae 5777 /* Process change. */
9bcb3eef 5778 bgp_process(bgp, dest, afi, safi);
137446f9 5779
ddb5b488
PZ
5780 if (SAFI_MPLS_VPN == safi
5781 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5782 vpn_leak_to_vrf_update(bgp, new);
5783 }
49e5a4a0 5784#ifdef ENABLE_BGP_VNC
d62a17ae 5785 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5786 safi, new->type, new->sub_type, &label);
65efcfce
LB
5787#endif
5788
d62a17ae 5789 /* Unintern original. */
5790 aspath_unintern(&attr.aspath);
137446f9
LB
5791}
5792
718e3744 5793/* Configure static BGP network. When user don't run zebra, static
5794 route should be installed as valid. */
37a87b8f
CS
5795int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5796 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5797 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5798{
d62a17ae 5799 struct prefix p;
5800 struct bgp_static *bgp_static;
9bcb3eef 5801 struct bgp_dest *dest;
d7c0a89a 5802 uint8_t need_update = 0;
d62a17ae 5803
37a87b8f 5804 prefix_copy(&p, pfx);
d62a17ae 5805 apply_mask(&p);
718e3744 5806
e2a86ad9 5807 if (negate) {
718e3744 5808
e2a86ad9 5809 /* Set BGP static route configuration. */
9bcb3eef 5810 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5811
9bcb3eef 5812 if (!dest) {
37a87b8f
CS
5813 snprintf(errmsg, errmsg_len,
5814 "Can't find static route specified\n");
5815 return -1;
d62a17ae 5816 }
5817
9bcb3eef 5818 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5819
e2a86ad9
DS
5820 if ((label_index != BGP_INVALID_LABEL_INDEX)
5821 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5822 snprintf(errmsg, errmsg_len,
5823 "label-index doesn't match static route\n");
5824 return -1;
d62a17ae 5825 }
d62a17ae 5826
e2a86ad9
DS
5827 if ((rmap && bgp_static->rmap.name)
5828 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5829 snprintf(errmsg, errmsg_len,
5830 "route-map name doesn't match static route\n");
5831 return -1;
d62a17ae 5832 }
718e3744 5833
e2a86ad9
DS
5834 /* Update BGP RIB. */
5835 if (!bgp_static->backdoor)
5836 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5837
e2a86ad9
DS
5838 /* Clear configuration. */
5839 bgp_static_free(bgp_static);
9bcb3eef
DS
5840 bgp_dest_set_bgp_static_info(dest, NULL);
5841 bgp_dest_unlock_node(dest);
5842 bgp_dest_unlock_node(dest);
e2a86ad9 5843 } else {
718e3744 5844
e2a86ad9 5845 /* Set BGP static route configuration. */
9bcb3eef
DS
5846 dest = bgp_node_get(bgp->route[afi][safi], &p);
5847 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5848 if (bgp_static) {
e2a86ad9 5849 /* Configuration change. */
e2a86ad9
DS
5850 /* Label index cannot be changed. */
5851 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5852 snprintf(errmsg, errmsg_len,
5853 "cannot change label-index\n");
5854 return -1;
e2a86ad9 5855 }
d62a17ae 5856
e2a86ad9 5857 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5858 if (bgp_static->valid
5859 && bgp_static->backdoor != backdoor)
e2a86ad9 5860 need_update = 1;
718e3744 5861
e2a86ad9 5862 bgp_static->backdoor = backdoor;
718e3744 5863
e2a86ad9 5864 if (rmap) {
0a22ddfb
QY
5865 XFREE(MTYPE_ROUTE_MAP_NAME,
5866 bgp_static->rmap.name);
b4897fa5 5867 route_map_counter_decrement(
5868 bgp_static->rmap.map);
e2a86ad9
DS
5869 bgp_static->rmap.name =
5870 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5871 bgp_static->rmap.map =
5872 route_map_lookup_by_name(rmap);
b4897fa5 5873 route_map_counter_increment(
5874 bgp_static->rmap.map);
e2a86ad9 5875 } else {
0a22ddfb
QY
5876 XFREE(MTYPE_ROUTE_MAP_NAME,
5877 bgp_static->rmap.name);
b4897fa5 5878 route_map_counter_decrement(
5879 bgp_static->rmap.map);
e2a86ad9
DS
5880 bgp_static->rmap.map = NULL;
5881 bgp_static->valid = 0;
5882 }
9bcb3eef 5883 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5884 } else {
5885 /* New configuration. */
5886 bgp_static = bgp_static_new();
5887 bgp_static->backdoor = backdoor;
5888 bgp_static->valid = 0;
5889 bgp_static->igpmetric = 0;
975a328e 5890 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5891 bgp_static->label_index = label_index;
718e3744 5892
e2a86ad9 5893 if (rmap) {
0a22ddfb
QY
5894 XFREE(MTYPE_ROUTE_MAP_NAME,
5895 bgp_static->rmap.name);
b4897fa5 5896 route_map_counter_decrement(
5897 bgp_static->rmap.map);
e2a86ad9
DS
5898 bgp_static->rmap.name =
5899 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5900 bgp_static->rmap.map =
5901 route_map_lookup_by_name(rmap);
b4897fa5 5902 route_map_counter_increment(
5903 bgp_static->rmap.map);
e2a86ad9 5904 }
9bcb3eef 5905 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5906 }
d62a17ae 5907
e2a86ad9
DS
5908 bgp_static->valid = 1;
5909 if (need_update)
5910 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5911
e2a86ad9
DS
5912 if (!bgp_static->backdoor)
5913 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5914 }
d62a17ae 5915
37a87b8f 5916 return 0;
d62a17ae 5917}
5918
5919void bgp_static_add(struct bgp *bgp)
5920{
5921 afi_t afi;
5922 safi_t safi;
9bcb3eef
DS
5923 struct bgp_dest *dest;
5924 struct bgp_dest *rm;
d62a17ae 5925 struct bgp_table *table;
5926 struct bgp_static *bgp_static;
5927
05c7a1cc 5928 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5929 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5930 dest = bgp_route_next(dest)) {
5931 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5932 continue;
ea47320b 5933
05c7a1cc
QY
5934 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5935 || (safi == SAFI_EVPN)) {
9bcb3eef 5936 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5937
5938 for (rm = bgp_table_top(table); rm;
5939 rm = bgp_route_next(rm)) {
a78beeb5 5940 bgp_static =
9bcb3eef 5941 bgp_dest_get_bgp_static_info(
5a8ba9fc 5942 rm);
9bcb3eef
DS
5943 bgp_static_update_safi(
5944 bgp, bgp_dest_get_prefix(rm),
5945 bgp_static, afi, safi);
d62a17ae 5946 }
05c7a1cc 5947 } else {
5a8ba9fc 5948 bgp_static_update(
9bcb3eef
DS
5949 bgp, bgp_dest_get_prefix(dest),
5950 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5951 safi);
ea47320b 5952 }
05c7a1cc 5953 }
6aeb9e78
DS
5954}
5955
718e3744 5956/* Called from bgp_delete(). Delete all static routes from the BGP
5957 instance. */
d62a17ae 5958void bgp_static_delete(struct bgp *bgp)
5959{
5960 afi_t afi;
5961 safi_t safi;
9bcb3eef
DS
5962 struct bgp_dest *dest;
5963 struct bgp_dest *rm;
d62a17ae 5964 struct bgp_table *table;
5965 struct bgp_static *bgp_static;
5966
05c7a1cc 5967 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5968 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5969 dest = bgp_route_next(dest)) {
5970 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5971 continue;
ea47320b 5972
05c7a1cc
QY
5973 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5974 || (safi == SAFI_EVPN)) {
9bcb3eef 5975 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5976
5977 for (rm = bgp_table_top(table); rm;
5978 rm = bgp_route_next(rm)) {
a78beeb5 5979 bgp_static =
9bcb3eef 5980 bgp_dest_get_bgp_static_info(
5a8ba9fc 5981 rm);
c7d14ba6
PG
5982 if (!bgp_static)
5983 continue;
5984
05c7a1cc 5985 bgp_static_withdraw_safi(
9bcb3eef 5986 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5987 AFI_IP, safi,
5988 (struct prefix_rd *)
9bcb3eef
DS
5989 bgp_dest_get_prefix(
5990 dest));
ea47320b 5991 bgp_static_free(bgp_static);
811c6797 5992 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5993 NULL);
811c6797 5994 bgp_dest_unlock_node(rm);
d62a17ae 5995 }
05c7a1cc 5996 } else {
9bcb3eef 5997 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5998 bgp_static_withdraw(bgp,
9bcb3eef 5999 bgp_dest_get_prefix(dest),
b54892e0 6000 afi, safi);
05c7a1cc 6001 bgp_static_free(bgp_static);
9bcb3eef
DS
6002 bgp_dest_set_bgp_static_info(dest, NULL);
6003 bgp_dest_unlock_node(dest);
ea47320b 6004 }
05c7a1cc 6005 }
d62a17ae 6006}
6007
6008void bgp_static_redo_import_check(struct bgp *bgp)
6009{
6010 afi_t afi;
6011 safi_t safi;
9bcb3eef
DS
6012 struct bgp_dest *dest;
6013 struct bgp_dest *rm;
d62a17ae 6014 struct bgp_table *table;
6015 struct bgp_static *bgp_static;
6016
6017 /* Use this flag to force reprocessing of the route */
892fedb6 6018 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6019 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6020 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6021 dest = bgp_route_next(dest)) {
6022 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6023 continue;
ea47320b 6024
05c7a1cc
QY
6025 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6026 || (safi == SAFI_EVPN)) {
9bcb3eef 6027 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6028
6029 for (rm = bgp_table_top(table); rm;
6030 rm = bgp_route_next(rm)) {
a78beeb5 6031 bgp_static =
9bcb3eef 6032 bgp_dest_get_bgp_static_info(
5a8ba9fc 6033 rm);
9bcb3eef
DS
6034 bgp_static_update_safi(
6035 bgp, bgp_dest_get_prefix(rm),
6036 bgp_static, afi, safi);
d62a17ae 6037 }
05c7a1cc 6038 } else {
9bcb3eef
DS
6039 bgp_static = bgp_dest_get_bgp_static_info(dest);
6040 bgp_static_update(bgp,
6041 bgp_dest_get_prefix(dest),
6042 bgp_static, afi, safi);
ea47320b 6043 }
05c7a1cc
QY
6044 }
6045 }
892fedb6 6046 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6047}
6048
6049static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6050 safi_t safi)
6051{
6052 struct bgp_table *table;
9bcb3eef 6053 struct bgp_dest *dest;
40381db7 6054 struct bgp_path_info *pi;
d62a17ae 6055
dfb6fd1d
NT
6056 /* Do not install the aggregate route if BGP is in the
6057 * process of termination.
6058 */
892fedb6
DA
6059 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6060 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6061 return;
6062
d62a17ae 6063 table = bgp->rib[afi][safi];
9bcb3eef
DS
6064 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6065 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6066 if (pi->peer == bgp->peer_self
6067 && ((pi->type == ZEBRA_ROUTE_BGP
6068 && pi->sub_type == BGP_ROUTE_STATIC)
6069 || (pi->type != ZEBRA_ROUTE_BGP
6070 && pi->sub_type
d62a17ae 6071 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6072 bgp_aggregate_decrement(
6073 bgp, bgp_dest_get_prefix(dest), pi, afi,
6074 safi);
40381db7 6075 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6076 bgp_path_info_delete(dest, pi);
6077 bgp_process(bgp, dest, afi, safi);
d62a17ae 6078 }
6079 }
6080 }
ad4cbda1 6081}
6082
6083/*
6084 * Purge all networks and redistributed routes from routing table.
6085 * Invoked upon the instance going down.
6086 */
d62a17ae 6087void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6088{
d62a17ae 6089 afi_t afi;
6090 safi_t safi;
ad4cbda1 6091
05c7a1cc
QY
6092 FOREACH_AFI_SAFI (afi, safi)
6093 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6094}
6095
137446f9
LB
6096/*
6097 * gpz 110624
6098 * Currently this is used to set static routes for VPN and ENCAP.
6099 * I think it can probably be factored with bgp_static_set.
6100 */
d62a17ae 6101int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6102 const char *ip_str, const char *rd_str,
6103 const char *label_str, const char *rmap_str,
6104 int evpn_type, const char *esi, const char *gwip,
6105 const char *ethtag, const char *routermac)
6106{
6107 VTY_DECLVAR_CONTEXT(bgp, bgp);
6108 int ret;
6109 struct prefix p;
6110 struct prefix_rd prd;
9bcb3eef
DS
6111 struct bgp_dest *pdest;
6112 struct bgp_dest *dest;
d62a17ae 6113 struct bgp_table *table;
6114 struct bgp_static *bgp_static;
6115 mpls_label_t label = MPLS_INVALID_LABEL;
6116 struct prefix gw_ip;
6117
6118 /* validate ip prefix */
6119 ret = str2prefix(ip_str, &p);
6120 if (!ret) {
6121 vty_out(vty, "%% Malformed prefix\n");
6122 return CMD_WARNING_CONFIG_FAILED;
6123 }
6124 apply_mask(&p);
6125 if ((afi == AFI_L2VPN)
6126 && (bgp_build_evpn_prefix(evpn_type,
6127 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6128 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6129 return CMD_WARNING_CONFIG_FAILED;
6130 }
718e3744 6131
d62a17ae 6132 ret = str2prefix_rd(rd_str, &prd);
6133 if (!ret) {
6134 vty_out(vty, "%% Malformed rd\n");
6135 return CMD_WARNING_CONFIG_FAILED;
6136 }
718e3744 6137
d62a17ae 6138 if (label_str) {
6139 unsigned long label_val;
6140 label_val = strtoul(label_str, NULL, 10);
6141 encode_label(label_val, &label);
6142 }
9bedbb1e 6143
d62a17ae 6144 if (safi == SAFI_EVPN) {
6145 if (esi && str2esi(esi, NULL) == 0) {
6146 vty_out(vty, "%% Malformed ESI\n");
6147 return CMD_WARNING_CONFIG_FAILED;
6148 }
6149 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6150 vty_out(vty, "%% Malformed Router MAC\n");
6151 return CMD_WARNING_CONFIG_FAILED;
6152 }
6153 if (gwip) {
6154 memset(&gw_ip, 0, sizeof(struct prefix));
6155 ret = str2prefix(gwip, &gw_ip);
6156 if (!ret) {
6157 vty_out(vty, "%% Malformed GatewayIp\n");
6158 return CMD_WARNING_CONFIG_FAILED;
6159 }
6160 if ((gw_ip.family == AF_INET
3714a385 6161 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6162 (struct prefix_evpn *)&p))
6163 || (gw_ip.family == AF_INET6
3714a385 6164 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6165 (struct prefix_evpn *)&p))) {
6166 vty_out(vty,
6167 "%% GatewayIp family differs with IP prefix\n");
6168 return CMD_WARNING_CONFIG_FAILED;
6169 }
6170 }
6171 }
9bcb3eef
DS
6172 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6173 if (!bgp_dest_has_bgp_path_info_data(pdest))
6174 bgp_dest_set_bgp_table_info(pdest,
67009e22 6175 bgp_table_init(bgp, afi, safi));
9bcb3eef 6176 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6177
9bcb3eef 6178 dest = bgp_node_get(table, &p);
d62a17ae 6179
9bcb3eef 6180 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6181 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6182 bgp_dest_unlock_node(dest);
d62a17ae 6183 } else {
6184 /* New configuration. */
6185 bgp_static = bgp_static_new();
6186 bgp_static->backdoor = 0;
6187 bgp_static->valid = 0;
6188 bgp_static->igpmetric = 0;
975a328e 6189 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6190 bgp_static->label = label;
6191 bgp_static->prd = prd;
6192
6193 if (rmap_str) {
0a22ddfb 6194 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6195 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6196 bgp_static->rmap.name =
6197 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6198 bgp_static->rmap.map =
6199 route_map_lookup_by_name(rmap_str);
b4897fa5 6200 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6201 }
718e3744 6202
d62a17ae 6203 if (safi == SAFI_EVPN) {
6204 if (esi) {
6205 bgp_static->eth_s_id =
6206 XCALLOC(MTYPE_ATTR,
0a50c248 6207 sizeof(esi_t));
d62a17ae 6208 str2esi(esi, bgp_static->eth_s_id);
6209 }
6210 if (routermac) {
6211 bgp_static->router_mac =
28328ea9 6212 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6213 (void)prefix_str2mac(routermac,
6214 bgp_static->router_mac);
d62a17ae 6215 }
6216 if (gwip)
6217 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6218 }
9bcb3eef 6219 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6220
d62a17ae 6221 bgp_static->valid = 1;
6222 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6223 }
718e3744 6224
d62a17ae 6225 return CMD_SUCCESS;
718e3744 6226}
6227
6228/* Configure static BGP network. */
d62a17ae 6229int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6230 const char *ip_str, const char *rd_str,
6231 const char *label_str, int evpn_type, const char *esi,
6232 const char *gwip, const char *ethtag)
6233{
6234 VTY_DECLVAR_CONTEXT(bgp, bgp);
6235 int ret;
6236 struct prefix p;
6237 struct prefix_rd prd;
9bcb3eef
DS
6238 struct bgp_dest *pdest;
6239 struct bgp_dest *dest;
d62a17ae 6240 struct bgp_table *table;
6241 struct bgp_static *bgp_static;
6242 mpls_label_t label = MPLS_INVALID_LABEL;
6243
6244 /* Convert IP prefix string to struct prefix. */
6245 ret = str2prefix(ip_str, &p);
6246 if (!ret) {
6247 vty_out(vty, "%% Malformed prefix\n");
6248 return CMD_WARNING_CONFIG_FAILED;
6249 }
6250 apply_mask(&p);
6251 if ((afi == AFI_L2VPN)
6252 && (bgp_build_evpn_prefix(evpn_type,
6253 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6254 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6255 return CMD_WARNING_CONFIG_FAILED;
6256 }
6257 ret = str2prefix_rd(rd_str, &prd);
6258 if (!ret) {
6259 vty_out(vty, "%% Malformed rd\n");
6260 return CMD_WARNING_CONFIG_FAILED;
6261 }
718e3744 6262
d62a17ae 6263 if (label_str) {
6264 unsigned long label_val;
6265 label_val = strtoul(label_str, NULL, 10);
6266 encode_label(label_val, &label);
6267 }
718e3744 6268
9bcb3eef
DS
6269 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6270 if (!bgp_dest_has_bgp_path_info_data(pdest))
6271 bgp_dest_set_bgp_table_info(pdest,
67009e22 6272 bgp_table_init(bgp, afi, safi));
d62a17ae 6273 else
9bcb3eef
DS
6274 bgp_dest_unlock_node(pdest);
6275 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6276
9bcb3eef 6277 dest = bgp_node_lookup(table, &p);
6b0655a2 6278
9bcb3eef 6279 if (dest) {
d62a17ae 6280 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6281
9bcb3eef 6282 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6283 bgp_static_free(bgp_static);
9bcb3eef
DS
6284 bgp_dest_set_bgp_static_info(dest, NULL);
6285 bgp_dest_unlock_node(dest);
6286 bgp_dest_unlock_node(dest);
d62a17ae 6287 } else
6288 vty_out(vty, "%% Can't find the route\n");
6289
6290 return CMD_SUCCESS;
6291}
6292
6293static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6294 const char *rmap_name)
6295{
6296 VTY_DECLVAR_CONTEXT(bgp, bgp);
6297 struct bgp_rmap *rmap;
6298
6299 rmap = &bgp->table_map[afi][safi];
6300 if (rmap_name) {
0a22ddfb 6301 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6302 route_map_counter_decrement(rmap->map);
d62a17ae 6303 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6304 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6305 route_map_counter_increment(rmap->map);
d62a17ae 6306 } else {
0a22ddfb 6307 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6308 route_map_counter_decrement(rmap->map);
d62a17ae 6309 rmap->map = NULL;
6310 }
73ac8160 6311
d62a17ae 6312 if (bgp_fibupd_safi(safi))
6313 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6314
d62a17ae 6315 return CMD_SUCCESS;
73ac8160
DS
6316}
6317
d62a17ae 6318static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6319 const char *rmap_name)
73ac8160 6320{
d62a17ae 6321 VTY_DECLVAR_CONTEXT(bgp, bgp);
6322 struct bgp_rmap *rmap;
73ac8160 6323
d62a17ae 6324 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6325 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6326 route_map_counter_decrement(rmap->map);
d62a17ae 6327 rmap->map = NULL;
73ac8160 6328
d62a17ae 6329 if (bgp_fibupd_safi(safi))
6330 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6331
d62a17ae 6332 return CMD_SUCCESS;
73ac8160
DS
6333}
6334
2b791107 6335void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6336 safi_t safi)
73ac8160 6337{
d62a17ae 6338 if (bgp->table_map[afi][safi].name) {
d62a17ae 6339 vty_out(vty, " table-map %s\n",
6340 bgp->table_map[afi][safi].name);
6341 }
73ac8160
DS
6342}
6343
73ac8160
DS
6344DEFUN (bgp_table_map,
6345 bgp_table_map_cmd,
6346 "table-map WORD",
6347 "BGP table to RIB route download filter\n"
6348 "Name of the route map\n")
6349{
d62a17ae 6350 int idx_word = 1;
6351 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6352 argv[idx_word]->arg);
73ac8160
DS
6353}
6354DEFUN (no_bgp_table_map,
6355 no_bgp_table_map_cmd,
6356 "no table-map WORD",
3a2d747c 6357 NO_STR
73ac8160
DS
6358 "BGP table to RIB route download filter\n"
6359 "Name of the route map\n")
6360{
d62a17ae 6361 int idx_word = 2;
6362 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6363 argv[idx_word]->arg);
73ac8160
DS
6364}
6365
37a87b8f
CS
6366DEFPY_YANG (bgp_network, bgp_network_cmd,
6367 "[no] network \
6368 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6369 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6370 backdoor$backdoor}]",
6371 NO_STR
6372 "Specify a network to announce via BGP\n"
6373 "IPv4 prefix\n"
6374 "Network number\n"
6375 "Network mask\n"
6376 "Network mask\n"
6377 "Route-map to modify the attributes\n"
6378 "Name of the route map\n"
6379 "Label index to associate with the prefix\n"
6380 "Label index value\n"
6381 "Specify a BGP backdoor route\n")
6382{
6383 char addr_prefix_str[PREFIX_STRLEN];
6384 char base_xpath[XPATH_MAXLEN];
6385 afi_t afi;
6386 safi_t safi;
e2a86ad9
DS
6387
6388 if (address_str) {
6389 int ret;
718e3744 6390
e2a86ad9
DS
6391 ret = netmask_str2prefix_str(address_str, netmask_str,
6392 addr_prefix_str);
6393 if (!ret) {
6394 vty_out(vty, "%% Inconsistent address and mask\n");
6395 return CMD_WARNING_CONFIG_FAILED;
6396 }
d62a17ae 6397 }
718e3744 6398
37a87b8f
CS
6399 afi = bgp_node_afi(vty);
6400 safi = bgp_node_safi(vty);
6401
6402 if (no) {
6403 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6404 } else {
6405 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6406
6407 if (map_name)
6408 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6409 NB_OP_CREATE, map_name);
6410 else
6411 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6412 NB_OP_DESTROY, NULL);
6413
6414 if (label_index_str)
6415 nb_cli_enqueue_change(vty, "./label-index",
6416 NB_OP_MODIFY, label_index_str);
6417
6418 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6419 backdoor ? "true" : "false");
6420 }
6421
6422 snprintf(
6423 base_xpath, sizeof(base_xpath),
6424 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6425 yang_afi_safi_value2identity(afi, safi),
6426 bgp_afi_safi_get_container_str(afi, safi),
6427 address_str ? addr_prefix_str : prefix_str);
6428
6429 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6430}
6431
37a87b8f
CS
6432DEFPY_YANG (ipv6_bgp_network,
6433 ipv6_bgp_network_cmd,
6434 "[no] network X:X::X:X/M$prefix \
6435 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6436 NO_STR
6437 "Specify a network to announce via BGP\n"
6438 "IPv6 prefix\n"
6439 "Route-map to modify the attributes\n"
6440 "Name of the route map\n"
6441 "Label index to associate with the prefix\n"
6442 "Label index value\n")
6443{
6444 char base_xpath[XPATH_MAXLEN];
6445 afi_t afi;
6446 safi_t safi;
6447
6448 afi = bgp_node_afi(vty);
6449 safi = bgp_node_safi(vty);
6450
6451 if (no) {
6452 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6453 } else {
6454 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6455
6456 if (map_name)
6457 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6458 NB_OP_MODIFY, map_name);
6459 else
6460 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6461 NB_OP_DESTROY, NULL);
6462
6463 if (label_index_str)
6464 nb_cli_enqueue_change(vty, "./label-index",
6465 NB_OP_MODIFY, label_index_str);
6466 }
6467
6468 snprintf(
6469 base_xpath, sizeof(base_xpath),
6470 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6471 yang_afi_safi_value2identity(afi, safi),
6472 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6473
6474 return nb_cli_apply_changes(vty, base_xpath);
6475}
6476
6477void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6478 struct lyd_node *dnode,
6479 bool show_defaults)
718e3744 6480{
37a87b8f
CS
6481 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6482
6483 if (yang_dnode_exists(dnode, "./label-index"))
6484 vty_out(vty, " label-index %s",
6485 yang_dnode_get_string(dnode, "./label-index"));
6486
6487 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6488 vty_out(vty, " route-map %s",
6489 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6490
6491 if (yang_dnode_get_bool(dnode, "./backdoor"))
6492 vty_out(vty, " backdoor");
6493
6494 vty_out(vty, "\n");
1b6d5c7e
VV
6495}
6496
d62a17ae 6497static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6498{
d62a17ae 6499 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6500}
6501
d62a17ae 6502static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6503{
365ab2e7
RZ
6504 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6505 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6506 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6507 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6508 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6509}
718e3744 6510
365ab2e7
RZ
6511/**
6512 * Helper function to avoid repeated code: prepare variables for a
6513 * `route_map_apply` call.
6514 *
6515 * \returns `true` on route map match, otherwise `false`.
6516 */
6517static bool aggr_suppress_map_test(struct bgp *bgp,
6518 struct bgp_aggregate *aggregate,
6519 struct bgp_path_info *pi)
6520{
6521 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6522 route_map_result_t rmr = RMAP_DENYMATCH;
6523 struct bgp_path_info rmap_path = {};
6524 struct attr attr = {};
6525
6526 /* No route map entries created, just don't match. */
6527 if (aggregate->suppress_map == NULL)
6528 return false;
6529
6530 /* Call route map matching and return result. */
6531 attr.aspath = aspath_empty();
6532 rmap_path.peer = bgp->peer_self;
6533 rmap_path.attr = &attr;
6534
6535 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6536 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6537 bgp->peer_self->rmap_type = 0;
6538
6539 bgp_attr_flush(&attr);
6540
6541 return rmr == RMAP_PERMITMATCH;
6542}
6543
4056a5f6
RZ
6544/** Test whether the aggregation has suppressed this path or not. */
6545static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6546 struct bgp_path_info *pi)
6547{
6548 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6549 return false;
6550
6551 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6552}
6553
6554/**
6555 * Suppress this path and keep the reference.
6556 *
6557 * \returns `true` if needs processing otherwise `false`.
6558 */
6559static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6560 struct bgp_path_info *pi)
6561{
6562 struct bgp_path_info_extra *pie;
6563
6564 /* Path is already suppressed by this aggregation. */
6565 if (aggr_suppress_exists(aggregate, pi))
6566 return false;
6567
6568 pie = bgp_path_info_extra_get(pi);
6569
6570 /* This is the first suppression, allocate memory and list it. */
6571 if (pie->aggr_suppressors == NULL)
6572 pie->aggr_suppressors = list_new();
6573
6574 listnode_add(pie->aggr_suppressors, aggregate);
6575
6576 /* Only mark for processing if suppressed. */
6577 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6578 if (BGP_DEBUG(update, UPDATE_OUT))
6579 zlog_debug("aggregate-address suppressing: %pFX",
6580 bgp_dest_get_prefix(pi->net));
6581
4056a5f6
RZ
6582 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6583 return true;
6584 }
6585
6586 return false;
6587}
6588
6589/**
6590 * Unsuppress this path and remove the reference.
6591 *
6592 * \returns `true` if needs processing otherwise `false`.
6593 */
6594static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6595 struct bgp_path_info *pi)
6596{
6597 /* Path wasn't suppressed. */
6598 if (!aggr_suppress_exists(aggregate, pi))
6599 return false;
6600
6601 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6602
6603 /* Unsuppress and free extra memory if last item. */
6604 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6605 if (BGP_DEBUG(update, UPDATE_OUT))
6606 zlog_debug("aggregate-address unsuppressing: %pFX",
6607 bgp_dest_get_prefix(pi->net));
6608
4056a5f6
RZ
6609 list_delete(&pi->extra->aggr_suppressors);
6610 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6611 return true;
6612 }
6613
6614 return false;
6615}
6616
3dc339cd
DA
6617static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6618 struct aspath *aspath,
6619 struct community *comm,
6620 struct ecommunity *ecomm,
6621 struct lcommunity *lcomm)
eaaf8adb
DS
6622{
6623 static struct aspath *ae = NULL;
6624
6625 if (!ae)
6626 ae = aspath_empty();
6627
40381db7 6628 if (!pi)
3dc339cd 6629 return false;
eaaf8adb 6630
40381db7 6631 if (origin != pi->attr->origin)
3dc339cd 6632 return false;
eaaf8adb 6633
40381db7 6634 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6635 return false;
29f7d023 6636
40381db7 6637 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6638 return false;
eaaf8adb 6639
3da2cc32 6640 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6641 return false;
eaaf8adb 6642
dd18c5a9 6643 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6644 return false;
dd18c5a9 6645
40381db7 6646 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6647 return false;
7ce8a8e0 6648
3dc339cd 6649 return true;
eaaf8adb
DS
6650}
6651
5f040085
DS
6652static void bgp_aggregate_install(
6653 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6654 uint8_t origin, struct aspath *aspath, struct community *community,
6655 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6656 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6657{
9bcb3eef 6658 struct bgp_dest *dest;
c701010e 6659 struct bgp_table *table;
6f94b685 6660 struct bgp_path_info *pi, *orig, *new;
20894f50 6661 struct attr *attr;
c701010e
DS
6662
6663 table = bgp->rib[afi][safi];
6664
9bcb3eef 6665 dest = bgp_node_get(table, p);
eaaf8adb 6666
9bcb3eef 6667 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6668 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6669 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6670 break;
6671
6aabb15d
RZ
6672 /*
6673 * If we have paths with different MEDs, then don't install
6674 * (or uninstall) the aggregate route.
6675 */
6676 if (aggregate->match_med && aggregate->med_mismatched)
6677 goto uninstall_aggregate_route;
6678
c701010e 6679 if (aggregate->count > 0) {
eaaf8adb
DS
6680 /*
6681 * If the aggregate information has not changed
6682 * no need to re-install it again.
6683 */
6f94b685 6684 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6685 ecommunity, lcommunity)) {
9bcb3eef 6686 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6687
6688 if (aspath)
6689 aspath_free(aspath);
6690 if (community)
3c1f53de 6691 community_free(&community);
3da2cc32
DS
6692 if (ecommunity)
6693 ecommunity_free(&ecommunity);
dd18c5a9
DS
6694 if (lcommunity)
6695 lcommunity_free(&lcommunity);
eaaf8adb
DS
6696
6697 return;
6698 }
6699
6700 /*
6701 * Mark the old as unusable
6702 */
40381db7 6703 if (pi)
9bcb3eef 6704 bgp_path_info_delete(dest, pi);
eaaf8adb 6705
20894f50
DA
6706 attr = bgp_attr_aggregate_intern(
6707 bgp, origin, aspath, community, ecommunity, lcommunity,
6708 aggregate, atomic_aggregate, p);
6709
6710 if (!attr) {
6711 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6712 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6713 zlog_debug("%s: %pFX null attribute", __func__,
6714 p);
20894f50
DA
6715 return;
6716 }
6717
3da2cc32 6718 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6719 bgp->peer_self, attr, dest);
20894f50 6720
1defdda8 6721 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6722
9bcb3eef
DS
6723 bgp_path_info_add(dest, new);
6724 bgp_process(bgp, dest, afi, safi);
c701010e 6725 } else {
6aabb15d 6726 uninstall_aggregate_route:
6f94b685 6727 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6728 if (pi->peer == bgp->peer_self
6729 && pi->type == ZEBRA_ROUTE_BGP
6730 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6731 break;
6732
6733 /* Withdraw static BGP route from routing table. */
40381db7 6734 if (pi) {
9bcb3eef
DS
6735 bgp_path_info_delete(dest, pi);
6736 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6737 }
6738 }
6739
9bcb3eef 6740 bgp_dest_unlock_node(dest);
c701010e
DS
6741}
6742
6aabb15d
RZ
6743/**
6744 * Check if the current path has different MED than other known paths.
6745 *
6746 * \returns `true` if the MED matched the others else `false`.
6747 */
6748static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6749 struct bgp *bgp, struct bgp_path_info *pi)
6750{
6751 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6752
6753 /* This is the first route being analyzed. */
6754 if (!aggregate->med_initialized) {
6755 aggregate->med_initialized = true;
6756 aggregate->med_mismatched = false;
6757 aggregate->med_matched_value = cur_med;
6758 } else {
6759 /* Check if routes with different MED showed up. */
6760 if (cur_med != aggregate->med_matched_value)
6761 aggregate->med_mismatched = true;
6762 }
6763
6764 return !aggregate->med_mismatched;
6765}
6766
6767/**
6768 * Initializes and tests all routes in the aggregate address path for MED
6769 * values.
6770 *
6771 * \returns `true` if all MEDs are the same otherwise `false`.
6772 */
6773static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6774 struct bgp *bgp, const struct prefix *p,
6775 afi_t afi, safi_t safi)
6776{
6777 struct bgp_table *table = bgp->rib[afi][safi];
6778 const struct prefix *dest_p;
6779 struct bgp_dest *dest, *top;
6780 struct bgp_path_info *pi;
6781 bool med_matched = true;
6782
6783 aggregate->med_initialized = false;
6784
6785 top = bgp_node_get(table, p);
6786 for (dest = bgp_node_get(table, p); dest;
6787 dest = bgp_route_next_until(dest, top)) {
6788 dest_p = bgp_dest_get_prefix(dest);
6789 if (dest_p->prefixlen <= p->prefixlen)
6790 continue;
6791
6792 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6793 if (BGP_PATH_HOLDDOWN(pi))
6794 continue;
6795 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6796 continue;
6797 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6798 med_matched = false;
6799 break;
6800 }
6801 }
6802 if (!med_matched)
6803 break;
6804 }
6805 bgp_dest_unlock_node(top);
6806
6807 return med_matched;
6808}
6809
6810/**
6811 * Toggles the route suppression status for this aggregate address
6812 * configuration.
6813 */
4056a5f6
RZ
6814void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6815 struct bgp *bgp, const struct prefix *p,
6816 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6817{
6818 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6819 const struct prefix *dest_p;
6820 struct bgp_dest *dest, *top;
6821 struct bgp_path_info *pi;
6822 bool toggle_suppression;
6823
6824 /* We've found a different MED we must revert any suppressed routes. */
6825 top = bgp_node_get(table, p);
6826 for (dest = bgp_node_get(table, p); dest;
6827 dest = bgp_route_next_until(dest, top)) {
6828 dest_p = bgp_dest_get_prefix(dest);
6829 if (dest_p->prefixlen <= p->prefixlen)
6830 continue;
6831
6832 toggle_suppression = false;
6833 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6834 if (BGP_PATH_HOLDDOWN(pi))
6835 continue;
6836 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6837 continue;
6838
6aabb15d
RZ
6839 /* We are toggling suppression back. */
6840 if (suppress) {
6aabb15d 6841 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6842 if (aggr_suppress_path(aggregate, pi))
6843 toggle_suppression = true;
6aabb15d
RZ
6844 continue;
6845 }
6846
6aabb15d 6847 /* Install route if there is no more suppression. */
4056a5f6 6848 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6849 toggle_suppression = true;
6aabb15d
RZ
6850 }
6851
6852 if (toggle_suppression)
6853 bgp_process(bgp, dest, afi, safi);
6854 }
6855 bgp_dest_unlock_node(top);
6856}
6857
6858/**
6859 * Aggregate address MED matching incremental test: this function is called
6860 * when the initial aggregation occurred and we are only testing a single
6861 * new path.
6862 *
6863 * In addition to testing and setting the MED validity it also installs back
6864 * suppressed routes (if summary is configured).
6865 *
6866 * Must not be called in `bgp_aggregate_route`.
6867 */
6868static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6869 struct bgp *bgp, const struct prefix *p,
6870 afi_t afi, safi_t safi,
6871 struct bgp_path_info *pi, bool is_adding)
6872{
6873 /* MED matching disabled. */
6874 if (!aggregate->match_med)
6875 return;
6876
6877 /* Aggregation with different MED, nothing to do. */
6878 if (aggregate->med_mismatched)
6879 return;
6880
6881 /*
6882 * Test the current entry:
6883 *
6884 * is_adding == true: if the new entry doesn't match then we must
6885 * install all suppressed routes.
6886 *
6887 * is_adding == false: if the entry being removed was the last
6888 * unmatching entry then we can suppress all routes.
6889 */
6890 if (!is_adding) {
6891 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6892 && aggregate->summary_only)
6893 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6894 safi, true);
6895 } else
6896 bgp_aggregate_med_match(aggregate, bgp, pi);
6897
6898 /* No mismatches, just quit. */
6899 if (!aggregate->med_mismatched)
6900 return;
6901
6902 /* Route summarization is disabled. */
6903 if (!aggregate->summary_only)
6904 return;
6905
6906 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6907}
6908
b5d58c32 6909/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6910void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6911 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6912{
6913 struct bgp_table *table;
9bcb3eef
DS
6914 struct bgp_dest *top;
6915 struct bgp_dest *dest;
d7c0a89a 6916 uint8_t origin;
d62a17ae 6917 struct aspath *aspath = NULL;
d62a17ae 6918 struct community *community = NULL;
3da2cc32 6919 struct ecommunity *ecommunity = NULL;
dd18c5a9 6920 struct lcommunity *lcommunity = NULL;
40381db7 6921 struct bgp_path_info *pi;
d62a17ae 6922 unsigned long match = 0;
d7c0a89a 6923 uint8_t atomic_aggregate = 0;
d62a17ae 6924
9f822fa2
S
6925 /* If the bgp instance is being deleted or self peer is deleted
6926 * then do not create aggregate route
6927 */
892fedb6
DA
6928 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6929 || (bgp->peer_self == NULL))
9f822fa2
S
6930 return;
6931
6aabb15d
RZ
6932 /* Initialize and test routes for MED difference. */
6933 if (aggregate->match_med)
6934 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6935
4056a5f6
RZ
6936 /*
6937 * Reset aggregate count: we might've been called from route map
6938 * update so in that case we must retest all more specific routes.
6939 *
6940 * \see `bgp_route_map_process_update`.
6941 */
6942 aggregate->count = 0;
6943 aggregate->incomplete_origin_count = 0;
6944 aggregate->incomplete_origin_count = 0;
6945 aggregate->egp_origin_count = 0;
6946
d62a17ae 6947 /* ORIGIN attribute: If at least one route among routes that are
6948 aggregated has ORIGIN with the value INCOMPLETE, then the
6949 aggregated route must have the ORIGIN attribute with the value
6950 INCOMPLETE. Otherwise, if at least one route among routes that
6951 are aggregated has ORIGIN with the value EGP, then the aggregated
6952 route must have the origin attribute with the value EGP. In all
6953 other case the value of the ORIGIN attribute of the aggregated
6954 route is INTERNAL. */
6955 origin = BGP_ORIGIN_IGP;
718e3744 6956
d62a17ae 6957 table = bgp->rib[afi][safi];
718e3744 6958
d62a17ae 6959 top = bgp_node_get(table, p);
9bcb3eef
DS
6960 for (dest = bgp_node_get(table, p); dest;
6961 dest = bgp_route_next_until(dest, top)) {
6962 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6963
9bcb3eef 6964 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6965 continue;
d62a17ae 6966
a77e2f4b
S
6967 /* If suppress fib is enabled and route not installed
6968 * in FIB, skip the route
6969 */
6970 if (!bgp_check_advertise(bgp, dest))
6971 continue;
6972
c2ff8b3e 6973 match = 0;
d62a17ae 6974
9bcb3eef 6975 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6976 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6977 continue;
718e3744 6978
40381db7 6979 if (pi->attr->flag
c2ff8b3e
DS
6980 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6981 atomic_aggregate = 1;
d62a17ae 6982
40381db7 6983 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6984 continue;
d62a17ae 6985
f273fef1
DS
6986 /*
6987 * summary-only aggregate route suppress
6988 * aggregated route announcements.
6aabb15d
RZ
6989 *
6990 * MED matching:
6991 * Don't create summaries if MED didn't match
6992 * otherwise neither the specific routes and the
6993 * aggregation will be announced.
f273fef1 6994 */
6aabb15d
RZ
6995 if (aggregate->summary_only
6996 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6997 if (aggr_suppress_path(aggregate, pi))
6998 match++;
d62a17ae 6999 }
c2ff8b3e 7000
365ab2e7
RZ
7001 /*
7002 * Suppress more specific routes that match the route
7003 * map results.
7004 *
7005 * MED matching:
7006 * Don't suppress routes if MED matching is enabled and
7007 * it mismatched otherwise we might end up with no
7008 * routes for this path.
7009 */
7010 if (aggregate->suppress_map_name
7011 && AGGREGATE_MED_VALID(aggregate)
7012 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7013 if (aggr_suppress_path(aggregate, pi))
7014 match++;
d62a17ae 7015 }
c2ff8b3e
DS
7016
7017 aggregate->count++;
7018
f273fef1
DS
7019 /*
7020 * If at least one route among routes that are
7021 * aggregated has ORIGIN with the value INCOMPLETE,
7022 * then the aggregated route MUST have the ORIGIN
7023 * attribute with the value INCOMPLETE. Otherwise, if
7024 * at least one route among routes that are aggregated
7025 * has ORIGIN with the value EGP, then the aggregated
7026 * route MUST have the ORIGIN attribute with the value
7027 * EGP.
7028 */
fc968841
NT
7029 switch (pi->attr->origin) {
7030 case BGP_ORIGIN_INCOMPLETE:
7031 aggregate->incomplete_origin_count++;
7032 break;
7033 case BGP_ORIGIN_EGP:
7034 aggregate->egp_origin_count++;
7035 break;
7036 default:
7037 /*Do nothing.
7038 */
7039 break;
7040 }
c2ff8b3e
DS
7041
7042 if (!aggregate->as_set)
7043 continue;
7044
f273fef1
DS
7045 /*
7046 * as-set aggregate route generate origin, as path,
7047 * and community aggregation.
7048 */
fc968841
NT
7049 /* Compute aggregate route's as-path.
7050 */
ef51a7d8 7051 bgp_compute_aggregate_aspath_hash(aggregate,
7052 pi->attr->aspath);
c2ff8b3e 7053
fc968841
NT
7054 /* Compute aggregate route's community.
7055 */
7056 if (pi->attr->community)
21fec674 7057 bgp_compute_aggregate_community_hash(
fc968841
NT
7058 aggregate,
7059 pi->attr->community);
dd18c5a9 7060
fc968841
NT
7061 /* Compute aggregate route's extended community.
7062 */
7063 if (pi->attr->ecommunity)
4edd83f9 7064 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7065 aggregate,
7066 pi->attr->ecommunity);
7067
7068 /* Compute aggregate route's large community.
7069 */
7070 if (pi->attr->lcommunity)
f1eb1f05 7071 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7072 aggregate,
7073 pi->attr->lcommunity);
d62a17ae 7074 }
c2ff8b3e 7075 if (match)
9bcb3eef 7076 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7077 }
21fec674 7078 if (aggregate->as_set) {
ef51a7d8 7079 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7080 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7081 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7082 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7083 }
7084
f1eb1f05 7085
9bcb3eef 7086 bgp_dest_unlock_node(top);
718e3744 7087
718e3744 7088
fc968841
NT
7089 if (aggregate->incomplete_origin_count > 0)
7090 origin = BGP_ORIGIN_INCOMPLETE;
7091 else if (aggregate->egp_origin_count > 0)
7092 origin = BGP_ORIGIN_EGP;
d62a17ae 7093
229757f1
DA
7094 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7095 origin = aggregate->origin;
7096
fc968841
NT
7097 if (aggregate->as_set) {
7098 if (aggregate->aspath)
7099 /* Retrieve aggregate route's as-path.
7100 */
7101 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7102
fc968841
NT
7103 if (aggregate->community)
7104 /* Retrieve aggregate route's community.
7105 */
7106 community = community_dup(aggregate->community);
3da2cc32 7107
fc968841
NT
7108 if (aggregate->ecommunity)
7109 /* Retrieve aggregate route's ecommunity.
7110 */
7111 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7112
fc968841
NT
7113 if (aggregate->lcommunity)
7114 /* Retrieve aggregate route's lcommunity.
7115 */
7116 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7117 }
718e3744 7118
c701010e 7119 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7120 ecommunity, lcommunity, atomic_aggregate,
7121 aggregate);
718e3744 7122}
7123
5f040085
DS
7124void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7125 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7126{
7127 struct bgp_table *table;
9bcb3eef
DS
7128 struct bgp_dest *top;
7129 struct bgp_dest *dest;
40381db7 7130 struct bgp_path_info *pi;
3b7db173
DS
7131 unsigned long match;
7132
7133 table = bgp->rib[afi][safi];
7134
7135 /* If routes exists below this node, generate aggregate routes. */
7136 top = bgp_node_get(table, p);
9bcb3eef
DS
7137 for (dest = bgp_node_get(table, p); dest;
7138 dest = bgp_route_next_until(dest, top)) {
7139 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7140
9bcb3eef 7141 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7142 continue;
7143 match = 0;
7144
9bcb3eef 7145 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7146 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7147 continue;
7148
40381db7 7149 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7150 continue;
7151
6aabb15d
RZ
7152 if (aggregate->summary_only && pi->extra
7153 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7154 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7155 match++;
3b7db173 7156 }
3b7db173 7157
365ab2e7
RZ
7158 if (aggregate->suppress_map_name
7159 && AGGREGATE_MED_VALID(aggregate)
7160 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7161 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7162 match++;
3b7db173 7163 }
365ab2e7 7164
3b7db173 7165 aggregate->count--;
fc968841
NT
7166
7167 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7168 aggregate->incomplete_origin_count--;
7169 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7170 aggregate->egp_origin_count--;
7171
7172 if (aggregate->as_set) {
7173 /* Remove as-path from aggregate.
7174 */
ef51a7d8 7175 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7176 aggregate,
7177 pi->attr->aspath);
7178
7179 if (pi->attr->community)
7180 /* Remove community from aggregate.
7181 */
21fec674 7182 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7183 aggregate,
7184 pi->attr->community);
7185
7186 if (pi->attr->ecommunity)
7187 /* Remove ecommunity from aggregate.
7188 */
4edd83f9 7189 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7190 aggregate,
7191 pi->attr->ecommunity);
7192
7193 if (pi->attr->lcommunity)
7194 /* Remove lcommunity from aggregate.
7195 */
f1eb1f05 7196 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7197 aggregate,
7198 pi->attr->lcommunity);
7199 }
3b7db173
DS
7200 }
7201
7202 /* If this node was suppressed, process the change. */
7203 if (match)
9bcb3eef 7204 bgp_process(bgp, dest, afi, safi);
3b7db173 7205 }
f1eb1f05 7206 if (aggregate->as_set) {
ef51a7d8 7207 aspath_free(aggregate->aspath);
7208 aggregate->aspath = NULL;
21fec674 7209 if (aggregate->community)
7210 community_free(&aggregate->community);
4edd83f9 7211 if (aggregate->ecommunity)
7212 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7213 if (aggregate->lcommunity)
7214 lcommunity_free(&aggregate->lcommunity);
7215 }
7216
9bcb3eef 7217 bgp_dest_unlock_node(top);
3b7db173 7218}
718e3744 7219
5f040085
DS
7220static void bgp_add_route_to_aggregate(struct bgp *bgp,
7221 const struct prefix *aggr_p,
fc968841
NT
7222 struct bgp_path_info *pinew, afi_t afi,
7223 safi_t safi,
7224 struct bgp_aggregate *aggregate)
7225{
7226 uint8_t origin;
7227 struct aspath *aspath = NULL;
7228 uint8_t atomic_aggregate = 0;
7229 struct community *community = NULL;
7230 struct ecommunity *ecommunity = NULL;
7231 struct lcommunity *lcommunity = NULL;
7232
a4559740 7233 /* If the bgp instance is being deleted or self peer is deleted
7234 * then do not create aggregate route
7235 */
7236 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7237 || (bgp->peer_self == NULL))
7238 return;
7239
fc968841
NT
7240 /* ORIGIN attribute: If at least one route among routes that are
7241 * aggregated has ORIGIN with the value INCOMPLETE, then the
7242 * aggregated route must have the ORIGIN attribute with the value
7243 * INCOMPLETE. Otherwise, if at least one route among routes that
7244 * are aggregated has ORIGIN with the value EGP, then the aggregated
7245 * route must have the origin attribute with the value EGP. In all
7246 * other case the value of the ORIGIN attribute of the aggregated
7247 * route is INTERNAL.
7248 */
7249 origin = BGP_ORIGIN_IGP;
7250
7251 aggregate->count++;
7252
6aabb15d
RZ
7253 /*
7254 * This must be called before `summary` check to avoid
7255 * "suppressing" twice.
7256 */
7257 if (aggregate->match_med)
7258 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7259 pinew, true);
7260
7261 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7262 aggr_suppress_path(aggregate, pinew);
fc968841 7263
365ab2e7
RZ
7264 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7265 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7266 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7267
7268 switch (pinew->attr->origin) {
7269 case BGP_ORIGIN_INCOMPLETE:
7270 aggregate->incomplete_origin_count++;
7271 break;
7272 case BGP_ORIGIN_EGP:
7273 aggregate->egp_origin_count++;
7274 break;
7275 default:
7276 /* Do nothing.
7277 */
7278 break;
7279 }
7280
7281 if (aggregate->incomplete_origin_count > 0)
7282 origin = BGP_ORIGIN_INCOMPLETE;
7283 else if (aggregate->egp_origin_count > 0)
7284 origin = BGP_ORIGIN_EGP;
7285
229757f1
DA
7286 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7287 origin = aggregate->origin;
7288
fc968841
NT
7289 if (aggregate->as_set) {
7290 /* Compute aggregate route's as-path.
7291 */
7292 bgp_compute_aggregate_aspath(aggregate,
7293 pinew->attr->aspath);
7294
7295 /* Compute aggregate route's community.
7296 */
7297 if (pinew->attr->community)
7298 bgp_compute_aggregate_community(
7299 aggregate,
7300 pinew->attr->community);
7301
7302 /* Compute aggregate route's extended community.
7303 */
7304 if (pinew->attr->ecommunity)
7305 bgp_compute_aggregate_ecommunity(
7306 aggregate,
7307 pinew->attr->ecommunity);
7308
7309 /* Compute aggregate route's large community.
7310 */
7311 if (pinew->attr->lcommunity)
7312 bgp_compute_aggregate_lcommunity(
7313 aggregate,
7314 pinew->attr->lcommunity);
7315
7316 /* Retrieve aggregate route's as-path.
7317 */
7318 if (aggregate->aspath)
7319 aspath = aspath_dup(aggregate->aspath);
7320
7321 /* Retrieve aggregate route's community.
7322 */
7323 if (aggregate->community)
7324 community = community_dup(aggregate->community);
7325
7326 /* Retrieve aggregate route's ecommunity.
7327 */
7328 if (aggregate->ecommunity)
7329 ecommunity = ecommunity_dup(aggregate->ecommunity);
7330
7331 /* Retrieve aggregate route's lcommunity.
7332 */
7333 if (aggregate->lcommunity)
7334 lcommunity = lcommunity_dup(aggregate->lcommunity);
7335 }
7336
7337 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7338 aspath, community, ecommunity,
7339 lcommunity, atomic_aggregate, aggregate);
7340}
7341
7342static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7343 safi_t safi,
7344 struct bgp_path_info *pi,
7345 struct bgp_aggregate *aggregate,
5f040085 7346 const struct prefix *aggr_p)
fc968841
NT
7347{
7348 uint8_t origin;
7349 struct aspath *aspath = NULL;
7350 uint8_t atomic_aggregate = 0;
7351 struct community *community = NULL;
7352 struct ecommunity *ecommunity = NULL;
7353 struct lcommunity *lcommunity = NULL;
7354 unsigned long match = 0;
7355
a4559740 7356 /* If the bgp instance is being deleted or self peer is deleted
7357 * then do not create aggregate route
7358 */
7359 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7360 || (bgp->peer_self == NULL))
7361 return;
7362
fc968841
NT
7363 if (BGP_PATH_HOLDDOWN(pi))
7364 return;
7365
7366 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7367 return;
7368
4056a5f6
RZ
7369 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7370 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7371 match++;
fc968841 7372
365ab2e7 7373 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7374 && aggr_suppress_map_test(bgp, aggregate, pi))
7375 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7376 match++;
fc968841 7377
6aabb15d 7378 /*
365ab2e7 7379 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7380 * "unsuppressing" twice.
7381 */
7382 if (aggregate->match_med)
7383 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7384 true);
7385
fc968841
NT
7386 if (aggregate->count > 0)
7387 aggregate->count--;
7388
7389 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7390 aggregate->incomplete_origin_count--;
7391 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7392 aggregate->egp_origin_count--;
7393
7394 if (aggregate->as_set) {
7395 /* Remove as-path from aggregate.
7396 */
7397 bgp_remove_aspath_from_aggregate(aggregate,
7398 pi->attr->aspath);
7399
7400 if (pi->attr->community)
7401 /* Remove community from aggregate.
7402 */
7403 bgp_remove_community_from_aggregate(
7404 aggregate,
7405 pi->attr->community);
7406
7407 if (pi->attr->ecommunity)
7408 /* Remove ecommunity from aggregate.
7409 */
7410 bgp_remove_ecommunity_from_aggregate(
7411 aggregate,
7412 pi->attr->ecommunity);
7413
7414 if (pi->attr->lcommunity)
7415 /* Remove lcommunity from aggregate.
7416 */
7417 bgp_remove_lcommunity_from_aggregate(
7418 aggregate,
7419 pi->attr->lcommunity);
7420 }
7421
7422 /* If this node was suppressed, process the change. */
7423 if (match)
7424 bgp_process(bgp, pi->net, afi, safi);
7425
7426 origin = BGP_ORIGIN_IGP;
7427 if (aggregate->incomplete_origin_count > 0)
7428 origin = BGP_ORIGIN_INCOMPLETE;
7429 else if (aggregate->egp_origin_count > 0)
7430 origin = BGP_ORIGIN_EGP;
7431
229757f1
DA
7432 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7433 origin = aggregate->origin;
7434
fc968841
NT
7435 if (aggregate->as_set) {
7436 /* Retrieve aggregate route's as-path.
7437 */
7438 if (aggregate->aspath)
7439 aspath = aspath_dup(aggregate->aspath);
7440
7441 /* Retrieve aggregate route's community.
7442 */
7443 if (aggregate->community)
7444 community = community_dup(aggregate->community);
7445
7446 /* Retrieve aggregate route's ecommunity.
7447 */
7448 if (aggregate->ecommunity)
7449 ecommunity = ecommunity_dup(aggregate->ecommunity);
7450
7451 /* Retrieve aggregate route's lcommunity.
7452 */
7453 if (aggregate->lcommunity)
7454 lcommunity = lcommunity_dup(aggregate->lcommunity);
7455 }
7456
7457 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7458 aspath, community, ecommunity,
7459 lcommunity, atomic_aggregate, aggregate);
7460}
7461
5a1ae2c2 7462void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7463 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7464{
9bcb3eef
DS
7465 struct bgp_dest *child;
7466 struct bgp_dest *dest;
d62a17ae 7467 struct bgp_aggregate *aggregate;
7468 struct bgp_table *table;
718e3744 7469
d62a17ae 7470 table = bgp->aggregate[afi][safi];
f018db83 7471
d62a17ae 7472 /* No aggregates configured. */
7473 if (bgp_table_top_nolock(table) == NULL)
7474 return;
f018db83 7475
d62a17ae 7476 if (p->prefixlen == 0)
7477 return;
718e3744 7478
40381db7 7479 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7480 return;
718e3744 7481
a77e2f4b
S
7482 /* If suppress fib is enabled and route not installed
7483 * in FIB, do not update the aggregate route
7484 */
7485 if (!bgp_check_advertise(bgp, pi->net))
7486 return;
7487
d62a17ae 7488 child = bgp_node_get(table, p);
718e3744 7489
d62a17ae 7490 /* Aggregate address configuration check. */
9bcb3eef
DS
7491 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7492 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7493
9bcb3eef
DS
7494 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7495 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7496 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7497 aggregate);
d62a17ae 7498 }
b1e62edd 7499 }
9bcb3eef 7500 bgp_dest_unlock_node(child);
718e3744 7501}
7502
5a1ae2c2 7503void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7504 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7505{
9bcb3eef
DS
7506 struct bgp_dest *child;
7507 struct bgp_dest *dest;
d62a17ae 7508 struct bgp_aggregate *aggregate;
7509 struct bgp_table *table;
718e3744 7510
d62a17ae 7511 table = bgp->aggregate[afi][safi];
718e3744 7512
d62a17ae 7513 /* No aggregates configured. */
7514 if (bgp_table_top_nolock(table) == NULL)
7515 return;
718e3744 7516
d62a17ae 7517 if (p->prefixlen == 0)
7518 return;
718e3744 7519
d62a17ae 7520 child = bgp_node_get(table, p);
718e3744 7521
d62a17ae 7522 /* Aggregate address configuration check. */
9bcb3eef
DS
7523 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7524 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7525
9bcb3eef
DS
7526 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7527 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7528 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7529 aggregate, dest_p);
d62a17ae 7530 }
b1e62edd 7531 }
9bcb3eef 7532 bgp_dest_unlock_node(child);
d62a17ae 7533}
718e3744 7534
718e3744 7535/* Aggregate route attribute. */
7536#define AGGREGATE_SUMMARY_ONLY 1
7537#define AGGREGATE_AS_SET 1
fb29348a 7538#define AGGREGATE_AS_UNSET 0
718e3744 7539
229757f1
DA
7540static const char *bgp_origin2str(uint8_t origin)
7541{
7542 switch (origin) {
7543 case BGP_ORIGIN_IGP:
7544 return "igp";
7545 case BGP_ORIGIN_EGP:
7546 return "egp";
7547 case BGP_ORIGIN_INCOMPLETE:
7548 return "incomplete";
7549 }
7550 return "n/a";
7551}
7552
37a87b8f
CS
7553int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7554 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7555{
9bcb3eef 7556 struct bgp_dest *dest;
d62a17ae 7557 struct bgp_aggregate *aggregate;
718e3744 7558
a4559740 7559 /* If the bgp instance is being deleted or self peer is deleted
7560 * then do not create aggregate route
7561 */
7562 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7563 || (bgp->peer_self == NULL))
7564 return 0;
7565
37a87b8f 7566 apply_mask(prefix);
d62a17ae 7567 /* Old configuration check. */
37a87b8f 7568 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7569 if (!dest) {
37a87b8f
CS
7570 snprintf(errmsg, errmsg_len,
7571 "There is no aggregate-address configuration.\n");
7572 return -1;
d62a17ae 7573 }
f6269b4f 7574
9bcb3eef 7575 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7576 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7577 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7578 0, aggregate);
d62a17ae 7579
7580 /* Unlock aggregate address configuration. */
9bcb3eef 7581 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7582
7583 if (aggregate->community)
7584 community_free(&aggregate->community);
7585
7586 if (aggregate->community_hash) {
7587 /* Delete all communities in the hash.
7588 */
7589 hash_clean(aggregate->community_hash,
7590 bgp_aggr_community_remove);
7591 /* Free up the community_hash.
7592 */
7593 hash_free(aggregate->community_hash);
7594 }
7595
7596 if (aggregate->ecommunity)
7597 ecommunity_free(&aggregate->ecommunity);
7598
7599 if (aggregate->ecommunity_hash) {
7600 /* Delete all ecommunities in the hash.
7601 */
7602 hash_clean(aggregate->ecommunity_hash,
7603 bgp_aggr_ecommunity_remove);
7604 /* Free up the ecommunity_hash.
7605 */
7606 hash_free(aggregate->ecommunity_hash);
7607 }
7608
7609 if (aggregate->lcommunity)
7610 lcommunity_free(&aggregate->lcommunity);
7611
7612 if (aggregate->lcommunity_hash) {
7613 /* Delete all lcommunities in the hash.
7614 */
7615 hash_clean(aggregate->lcommunity_hash,
7616 bgp_aggr_lcommunity_remove);
7617 /* Free up the lcommunity_hash.
7618 */
7619 hash_free(aggregate->lcommunity_hash);
7620 }
7621
7622 if (aggregate->aspath)
7623 aspath_free(aggregate->aspath);
7624
7625 if (aggregate->aspath_hash) {
7626 /* Delete all as-paths in the hash.
7627 */
7628 hash_clean(aggregate->aspath_hash,
7629 bgp_aggr_aspath_remove);
7630 /* Free up the aspath_hash.
7631 */
7632 hash_free(aggregate->aspath_hash);
7633 }
7634
d62a17ae 7635 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7636 bgp_dest_unlock_node(dest);
7637 bgp_dest_unlock_node(dest);
d62a17ae 7638
37a87b8f 7639 return 0;
d62a17ae 7640}
7641
37a87b8f
CS
7642int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7643 safi_t safi, const char *rmap, uint8_t summary_only,
7644 uint8_t as_set, uint8_t origin, bool match_med,
7645 const char *suppress_map,
7646 char *errmsg, size_t errmsg_len)
d62a17ae 7647{
d62a17ae 7648 int ret;
9bcb3eef 7649 struct bgp_dest *dest;
d62a17ae 7650 struct bgp_aggregate *aggregate;
fb29348a 7651 uint8_t as_set_new = as_set;
37a87b8f 7652 char buf[PREFIX2STR_BUFFER];
d62a17ae 7653
365ab2e7 7654 if (suppress_map && summary_only) {
37a87b8f 7655 snprintf(errmsg, errmsg_len,
365ab2e7 7656 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7657 return -1;
365ab2e7
RZ
7658 }
7659
37a87b8f 7660 apply_mask(prefix);
d62a17ae 7661
37a87b8f
CS
7662 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7663 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7664 snprintf(
7665 errmsg, errmsg_len,
7666 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7667 prefix2str(prefix, buf, PREFIX_STRLEN));
7668 return -1;
3624ac81
DS
7669 }
7670
d62a17ae 7671 /* Old configuration check. */
37a87b8f 7672 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7673 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7674
20894f50 7675 if (aggregate) {
37a87b8f
CS
7676 snprintf(errmsg, errmsg_len,
7677 "There is already same aggregate network.\n");
d62a17ae 7678 /* try to remove the old entry */
37a87b8f
CS
7679 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7680 errmsg_len);
d62a17ae 7681 if (ret) {
37a87b8f
CS
7682 snprintf(errmsg, errmsg_len,
7683 "Error deleting aggregate.\n");
9bcb3eef 7684 bgp_dest_unlock_node(dest);
37a87b8f 7685 return -1;
d62a17ae 7686 }
7687 }
718e3744 7688
d62a17ae 7689 /* Make aggregate address structure. */
7690 aggregate = bgp_aggregate_new();
7691 aggregate->summary_only = summary_only;
6aabb15d 7692 aggregate->match_med = match_med;
fb29348a
DA
7693
7694 /* Network operators MUST NOT locally generate any new
7695 * announcements containing AS_SET or AS_CONFED_SET. If they have
7696 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7697 * SHOULD withdraw those routes and re-announce routes for the
7698 * aggregate or component prefixes (i.e., the more-specific routes
7699 * subsumed by the previously aggregated route) without AS_SET
7700 * or AS_CONFED_SET in the updates.
7701 */
7f972cd8 7702 if (bgp->reject_as_sets) {
fb29348a
DA
7703 if (as_set == AGGREGATE_AS_SET) {
7704 as_set_new = AGGREGATE_AS_UNSET;
7705 zlog_warn(
63efca0e 7706 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7707 __func__);
37a87b8f
CS
7708 snprintf(
7709 errmsg, errmsg_len,
fb29348a
DA
7710 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7711 }
7712 }
7713
7714 aggregate->as_set = as_set_new;
d62a17ae 7715 aggregate->safi = safi;
229757f1
DA
7716 /* Override ORIGIN attribute if defined.
7717 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7718 * to IGP which is not what rfc4271 says.
7719 * This enables the same behavior, optionally.
7720 */
7721 aggregate->origin = origin;
20894f50
DA
7722
7723 if (rmap) {
7724 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7725 route_map_counter_decrement(aggregate->rmap.map);
7726 aggregate->rmap.name =
7727 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7728 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7729 route_map_counter_increment(aggregate->rmap.map);
7730 }
365ab2e7
RZ
7731
7732 if (suppress_map) {
7733 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7734 route_map_counter_decrement(aggregate->suppress_map);
7735
7736 aggregate->suppress_map_name =
7737 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7738 aggregate->suppress_map =
7739 route_map_lookup_by_name(aggregate->suppress_map_name);
7740 route_map_counter_increment(aggregate->suppress_map);
7741 }
7742
9bcb3eef 7743 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7744
d62a17ae 7745 /* Aggregate address insert into BGP routing table. */
37a87b8f 7746 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7747
37a87b8f 7748 return 0;
718e3744 7749}
7750
37a87b8f
CS
7751DEFPY_YANG(
7752 aggregate_addressv4, aggregate_addressv4_cmd,
7753 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7754 "as-set$as_set_s"
7755 "|summary-only$summary_only"
7756 "|route-map WORD$rmap_name"
7757 "|origin <egp|igp|incomplete>$origin_s"
7758 "|matching-MED-only$match_med"
90e21f35 7759 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7760 "}",
7761 NO_STR
7762 "Configure BGP aggregate entries\n"
7763 "Aggregate prefix\n"
7764 "Aggregate address\n"
7765 "Aggregate mask\n"
7766 "Generate AS set path information\n"
7767 "Filter more specific routes from updates\n"
7768 "Apply route map to aggregate network\n"
7769 "Route map name\n"
7770 "BGP origin code\n"
7771 "Remote EGP\n"
7772 "Local IGP\n"
7773 "Unknown heritage\n"
7774 "Only aggregate routes with matching MED\n"
90e21f35
CS
7775 "Suppress the selected more specific routes\n"
7776 "Route map with the route selectors\n")
37a87b8f
CS
7777{
7778 char base_xpath[XPATH_MAXLEN];
554b3b10 7779 safi_t safi = bgp_node_safi(vty);
554b3b10 7780 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7781
554b3b10
RZ
7782 if (addr_str) {
7783 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7784 == 0) {
7785 vty_out(vty, "%% Inconsistent address and mask\n");
7786 return CMD_WARNING_CONFIG_FAILED;
7787 }
37a87b8f
CS
7788 } else {
7789 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7790 }
7791
37a87b8f
CS
7792 if (!no && origin_s)
7793 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7794
7795 if (!no && as_set_s)
7796 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7797 else
7798 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7799
7800 if (!no && summary_only)
7801 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7802 "true");
7803 else
7804 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7805 "false");
7806
fa423774
CS
7807 if (!no && match_med)
7808 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7809 else
7810 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7811 "false");
7812
37a87b8f
CS
7813 if (rmap_name)
7814 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7815 rmap_name);
7816 else
7817 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7818 NB_OP_DESTROY, NULL);
7819
90e21f35
CS
7820 if (suppress_map)
7821 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7822 suppress_map);
7823 else
7824 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7825 NULL);
7826
37a87b8f
CS
7827 snprintf(
7828 base_xpath, sizeof(base_xpath),
7829 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7830 yang_afi_safi_value2identity(AFI_IP, safi),
7831 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7832
554b3b10 7833 if (no)
37a87b8f
CS
7834 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7835 else
7836 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7837
7838 return nb_cli_apply_changes(vty, base_xpath);
7839}
7840
7841DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7842 "[no] aggregate-address X:X::X:X/M$prefix {"
7843 "as-set$as_set_s"
7844 "|summary-only$summary_only"
7845 "|route-map WORD$rmap_name"
7846 "|origin <egp|igp|incomplete>$origin_s"
7847 "|matching-MED-only$match_med"
90e21f35 7848 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7849 "}",
7850 NO_STR
7851 "Configure BGP aggregate entries\n"
7852 "Aggregate prefix\n"
7853 "Generate AS set path information\n"
7854 "Filter more specific routes from updates\n"
7855 "Apply route map to aggregate network\n"
7856 "Route map name\n"
7857 "BGP origin code\n"
7858 "Remote EGP\n"
7859 "Local IGP\n"
7860 "Unknown heritage\n"
7861 "Only aggregate routes with matching MED\n"
7862 "Suppress the selected more specific routes\n"
90e21f35 7863 "Route map with the route selectors\n")
37a87b8f
CS
7864{
7865 char base_xpath[XPATH_MAXLEN];
7866 safi_t safi = bgp_node_safi(vty);
7867
7868 if (!no && origin_s)
7869 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7870
7871 if (!no && as_set_s)
7872 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7873 else
7874 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7875
7876 if (!no && summary_only)
7877 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7878 "true");
7879 else
7880 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7881 "false");
7882
fa423774
CS
7883 if (!no && match_med)
7884 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7885 else
7886 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7887 "false");
7888
37a87b8f
CS
7889 if (rmap_name)
7890 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7891 rmap_name);
7892
90e21f35
CS
7893 if (suppress_map)
7894 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7895 suppress_map);
7896 else
7897 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7898 NULL);
7899
37a87b8f
CS
7900 snprintf(
7901 base_xpath, sizeof(base_xpath),
7902 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7903 yang_afi_safi_value2identity(AFI_IP6, safi),
7904 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7905
554b3b10 7906 if (no)
37a87b8f
CS
7907 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7908 else
7909 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7910
37a87b8f
CS
7911 return nb_cli_apply_changes(vty, base_xpath);
7912}
7913
7914void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7915 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7916{
7917 uint8_t origin;
7918
7919 vty_out(vty, " aggregate-address %s",
7920 yang_dnode_get_string(dnode, "./prefix"));
7921
7922 if (yang_dnode_get_bool(dnode, "./as-set"))
7923 vty_out(vty, " as-set");
7924
7925 if (yang_dnode_get_bool(dnode, "./summary-only"))
7926 vty_out(vty, " summary-only");
7927
7928 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7929 vty_out(vty, " route-map %s",
7930 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7931
7932 origin = yang_dnode_get_enum(dnode, "./origin");
7933 if (origin != BGP_ORIGIN_UNSPECIFIED)
7934 vty_out(vty, " origin %s", bgp_origin2str(origin));
7935
fa423774
CS
7936 if (yang_dnode_get_bool(dnode, "./match-med"))
7937 vty_out(vty, " matching-MED-only");
7938
37a87b8f 7939 vty_out(vty, "\n");
718e3744 7940}
7941
718e3744 7942/* Redistribute route treatment. */
d62a17ae 7943void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7944 const union g_addr *nexthop, ifindex_t ifindex,
7945 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7946 uint8_t type, unsigned short instance,
7947 route_tag_t tag)
d62a17ae 7948{
4b7e6066 7949 struct bgp_path_info *new;
40381db7
DS
7950 struct bgp_path_info *bpi;
7951 struct bgp_path_info rmap_path;
9bcb3eef 7952 struct bgp_dest *bn;
d62a17ae 7953 struct attr attr;
7954 struct attr *new_attr;
7955 afi_t afi;
b68885f9 7956 route_map_result_t ret;
d62a17ae 7957 struct bgp_redist *red;
7958
7959 /* Make default attribute. */
7960 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7961 /*
7962 * This must not be NULL to satisfy Coverity SA
7963 */
7964 assert(attr.aspath);
9de1f7ff 7965
a4d82a8a 7966 switch (nhtype) {
9de1f7ff
DS
7967 case NEXTHOP_TYPE_IFINDEX:
7968 break;
7969 case NEXTHOP_TYPE_IPV4:
7970 case NEXTHOP_TYPE_IPV4_IFINDEX:
7971 attr.nexthop = nexthop->ipv4;
7972 break;
7973 case NEXTHOP_TYPE_IPV6:
7974 case NEXTHOP_TYPE_IPV6_IFINDEX:
7975 attr.mp_nexthop_global = nexthop->ipv6;
7976 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7977 break;
7978 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7979 switch (p->family) {
7980 case AF_INET:
9de1f7ff 7981 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7982 break;
7983 case AF_INET6:
9de1f7ff
DS
7984 memset(&attr.mp_nexthop_global, 0,
7985 sizeof(attr.mp_nexthop_global));
74489921 7986 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7987 break;
74489921 7988 }
9de1f7ff 7989 break;
d62a17ae 7990 }
74489921 7991 attr.nh_ifindex = ifindex;
f04a80a5 7992
d62a17ae 7993 attr.med = metric;
7994 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7995 attr.tag = tag;
718e3744 7996
d62a17ae 7997 afi = family2afi(p->family);
6aeb9e78 7998
d62a17ae 7999 red = bgp_redist_lookup(bgp, afi, type, instance);
8000 if (red) {
8001 struct attr attr_new;
718e3744 8002
d62a17ae 8003 /* Copy attribute for modification. */
6f4f49b2 8004 attr_new = attr;
718e3744 8005
d62a17ae 8006 if (red->redist_metric_flag)
8007 attr_new.med = red->redist_metric;
718e3744 8008
d62a17ae 8009 /* Apply route-map. */
8010 if (red->rmap.name) {
40381db7
DS
8011 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8012 rmap_path.peer = bgp->peer_self;
8013 rmap_path.attr = &attr_new;
718e3744 8014
d62a17ae 8015 SET_FLAG(bgp->peer_self->rmap_type,
8016 PEER_RMAP_TYPE_REDISTRIBUTE);
8017
1782514f 8018 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8019
8020 bgp->peer_self->rmap_type = 0;
8021
8022 if (ret == RMAP_DENYMATCH) {
8023 /* Free uninterned attribute. */
8024 bgp_attr_flush(&attr_new);
8025
8026 /* Unintern original. */
8027 aspath_unintern(&attr.aspath);
8028 bgp_redistribute_delete(bgp, p, type, instance);
8029 return;
8030 }
8031 }
8032
637e5ba4 8033 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8034 bgp_attr_add_gshut_community(&attr_new);
8035
d62a17ae 8036 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8037 SAFI_UNICAST, p, NULL);
8038
8039 new_attr = bgp_attr_intern(&attr_new);
8040
9bcb3eef 8041 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8042 if (bpi->peer == bgp->peer_self
8043 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8044 break;
8045
40381db7 8046 if (bpi) {
d62a17ae 8047 /* Ensure the (source route) type is updated. */
40381db7
DS
8048 bpi->type = type;
8049 if (attrhash_cmp(bpi->attr, new_attr)
8050 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8051 bgp_attr_unintern(&new_attr);
8052 aspath_unintern(&attr.aspath);
9bcb3eef 8053 bgp_dest_unlock_node(bn);
d62a17ae 8054 return;
8055 } else {
8056 /* The attribute is changed. */
40381db7 8057 bgp_path_info_set_flag(bn, bpi,
18ee8310 8058 BGP_PATH_ATTR_CHANGED);
d62a17ae 8059
8060 /* Rewrite BGP route information. */
40381db7
DS
8061 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8062 bgp_path_info_restore(bn, bpi);
d62a17ae 8063 else
40381db7
DS
8064 bgp_aggregate_decrement(
8065 bgp, p, bpi, afi, SAFI_UNICAST);
8066 bgp_attr_unintern(&bpi->attr);
8067 bpi->attr = new_attr;
8068 bpi->uptime = bgp_clock();
d62a17ae 8069
8070 /* Process change. */
40381db7 8071 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8072 SAFI_UNICAST);
8073 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8074 bgp_dest_unlock_node(bn);
d62a17ae 8075 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8076
8077 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8078 || (bgp->inst_type
8079 == BGP_INSTANCE_TYPE_DEFAULT)) {
8080
8081 vpn_leak_from_vrf_update(
40381db7 8082 bgp_get_default(), bgp, bpi);
ddb5b488 8083 }
d62a17ae 8084 return;
8085 }
8086 }
8087
8088 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8089 bgp->peer_self, new_attr, bn);
1defdda8 8090 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8091
8092 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8093 bgp_path_info_add(bn, new);
9bcb3eef 8094 bgp_dest_unlock_node(bn);
d62a17ae 8095 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8096
8097 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8098 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8099
8100 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8101 }
d62a17ae 8102 }
8103
8104 /* Unintern original. */
8105 aspath_unintern(&attr.aspath);
718e3744 8106}
8107
d7c0a89a
QY
8108void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8109 unsigned short instance)
718e3744 8110{
d62a17ae 8111 afi_t afi;
9bcb3eef 8112 struct bgp_dest *dest;
40381db7 8113 struct bgp_path_info *pi;
d62a17ae 8114 struct bgp_redist *red;
718e3744 8115
d62a17ae 8116 afi = family2afi(p->family);
718e3744 8117
d62a17ae 8118 red = bgp_redist_lookup(bgp, afi, type, instance);
8119 if (red) {
9bcb3eef
DS
8120 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8121 SAFI_UNICAST, p, NULL);
d62a17ae 8122
9bcb3eef 8123 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8124 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8125 break;
8126
40381db7 8127 if (pi) {
ddb5b488
PZ
8128 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8129 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8130
8131 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8132 bgp, pi);
ddb5b488 8133 }
40381db7 8134 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8135 bgp_path_info_delete(dest, pi);
8136 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8137 }
9bcb3eef 8138 bgp_dest_unlock_node(dest);
d62a17ae 8139 }
8140}
8141
8142/* Withdraw specified route type's route. */
8143void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8144 unsigned short instance)
d62a17ae 8145{
9bcb3eef 8146 struct bgp_dest *dest;
40381db7 8147 struct bgp_path_info *pi;
d62a17ae 8148 struct bgp_table *table;
8149
8150 table = bgp->rib[afi][SAFI_UNICAST];
8151
9bcb3eef
DS
8152 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8153 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8154 if (pi->peer == bgp->peer_self && pi->type == type
8155 && pi->instance == instance)
d62a17ae 8156 break;
8157
40381db7 8158 if (pi) {
ddb5b488
PZ
8159 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8160 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8161
8162 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8163 bgp, pi);
ddb5b488 8164 }
9bcb3eef 8165 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8166 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8167 bgp_path_info_delete(dest, pi);
8168 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8169 }
718e3744 8170 }
718e3744 8171}
6b0655a2 8172
718e3744 8173/* Static function to display route. */
bd494ec5 8174static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8175 json_object *json, bool wide)
718e3744 8176{
be054588 8177 int len = 0;
d62a17ae 8178 char buf[BUFSIZ];
50e05855 8179 char buf2[BUFSIZ];
718e3744 8180
d62a17ae 8181 if (p->family == AF_INET) {
c6462ff4 8182 if (!json) {
8228a9a7 8183 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8184 } else {
8185 json_object_string_add(json, "prefix",
8186 inet_ntop(p->family,
8187 &p->u.prefix, buf,
8188 BUFSIZ));
8189 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8190 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8191 json_object_string_add(json, "network", buf2);
c6462ff4 8192 }
d62a17ae 8193 } else if (p->family == AF_ETHERNET) {
8228a9a7 8194 len = vty_out(vty, "%pFX", p);
b03b8898 8195 } else if (p->family == AF_EVPN) {
57f7feb6 8196 if (!json)
2dbe669b 8197 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8198 else
60466a63 8199 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8200 } else if (p->family == AF_FLOWSPEC) {
8201 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8202 json ?
8203 NLRI_STRING_FORMAT_JSON_SIMPLE :
8204 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8205 } else {
c6462ff4 8206 if (!json)
8228a9a7 8207 len = vty_out(vty, "%pFX", p);
50e05855
AD
8208 else {
8209 json_object_string_add(json, "prefix",
8210 inet_ntop(p->family,
8211 &p->u.prefix, buf,
8212 BUFSIZ));
8213 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8214 prefix2str(p, buf2, PREFIX_STRLEN);
8215 json_object_string_add(json, "network", buf2);
8216 }
9c92b5f7 8217 }
d62a17ae 8218
9c92b5f7 8219 if (!json) {
ae248832 8220 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8221 if (len < 1)
8222 vty_out(vty, "\n%*s", 20, " ");
8223 else
8224 vty_out(vty, "%*s", len, " ");
8225 }
718e3744 8226}
8227
d62a17ae 8228enum bgp_display_type {
8229 normal_list,
718e3744 8230};
8231
bbb46eb5
DA
8232static const char *
8233bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8234{
8235 switch (reason) {
8236 case bgp_path_selection_none:
8237 return "Nothing to Select";
8238 case bgp_path_selection_first:
8239 return "First path received";
8240 case bgp_path_selection_evpn_sticky_mac:
8241 return "EVPN Sticky Mac";
8242 case bgp_path_selection_evpn_seq:
8243 return "EVPN sequence number";
8244 case bgp_path_selection_evpn_lower_ip:
8245 return "EVPN lower IP";
8246 case bgp_path_selection_evpn_local_path:
8247 return "EVPN local ES path";
8248 case bgp_path_selection_evpn_non_proxy:
8249 return "EVPN non proxy";
8250 case bgp_path_selection_weight:
8251 return "Weight";
8252 case bgp_path_selection_local_pref:
8253 return "Local Pref";
8254 case bgp_path_selection_local_route:
8255 return "Local Route";
8256 case bgp_path_selection_confed_as_path:
8257 return "Confederation based AS Path";
8258 case bgp_path_selection_as_path:
8259 return "AS Path";
8260 case bgp_path_selection_origin:
8261 return "Origin";
8262 case bgp_path_selection_med:
8263 return "MED";
8264 case bgp_path_selection_peer:
8265 return "Peer Type";
8266 case bgp_path_selection_confed:
8267 return "Confed Peer Type";
8268 case bgp_path_selection_igp_metric:
8269 return "IGP Metric";
8270 case bgp_path_selection_older:
8271 return "Older Path";
8272 case bgp_path_selection_router_id:
8273 return "Router ID";
8274 case bgp_path_selection_cluster_length:
bcab253c 8275 return "Cluster length";
bbb46eb5
DA
8276 case bgp_path_selection_stale:
8277 return "Path Staleness";
8278 case bgp_path_selection_local_configured:
8279 return "Locally configured route";
8280 case bgp_path_selection_neighbor_ip:
8281 return "Neighbor IP";
8282 case bgp_path_selection_default:
8283 return "Nothing left to compare";
8284 }
8285 return "Invalid (internal error)";
8286}
8287
18ee8310 8288/* Print the short form route status for a bgp_path_info */
4b7e6066 8289static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8290 struct bgp_path_info *path,
d62a17ae 8291 json_object *json_path)
718e3744 8292{
d62a17ae 8293 if (json_path) {
b05a1c8b 8294
d62a17ae 8295 /* Route status display. */
9b6d8fcf 8296 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8297 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8298
9b6d8fcf 8299 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8300 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8301
4056a5f6 8302 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8303 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8304
9b6d8fcf
DS
8305 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8306 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8307 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8308
d62a17ae 8309 /* Selected */
9b6d8fcf 8310 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8311 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8312
9b6d8fcf 8313 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8314 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8315
bbb46eb5 8316 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8317 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8318 json_object_string_add(json_path, "selectionReason",
8319 bgp_path_selection_reason2str(
8320 path->net->reason));
8321 }
b05a1c8b 8322
9b6d8fcf 8323 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8324 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8325
d62a17ae 8326 /* Internal route. */
9b6d8fcf
DS
8327 if ((path->peer->as)
8328 && (path->peer->as == path->peer->local_as))
d62a17ae 8329 json_object_string_add(json_path, "pathFrom",
8330 "internal");
8331 else
8332 json_object_string_add(json_path, "pathFrom",
8333 "external");
b05a1c8b 8334
d62a17ae 8335 return;
8336 }
b05a1c8b 8337
d62a17ae 8338 /* Route status display. */
9b6d8fcf 8339 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8340 vty_out(vty, "R");
9b6d8fcf 8341 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8342 vty_out(vty, "S");
4056a5f6 8343 else if (bgp_path_suppressed(path))
d62a17ae 8344 vty_out(vty, "s");
9b6d8fcf
DS
8345 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8346 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8347 vty_out(vty, "*");
8348 else
8349 vty_out(vty, " ");
8350
8351 /* Selected */
9b6d8fcf 8352 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8353 vty_out(vty, "h");
9b6d8fcf 8354 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8355 vty_out(vty, "d");
9b6d8fcf 8356 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8357 vty_out(vty, ">");
9b6d8fcf 8358 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8359 vty_out(vty, "=");
8360 else
8361 vty_out(vty, " ");
718e3744 8362
d62a17ae 8363 /* Internal route. */
9b6d8fcf
DS
8364 if (path->peer && (path->peer->as)
8365 && (path->peer->as == path->peer->local_as))
d62a17ae 8366 vty_out(vty, "i");
8367 else
8368 vty_out(vty, " ");
b40d939b 8369}
8370
2ba93fd6
DA
8371static char *bgp_nexthop_hostname(struct peer *peer,
8372 struct bgp_nexthop_cache *bnc)
25b5da8d 8373{
892fedb6 8374 if (peer->hostname
aef999a2 8375 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8376 return peer->hostname;
8377 return NULL;
8378}
8379
b40d939b 8380/* called from terminal list command */
bd494ec5 8381void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8382 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8383 json_object *json_paths, bool wide)
d62a17ae 8384{
aef999a2 8385 int len;
515c2602 8386 struct attr *attr = path->attr;
d62a17ae 8387 json_object *json_path = NULL;
8388 json_object *json_nexthops = NULL;
8389 json_object *json_nexthop_global = NULL;
8390 json_object *json_nexthop_ll = NULL;
6f214dd3 8391 json_object *json_ext_community = NULL;
9df8b37c 8392 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8393 bool nexthop_self =
9b6d8fcf 8394 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8395 bool nexthop_othervrf = false;
43089216 8396 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8397 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8398 char *nexthop_hostname =
8399 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8400 char esi_buf[ESI_STR_LEN];
d62a17ae 8401
8402 if (json_paths)
8403 json_path = json_object_new_object();
8404
8405 /* short status lead text */
9b6d8fcf 8406 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8407
8408 if (!json_paths) {
8409 /* print prefix and mask */
8410 if (!display)
ae248832 8411 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8412 else
ae248832 8413 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8414 } else {
ae248832 8415 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8416 }
47fc97cc 8417
9df8b37c
PZ
8418 /*
8419 * If vrf id of nexthop is different from that of prefix,
8420 * set up printable string to append
8421 */
9b6d8fcf 8422 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8423 const char *self = "";
8424
8425 if (nexthop_self)
8426 self = "<";
8427
8428 nexthop_othervrf = true;
9b6d8fcf 8429 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8430
9b6d8fcf 8431 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8432 snprintf(vrf_id_str, sizeof(vrf_id_str),
8433 "@%s%s", VRFID_NONE_STR, self);
8434 else
8435 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8436 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8437
9b6d8fcf
DS
8438 if (path->extra->bgp_orig->inst_type
8439 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8440
9b6d8fcf 8441 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8442 } else {
8443 const char *self = "";
8444
8445 if (nexthop_self)
8446 self = "<";
8447
8448 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8449 }
8450
445c2480
DS
8451 /*
8452 * For ENCAP and EVPN routes, nexthop address family is not
8453 * neccessarily the same as the prefix address family.
8454 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8455 * EVPN routes are also exchanged with a MP nexthop. Currently,
8456 * this
8457 * is only IPv4, the value will be present in either
8458 * attr->nexthop or
8459 * attr->mp_nexthop_global_in
8460 */
8461 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8462 char buf[BUFSIZ];
8463 char nexthop[128];
8464 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8465
8466 switch (af) {
8467 case AF_INET:
772270f3
QY
8468 snprintf(nexthop, sizeof(nexthop), "%s",
8469 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8470 BUFSIZ));
445c2480
DS
8471 break;
8472 case AF_INET6:
772270f3
QY
8473 snprintf(nexthop, sizeof(nexthop), "%s",
8474 inet_ntop(af, &attr->mp_nexthop_global, buf,
8475 BUFSIZ));
445c2480
DS
8476 break;
8477 default:
772270f3 8478 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8479 break;
d62a17ae 8480 }
d62a17ae 8481
445c2480
DS
8482 if (json_paths) {
8483 json_nexthop_global = json_object_new_object();
8484
515c2602
DA
8485 json_object_string_add(json_nexthop_global, "ip",
8486 nexthop);
8487
939a97f4 8488 if (path->peer->hostname)
515c2602
DA
8489 json_object_string_add(json_nexthop_global,
8490 "hostname",
939a97f4 8491 path->peer->hostname);
515c2602
DA
8492
8493 json_object_string_add(json_nexthop_global, "afi",
8494 (af == AF_INET) ? "ipv4"
8495 : "ipv6");
445c2480
DS
8496 json_object_boolean_true_add(json_nexthop_global,
8497 "used");
aef999a2
DA
8498 } else {
8499 if (nexthop_hostname)
8500 len = vty_out(vty, "%s(%s)%s", nexthop,
8501 nexthop_hostname, vrf_id_str);
8502 else
8503 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8504
ae248832 8505 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8506 if (len < 1)
8507 vty_out(vty, "\n%*s", 36, " ");
8508 else
8509 vty_out(vty, "%*s", len, " ");
8510 }
445c2480
DS
8511 } else if (safi == SAFI_EVPN) {
8512 if (json_paths) {
23d0a753
DA
8513 char buf[BUFSIZ] = {0};
8514
445c2480
DS
8515 json_nexthop_global = json_object_new_object();
8516
515c2602 8517 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8518 inet_ntop(AF_INET,
8519 &attr->nexthop, buf,
8520 sizeof(buf)));
515c2602 8521
939a97f4 8522 if (path->peer->hostname)
515c2602
DA
8523 json_object_string_add(json_nexthop_global,
8524 "hostname",
939a97f4 8525 path->peer->hostname);
515c2602 8526
a4d82a8a
PZ
8527 json_object_string_add(json_nexthop_global, "afi",
8528 "ipv4");
445c2480
DS
8529 json_object_boolean_true_add(json_nexthop_global,
8530 "used");
aef999a2
DA
8531 } else {
8532 if (nexthop_hostname)
8533 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8534 nexthop_hostname, vrf_id_str);
8535 else
8536 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8537 vrf_id_str);
8538
ae248832 8539 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8540 if (len < 1)
8541 vty_out(vty, "\n%*s", 36, " ");
8542 else
8543 vty_out(vty, "%*s", len, " ");
8544 }
d33fc23b 8545 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8546 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8547 if (json_paths) {
23d0a753
DA
8548 char buf[BUFSIZ] = {0};
8549
026b914a 8550 json_nexthop_global = json_object_new_object();
515c2602 8551
026b914a
PG
8552 json_object_string_add(json_nexthop_global,
8553 "afi", "ipv4");
515c2602
DA
8554 json_object_string_add(
8555 json_nexthop_global, "ip",
23d0a753
DA
8556 inet_ntop(AF_INET, &attr->nexthop, buf,
8557 sizeof(buf)));
515c2602 8558
939a97f4 8559 if (path->peer->hostname)
515c2602
DA
8560 json_object_string_add(
8561 json_nexthop_global, "hostname",
939a97f4 8562 path->peer->hostname);
515c2602 8563
50e05855
AD
8564 json_object_boolean_true_add(
8565 json_nexthop_global,
026b914a
PG
8566 "used");
8567 } else {
aef999a2
DA
8568 if (nexthop_hostname)
8569 len = vty_out(vty, "%pI4(%s)%s",
8570 &attr->nexthop,
8571 nexthop_hostname,
8572 vrf_id_str);
8573 else
8574 len = vty_out(vty, "%pI4%s",
8575 &attr->nexthop,
8576 vrf_id_str);
8577
ae248832 8578 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8579 if (len < 1)
8580 vty_out(vty, "\n%*s", 36, " ");
8581 else
8582 vty_out(vty, "%*s", len, " ");
026b914a
PG
8583 }
8584 }
d33fc23b 8585 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8586 if (json_paths) {
23d0a753
DA
8587 char buf[BUFSIZ] = {0};
8588
445c2480 8589 json_nexthop_global = json_object_new_object();
d62a17ae 8590
515c2602 8591 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8592 inet_ntop(AF_INET,
8593 &attr->nexthop, buf,
8594 sizeof(buf)));
515c2602 8595
939a97f4 8596 if (path->peer->hostname)
515c2602
DA
8597 json_object_string_add(json_nexthop_global,
8598 "hostname",
939a97f4 8599 path->peer->hostname);
445c2480 8600
a4d82a8a
PZ
8601 json_object_string_add(json_nexthop_global, "afi",
8602 "ipv4");
445c2480
DS
8603 json_object_boolean_true_add(json_nexthop_global,
8604 "used");
8605 } else {
aef999a2
DA
8606 if (nexthop_hostname)
8607 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8608 nexthop_hostname, vrf_id_str);
8609 else
8610 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8611 vrf_id_str);
9df8b37c 8612
ae248832 8613 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8614 if (len < 1)
8615 vty_out(vty, "\n%*s", 36, " ");
8616 else
8617 vty_out(vty, "%*s", len, " ");
d62a17ae 8618 }
445c2480 8619 }
b05a1c8b 8620
445c2480 8621 /* IPv6 Next Hop */
a4d82a8a 8622 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8623 char buf[BUFSIZ];
d62a17ae 8624
445c2480
DS
8625 if (json_paths) {
8626 json_nexthop_global = json_object_new_object();
a4d82a8a 8627 json_object_string_add(
515c2602
DA
8628 json_nexthop_global, "ip",
8629 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8630 buf, BUFSIZ));
8631
939a97f4 8632 if (path->peer->hostname)
515c2602
DA
8633 json_object_string_add(json_nexthop_global,
8634 "hostname",
939a97f4 8635 path->peer->hostname);
515c2602 8636
a4d82a8a
PZ
8637 json_object_string_add(json_nexthop_global, "afi",
8638 "ipv6");
8639 json_object_string_add(json_nexthop_global, "scope",
8640 "global");
445c2480
DS
8641
8642 /* We display both LL & GL if both have been
8643 * received */
0606039c
DA
8644 if ((attr->mp_nexthop_len
8645 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8646 || (path->peer->conf_if)) {
a4d82a8a 8647 json_nexthop_ll = json_object_new_object();
d62a17ae 8648 json_object_string_add(
515c2602
DA
8649 json_nexthop_ll, "ip",
8650 inet_ntop(AF_INET6,
8651 &attr->mp_nexthop_local, buf,
8652 BUFSIZ));
8653
939a97f4 8654 if (path->peer->hostname)
515c2602
DA
8655 json_object_string_add(
8656 json_nexthop_ll, "hostname",
939a97f4 8657 path->peer->hostname);
515c2602 8658
a4d82a8a
PZ
8659 json_object_string_add(json_nexthop_ll, "afi",
8660 "ipv6");
8661 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8662 "link-local");
d62a17ae 8663
a4d82a8a
PZ
8664 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8665 &attr->mp_nexthop_local)
445c2480
DS
8666 != 0)
8667 && !attr->mp_nexthop_prefer_global)
d62a17ae 8668 json_object_boolean_true_add(
a4d82a8a 8669 json_nexthop_ll, "used");
445c2480
DS
8670 else
8671 json_object_boolean_true_add(
a4d82a8a 8672 json_nexthop_global, "used");
445c2480
DS
8673 } else
8674 json_object_boolean_true_add(
8675 json_nexthop_global, "used");
8676 } else {
8677 /* Display LL if LL/Global both in table unless
8678 * prefer-global is set */
0606039c
DA
8679 if (((attr->mp_nexthop_len
8680 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8681 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8682 || (path->peer->conf_if)) {
8683 if (path->peer->conf_if) {
a4d82a8a 8684 len = vty_out(vty, "%s",
9b6d8fcf 8685 path->peer->conf_if);
ae248832
MK
8686 /* len of IPv6 addr + max len of def
8687 * ifname */
8688 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8689
8690 if (len < 1)
a4d82a8a 8691 vty_out(vty, "\n%*s", 36, " ");
445c2480 8692 else
a4d82a8a 8693 vty_out(vty, "%*s", len, " ");
d62a17ae 8694 } else {
aef999a2
DA
8695 if (nexthop_hostname)
8696 len = vty_out(
8697 vty, "%pI6(%s)%s",
8698 &attr->mp_nexthop_local,
8699 nexthop_hostname,
8700 vrf_id_str);
8701 else
8702 len = vty_out(
8703 vty, "%pI6%s",
8704 &attr->mp_nexthop_local,
8705 vrf_id_str);
8706
ae248832 8707 len = wide ? (41 - len) : (16 - len);
d62a17ae 8708
8709 if (len < 1)
a4d82a8a 8710 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8711 else
a4d82a8a 8712 vty_out(vty, "%*s", len, " ");
d62a17ae 8713 }
445c2480 8714 } else {
aef999a2
DA
8715 if (nexthop_hostname)
8716 len = vty_out(vty, "%pI6(%s)%s",
8717 &attr->mp_nexthop_global,
8718 nexthop_hostname,
8719 vrf_id_str);
8720 else
8721 len = vty_out(vty, "%pI6%s",
8722 &attr->mp_nexthop_global,
8723 vrf_id_str);
8724
ae248832 8725 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8726
8727 if (len < 1)
8728 vty_out(vty, "\n%*s", 36, " ");
8729 else
8730 vty_out(vty, "%*s", len, " ");
d62a17ae 8731 }
8732 }
445c2480 8733 }
718e3744 8734
445c2480
DS
8735 /* MED/Metric */
8736 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8737 if (json_paths)
50e05855 8738 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8739 else if (wide)
8740 vty_out(vty, "%7u", attr->med);
0fbac0b4 8741 else
445c2480 8742 vty_out(vty, "%10u", attr->med);
ae248832
MK
8743 else if (!json_paths) {
8744 if (wide)
8745 vty_out(vty, "%*s", 7, " ");
8746 else
8747 vty_out(vty, "%*s", 10, " ");
8748 }
d62a17ae 8749
445c2480
DS
8750 /* Local Pref */
8751 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8752 if (json_paths)
50e05855 8753 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8754 attr->local_pref);
8755 else
445c2480
DS
8756 vty_out(vty, "%7u", attr->local_pref);
8757 else if (!json_paths)
8758 vty_out(vty, " ");
d62a17ae 8759
445c2480
DS
8760 if (json_paths)
8761 json_object_int_add(json_path, "weight", attr->weight);
8762 else
8763 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8764
445c2480
DS
8765 if (json_paths) {
8766 char buf[BUFSIZ];
a4d82a8a
PZ
8767 json_object_string_add(
8768 json_path, "peerId",
9b6d8fcf 8769 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8770 }
b05a1c8b 8771
445c2480
DS
8772 /* Print aspath */
8773 if (attr->aspath) {
0fbac0b4 8774 if (json_paths)
50e05855 8775 json_object_string_add(json_path, "path",
0fbac0b4
DA
8776 attr->aspath->str);
8777 else
445c2480 8778 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8779 }
f1aa5d8a 8780
445c2480
DS
8781 /* Print origin */
8782 if (json_paths)
a4d82a8a
PZ
8783 json_object_string_add(json_path, "origin",
8784 bgp_origin_long_str[attr->origin]);
445c2480
DS
8785 else
8786 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8787
9df8b37c 8788 if (json_paths) {
d071f237 8789 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8790 json_object_string_add(json_path, "esi",
8791 esi_to_str(&attr->esi,
8792 esi_buf, sizeof(esi_buf)));
8793 }
6f214dd3
CS
8794 if (safi == SAFI_EVPN &&
8795 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8796 json_ext_community = json_object_new_object();
8797 json_object_string_add(json_ext_community,
8798 "string",
8799 attr->ecommunity->str);
8800 json_object_object_add(json_path,
8801 "extendedCommunity",
8802 json_ext_community);
8803 }
8804
9df8b37c
PZ
8805 if (nexthop_self)
8806 json_object_boolean_true_add(json_path,
8807 "announceNexthopSelf");
8808 if (nexthop_othervrf) {
8809 json_object_string_add(json_path, "nhVrfName",
8810 nexthop_vrfname);
8811
8812 json_object_int_add(json_path, "nhVrfId",
8813 ((nexthop_vrfid == VRF_UNKNOWN)
8814 ? -1
8815 : (int)nexthop_vrfid));
8816 }
8817 }
8818
d62a17ae 8819 if (json_paths) {
8820 if (json_nexthop_global || json_nexthop_ll) {
8821 json_nexthops = json_object_new_array();
f1aa5d8a 8822
d62a17ae 8823 if (json_nexthop_global)
8824 json_object_array_add(json_nexthops,
8825 json_nexthop_global);
f1aa5d8a 8826
d62a17ae 8827 if (json_nexthop_ll)
8828 json_object_array_add(json_nexthops,
8829 json_nexthop_ll);
f1aa5d8a 8830
d62a17ae 8831 json_object_object_add(json_path, "nexthops",
8832 json_nexthops);
8833 }
8834
8835 json_object_array_add(json_paths, json_path);
8836 } else {
8837 vty_out(vty, "\n");
6f214dd3 8838
b5e140c8 8839 if (safi == SAFI_EVPN) {
229587fb
AK
8840 struct bgp_path_es_info *path_es_info = NULL;
8841
8842 if (path->extra)
8843 path_es_info = path->extra->es_info;
8844
d071f237 8845 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8846 /* XXX - add these params to the json out */
b5e140c8 8847 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8848 vty_out(vty, "ESI:%s",
8849 esi_to_str(&attr->esi, esi_buf,
8850 sizeof(esi_buf)));
8851 if (path_es_info && path_es_info->es)
8852 vty_out(vty, " VNI: %u",
8853 path_es_info->vni);
8854 vty_out(vty, "\n");
b5e140c8
AK
8855 }
8856 if (attr->flag &
8857 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8858 vty_out(vty, "%*s", 20, " ");
8859 vty_out(vty, "%s\n", attr->ecommunity->str);
8860 }
6f214dd3
CS
8861 }
8862
49e5a4a0 8863#ifdef ENABLE_BGP_VNC
d62a17ae 8864 /* prints an additional line, indented, with VNC info, if
8865 * present */
8866 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8867 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8868#endif
d62a17ae 8869 }
8870}
718e3744 8871
8872/* called from terminal list command */
5f040085
DS
8873void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8874 struct attr *attr, safi_t safi, bool use_json,
ae248832 8875 json_object *json_ar, bool wide)
d62a17ae 8876{
8877 json_object *json_status = NULL;
8878 json_object *json_net = NULL;
aef999a2 8879 int len;
d62a17ae 8880 char buff[BUFSIZ];
dc387b0f 8881
d62a17ae 8882 /* Route status display. */
8883 if (use_json) {
8884 json_status = json_object_new_object();
8885 json_net = json_object_new_object();
8886 } else {
8887 vty_out(vty, "*");
8888 vty_out(vty, ">");
8889 vty_out(vty, " ");
8890 }
718e3744 8891
d62a17ae 8892 /* print prefix and mask */
50e05855 8893 if (use_json) {
dc387b0f
LK
8894 if (safi == SAFI_EVPN)
8895 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8896 else if (p->family == AF_INET || p->family == AF_INET6) {
8897 json_object_string_add(
8898 json_net, "addrPrefix",
8899 inet_ntop(p->family, &p->u.prefix, buff,
8900 BUFSIZ));
8901 json_object_int_add(json_net, "prefixLen",
8902 p->prefixlen);
8903 prefix2str(p, buff, PREFIX_STRLEN);
8904 json_object_string_add(json_net, "network", buff);
8905 }
50e05855 8906 } else
ae248832 8907 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8908
8909 /* Print attribute */
8910 if (attr) {
8911 if (use_json) {
23d0a753
DA
8912 char buf[BUFSIZ] = {0};
8913
d62a17ae 8914 if (p->family == AF_INET
8915 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8916 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8917 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8918 json_object_string_add(
8919 json_net, "nextHop",
23d0a753
DA
8920 inet_ntop(
8921 AF_INET,
8922 &attr->mp_nexthop_global_in,
8923 buf, sizeof(buf)));
d62a17ae 8924 else
8925 json_object_string_add(
8926 json_net, "nextHop",
23d0a753
DA
8927 inet_ntop(AF_INET,
8928 &attr->nexthop, buf,
8929 sizeof(buf)));
d62a17ae 8930 } else if (p->family == AF_INET6
8931 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8932 char buf[BUFSIZ];
8933
8934 json_object_string_add(
aa0a10fc 8935 json_net, "nextHopGlobal",
d62a17ae 8936 inet_ntop(AF_INET6,
8937 &attr->mp_nexthop_global, buf,
8938 BUFSIZ));
23d0a753
DA
8939 } else if (p->family == AF_EVPN
8940 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8941 char buf[BUFSIZ] = {0};
8942
8943 json_object_string_add(
8944 json_net, "nextHop",
8945 inet_ntop(AF_INET,
8946 &attr->mp_nexthop_global_in,
8947 buf, sizeof(buf)));
8948 }
d62a17ae 8949
8950 if (attr->flag
8951 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8952 json_object_int_add(json_net, "metric",
8953 attr->med);
8954
0fbac0b4 8955 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8956 json_object_int_add(json_net, "locPrf",
0fbac0b4 8957 attr->local_pref);
d62a17ae 8958
8959 json_object_int_add(json_net, "weight", attr->weight);
8960
8961 /* Print aspath */
0fbac0b4 8962 if (attr->aspath)
50e05855 8963 json_object_string_add(json_net, "path",
0fbac0b4 8964 attr->aspath->str);
d62a17ae 8965
8966 /* Print origin */
8967 json_object_string_add(json_net, "bgpOriginCode",
8968 bgp_origin_str[attr->origin]);
8969 } else {
8970 if (p->family == AF_INET
8971 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8972 || safi == SAFI_EVPN
8973 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8974 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8975 || safi == SAFI_EVPN)
23d0a753
DA
8976 vty_out(vty, "%-16pI4",
8977 &attr->mp_nexthop_global_in);
ae248832 8978 else if (wide)
23d0a753 8979 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8980 else
23d0a753 8981 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8982 } else if (p->family == AF_INET6
8983 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8984 char buf[BUFSIZ];
8985
8986 len = vty_out(
8987 vty, "%s",
8988 inet_ntop(AF_INET6,
8989 &attr->mp_nexthop_global, buf,
8990 BUFSIZ));
ae248832 8991 len = wide ? (41 - len) : (16 - len);
d62a17ae 8992 if (len < 1)
8993 vty_out(vty, "\n%*s", 36, " ");
8994 else
8995 vty_out(vty, "%*s", len, " ");
8996 }
8997 if (attr->flag
8998 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8999 if (wide)
9000 vty_out(vty, "%7u", attr->med);
9001 else
9002 vty_out(vty, "%10u", attr->med);
9003 else if (wide)
9004 vty_out(vty, " ");
d62a17ae 9005 else
9006 vty_out(vty, " ");
718e3744 9007
d62a17ae 9008 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9009 vty_out(vty, "%7u", attr->local_pref);
9010 else
9011 vty_out(vty, " ");
9012
9013 vty_out(vty, "%7u ", attr->weight);
9014
9015 /* Print aspath */
9016 if (attr->aspath)
9017 aspath_print_vty(vty, "%s", attr->aspath, " ");
9018
9019 /* Print origin */
9020 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9021 }
9022 }
9023 if (use_json) {
9024 json_object_boolean_true_add(json_status, "*");
9025 json_object_boolean_true_add(json_status, ">");
9026 json_object_object_add(json_net, "appliedStatusSymbols",
9027 json_status);
1608ff77 9028
dc387b0f
LK
9029 prefix2str(p, buff, PREFIX_STRLEN);
9030 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9031 } else
9032 vty_out(vty, "\n");
9033}
9034
bd494ec5 9035void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9036 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9037 json_object *json)
9038{
9039 json_object *json_out = NULL;
9040 struct attr *attr;
9041 mpls_label_t label = MPLS_INVALID_LABEL;
9042
9b6d8fcf 9043 if (!path->extra)
d62a17ae 9044 return;
9045
9046 if (json)
9047 json_out = json_object_new_object();
9048
9049 /* short status lead text */
9b6d8fcf 9050 route_vty_short_status_out(vty, path, json_out);
d62a17ae 9051
9052 /* print prefix and mask */
9053 if (json == NULL) {
9054 if (!display)
ae248832 9055 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9056 else
9057 vty_out(vty, "%*s", 17, " ");
9058 }
9059
9060 /* Print attribute */
9b6d8fcf 9061 attr = path->attr;
05864da7
DS
9062 if (((p->family == AF_INET)
9063 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9064 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9065 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9066 char buf[BUFSIZ] = {0};
9067
05864da7
DS
9068 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9069 || safi == SAFI_EVPN) {
9070 if (json)
9071 json_object_string_add(
9072 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9073 inet_ntop(AF_INET,
9074 &attr->mp_nexthop_global_in,
9075 buf, sizeof(buf)));
05864da7 9076 else
23d0a753
DA
9077 vty_out(vty, "%-16pI4",
9078 &attr->mp_nexthop_global_in);
05864da7
DS
9079 } else {
9080 if (json)
9081 json_object_string_add(
9082 json_out, "nexthop",
23d0a753
DA
9083 inet_ntop(AF_INET, &attr->nexthop, buf,
9084 sizeof(buf)));
05864da7 9085 else
23d0a753 9086 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9087 }
9088 } else if (((p->family == AF_INET6)
9089 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9090 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9091 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9092 char buf_a[512];
9093
9094 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9095 if (json)
9096 json_object_string_add(
9097 json_out, "mpNexthopGlobalIn",
9098 inet_ntop(AF_INET6,
9099 &attr->mp_nexthop_global,
9100 buf_a, sizeof(buf_a)));
9101 else
9102 vty_out(vty, "%s",
9103 inet_ntop(AF_INET6,
9104 &attr->mp_nexthop_global,
9105 buf_a, sizeof(buf_a)));
9106 } else if (attr->mp_nexthop_len
9107 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9108 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9109 &attr->mp_nexthop_global,
9110 &attr->mp_nexthop_local);
9111 if (json)
9112 json_object_string_add(json_out,
9113 "mpNexthopGlobalLocal",
9114 buf_a);
9115 else
9116 vty_out(vty, "%s", buf_a);
d62a17ae 9117 }
9118 }
9119
9b6d8fcf 9120 label = decode_label(&path->extra->label[0]);
d62a17ae 9121
9122 if (bgp_is_valid_label(&label)) {
9123 if (json) {
9124 json_object_int_add(json_out, "notag", label);
9125 json_object_array_add(json, json_out);
9126 } else {
9127 vty_out(vty, "notag/%d", label);
9128 vty_out(vty, "\n");
9129 }
9130 }
9131}
718e3744 9132
bd494ec5 9133void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9134 struct bgp_path_info *path, int display,
d62a17ae 9135 json_object *json_paths)
718e3744 9136{
d62a17ae 9137 struct attr *attr;
14f51eba 9138 char buf[BUFSIZ] = {0};
d62a17ae 9139 json_object *json_path = NULL;
14f51eba
LK
9140 json_object *json_nexthop = NULL;
9141 json_object *json_overlay = NULL;
856ca177 9142
9b6d8fcf 9143 if (!path->extra)
d62a17ae 9144 return;
718e3744 9145
14f51eba
LK
9146 if (json_paths) {
9147 json_path = json_object_new_object();
9148 json_overlay = json_object_new_object();
9149 json_nexthop = json_object_new_object();
9150 }
9151
d62a17ae 9152 /* short status lead text */
9b6d8fcf 9153 route_vty_short_status_out(vty, path, json_path);
856ca177 9154
d62a17ae 9155 /* print prefix and mask */
9156 if (!display)
ae248832 9157 route_vty_out_route(p, vty, json_path, false);
d62a17ae 9158 else
9159 vty_out(vty, "%*s", 17, " ");
9160
9161 /* Print attribute */
9b6d8fcf 9162 attr = path->attr;
05864da7
DS
9163 char buf1[BUFSIZ];
9164 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9165
05864da7
DS
9166 switch (af) {
9167 case AF_INET:
9168 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9169 if (!json_path) {
9170 vty_out(vty, "%-16s", buf);
9171 } else {
9172 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9173
05864da7 9174 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9175
05864da7
DS
9176 json_object_object_add(json_path, "nexthop",
9177 json_nexthop);
9178 }
9179 break;
9180 case AF_INET6:
9181 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9182 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9183 if (!json_path) {
9184 vty_out(vty, "%s(%s)", buf, buf1);
9185 } else {
9186 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9187
05864da7
DS
9188 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9189 buf1);
14f51eba 9190
05864da7 9191 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9192
05864da7
DS
9193 json_object_object_add(json_path, "nexthop",
9194 json_nexthop);
9195 }
9196 break;
9197 default:
9198 if (!json_path) {
9199 vty_out(vty, "?");
9200 } else {
9201 json_object_string_add(json_nexthop, "Error",
9202 "Unsupported address-family");
d62a17ae 9203 }
05864da7 9204 }
988258b4 9205
6c924775
DS
9206 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9207
9208 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9209 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9210 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9211 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9212
05864da7
DS
9213 if (!json_path)
9214 vty_out(vty, "/%s", buf);
9215 else
9216 json_object_string_add(json_overlay, "gw", buf);
9217
9218 if (attr->ecommunity) {
9219 char *mac = NULL;
9220 struct ecommunity_val *routermac = ecommunity_lookup(
9221 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9222 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9223
9224 if (routermac)
9225 mac = ecom_mac2str((char *)routermac->val);
9226 if (mac) {
9227 if (!json_path) {
c4efd0f4 9228 vty_out(vty, "/%s", mac);
05864da7
DS
9229 } else {
9230 json_object_string_add(json_overlay, "rmac",
9231 mac);
988258b4 9232 }
05864da7 9233 XFREE(MTYPE_TMP, mac);
988258b4 9234 }
05864da7 9235 }
718e3744 9236
05864da7
DS
9237 if (!json_path) {
9238 vty_out(vty, "\n");
9239 } else {
9240 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9241
05864da7 9242 json_object_array_add(json_paths, json_path);
14f51eba 9243 }
d62a17ae 9244}
718e3744 9245
d62a17ae 9246/* dampening route */
5f040085
DS
9247static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9248 struct bgp_path_info *path, int display,
9249 afi_t afi, safi_t safi, bool use_json,
9250 json_object *json)
d62a17ae 9251{
9252 struct attr *attr;
9253 int len;
9254 char timebuf[BGP_UPTIME_LEN];
9255
9256 /* short status lead text */
9b6d8fcf 9257 route_vty_short_status_out(vty, path, json);
d62a17ae 9258
9259 /* print prefix and mask */
9260 if (!use_json) {
9261 if (!display)
ae248832 9262 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9263 else
9264 vty_out(vty, "%*s", 17, " ");
9265 }
9266
9b6d8fcf 9267 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9268 len = 17 - len;
9269 if (len < 1) {
9270 if (!use_json)
9271 vty_out(vty, "\n%*s", 34, " ");
9272 } else {
9273 if (use_json)
9274 json_object_int_add(json, "peerHost", len);
9275 else
9276 vty_out(vty, "%*s", len, " ");
9277 }
9278
9279 if (use_json)
a935f597
DA
9280 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9281 safi, use_json, json);
d62a17ae 9282 else
9b6d8fcf
DS
9283 vty_out(vty, "%s ",
9284 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9285 BGP_UPTIME_LEN, afi, safi,
9286 use_json, json));
d62a17ae 9287
9288 /* Print attribute */
9b6d8fcf 9289 attr = path->attr;
d62a17ae 9290
05864da7
DS
9291 /* Print aspath */
9292 if (attr->aspath) {
d62a17ae 9293 if (use_json)
05864da7
DS
9294 json_object_string_add(json, "asPath",
9295 attr->aspath->str);
d62a17ae 9296 else
05864da7 9297 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9298 }
05864da7
DS
9299
9300 /* Print origin */
9301 if (use_json)
9302 json_object_string_add(json, "origin",
9303 bgp_origin_str[attr->origin]);
9304 else
9305 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9306
d62a17ae 9307 if (!use_json)
9308 vty_out(vty, "\n");
9309}
718e3744 9310
d62a17ae 9311/* flap route */
5f040085
DS
9312static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9313 struct bgp_path_info *path, int display,
9314 afi_t afi, safi_t safi, bool use_json,
9315 json_object *json)
784d3a42 9316{
d62a17ae 9317 struct attr *attr;
9318 struct bgp_damp_info *bdi;
9319 char timebuf[BGP_UPTIME_LEN];
9320 int len;
784d3a42 9321
9b6d8fcf 9322 if (!path->extra)
d62a17ae 9323 return;
784d3a42 9324
9b6d8fcf 9325 bdi = path->extra->damp_info;
784d3a42 9326
d62a17ae 9327 /* short status lead text */
9b6d8fcf 9328 route_vty_short_status_out(vty, path, json);
784d3a42 9329
d62a17ae 9330 /* print prefix and mask */
9331 if (!use_json) {
9332 if (!display)
ae248832 9333 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9334 else
9335 vty_out(vty, "%*s", 17, " ");
9336 }
784d3a42 9337
9b6d8fcf 9338 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9339 len = 16 - len;
9340 if (len < 1) {
9341 if (!use_json)
9342 vty_out(vty, "\n%*s", 33, " ");
9343 } else {
9344 if (use_json)
9345 json_object_int_add(json, "peerHost", len);
9346 else
9347 vty_out(vty, "%*s", len, " ");
9348 }
784d3a42 9349
d62a17ae 9350 len = vty_out(vty, "%d", bdi->flap);
9351 len = 5 - len;
9352 if (len < 1) {
9353 if (!use_json)
9354 vty_out(vty, " ");
9355 } else {
9356 if (use_json)
9357 json_object_int_add(json, "bdiFlap", len);
9358 else
9359 vty_out(vty, "%*s", len, " ");
9360 }
9361
9362 if (use_json)
9363 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9364 json);
9365 else
996c9314
LB
9366 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9367 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9368
9b6d8fcf
DS
9369 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9370 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9371 if (use_json)
9b6d8fcf 9372 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9373 BGP_UPTIME_LEN, afi, safi,
9374 use_json, json);
d62a17ae 9375 else
9376 vty_out(vty, "%s ",
9b6d8fcf 9377 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9378 BGP_UPTIME_LEN, afi,
9379 safi, use_json, json));
d62a17ae 9380 } else {
9381 if (!use_json)
9382 vty_out(vty, "%*s ", 8, " ");
9383 }
9384
9385 /* Print attribute */
9b6d8fcf 9386 attr = path->attr;
d62a17ae 9387
05864da7
DS
9388 /* Print aspath */
9389 if (attr->aspath) {
d62a17ae 9390 if (use_json)
05864da7
DS
9391 json_object_string_add(json, "asPath",
9392 attr->aspath->str);
d62a17ae 9393 else
05864da7 9394 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9395 }
05864da7
DS
9396
9397 /* Print origin */
9398 if (use_json)
9399 json_object_string_add(json, "origin",
9400 bgp_origin_str[attr->origin]);
9401 else
9402 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9403
d62a17ae 9404 if (!use_json)
9405 vty_out(vty, "\n");
9406}
9407
9408static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9409 int *first, const char *header,
9410 json_object *json_adv_to)
9411{
9412 char buf1[INET6_ADDRSTRLEN];
9413 json_object *json_peer = NULL;
9414
9415 if (json_adv_to) {
9416 /* 'advertised-to' is a dictionary of peers we have advertised
9417 * this
9418 * prefix too. The key is the peer's IP or swpX, the value is
9419 * the
9420 * hostname if we know it and "" if not.
9421 */
9422 json_peer = json_object_new_object();
9423
9424 if (peer->hostname)
9425 json_object_string_add(json_peer, "hostname",
9426 peer->hostname);
9427
9428 if (peer->conf_if)
9429 json_object_object_add(json_adv_to, peer->conf_if,
9430 json_peer);
9431 else
9432 json_object_object_add(
9433 json_adv_to,
9434 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9435 json_peer);
9436 } else {
9437 if (*first) {
9438 vty_out(vty, "%s", header);
9439 *first = 0;
9440 }
9441
9442 if (peer->hostname
892fedb6 9443 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9444 if (peer->conf_if)
9445 vty_out(vty, " %s(%s)", peer->hostname,
9446 peer->conf_if);
9447 else
9448 vty_out(vty, " %s(%s)", peer->hostname,
9449 sockunion2str(&peer->su, buf1,
9450 SU_ADDRSTRLEN));
9451 } else {
9452 if (peer->conf_if)
9453 vty_out(vty, " %s", peer->conf_if);
9454 else
9455 vty_out(vty, " %s",
9456 sockunion2str(&peer->su, buf1,
9457 SU_ADDRSTRLEN));
9458 }
9459 }
784d3a42
PG
9460}
9461
dcc68b5e
MS
9462static void route_vty_out_tx_ids(struct vty *vty,
9463 struct bgp_addpath_info_data *d)
9464{
9465 int i;
9466
9467 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9468 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9469 d->addpath_tx_id[i],
9470 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9471 }
9472}
9473
5e4d4c8a 9474static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9475 struct bgp_path_info *pi,
9476 struct attr *attr,
9477 json_object *json_path)
5e4d4c8a
AK
9478{
9479 char esi_buf[ESI_STR_LEN];
9480 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9481 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9482 ATTR_ES_PEER_ROUTER);
9483 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9484 ATTR_ES_PEER_ACTIVE);
9485 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9486 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9487 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9488 if (json_path) {
9489 json_object *json_es_info = NULL;
9490
9491 json_object_string_add(
9492 json_path, "esi",
9493 esi_buf);
9494 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9495 json_es_info = json_object_new_object();
9496 if (es_local)
9497 json_object_boolean_true_add(
9498 json_es_info, "localEs");
9499 if (peer_active)
9500 json_object_boolean_true_add(
9501 json_es_info, "peerActive");
9502 if (peer_proxy)
9503 json_object_boolean_true_add(
9504 json_es_info, "peerProxy");
9505 if (peer_router)
9506 json_object_boolean_true_add(
9507 json_es_info, "peerRouter");
9508 if (attr->mm_sync_seqnum)
9509 json_object_int_add(
9510 json_es_info, "peerSeq",
9511 attr->mm_sync_seqnum);
9512 json_object_object_add(
9513 json_path, "es_info",
9514 json_es_info);
9515 }
9516 } else {
9517 if (bgp_evpn_attr_is_sync(attr))
9518 vty_out(vty,
9519 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9520 esi_buf,
9521 es_local ? "local-es":"",
9522 peer_proxy ? "proxy " : "",
9523 peer_active ? "active ":"",
9524 peer_router ? "router ":"",
9525 attr->mm_sync_seqnum);
9526 else
9527 vty_out(vty, " ESI %s %s\n",
9528 esi_buf,
9529 es_local ? "local-es":"");
9530 }
9531}
9532
9533void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9534 struct bgp_dest *bn, struct bgp_path_info *path,
9535 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9536{
9537 char buf[INET6_ADDRSTRLEN];
9538 char buf1[BUFSIZ];
515c2602 9539 struct attr *attr = path->attr;
d62a17ae 9540 int sockunion_vty_out(struct vty *, union sockunion *);
9541 time_t tbuf;
9542 json_object *json_bestpath = NULL;
9543 json_object *json_cluster_list = NULL;
9544 json_object *json_cluster_list_list = NULL;
9545 json_object *json_ext_community = NULL;
9546 json_object *json_last_update = NULL;
7fd077aa 9547 json_object *json_pmsi = NULL;
d62a17ae 9548 json_object *json_nexthop_global = NULL;
9549 json_object *json_nexthop_ll = NULL;
9550 json_object *json_nexthops = NULL;
9551 json_object *json_path = NULL;
9552 json_object *json_peer = NULL;
9553 json_object *json_string = NULL;
9554 json_object *json_adv_to = NULL;
9555 int first = 0;
9556 struct listnode *node, *nnode;
9557 struct peer *peer;
9558 int addpath_capable;
9559 int has_adj;
9560 unsigned int first_as;
1defdda8 9561 bool nexthop_self =
9b6d8fcf 9562 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9563 int i;
2ba93fd6
DA
9564 char *nexthop_hostname =
9565 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9566
9567 if (json_paths) {
9568 json_path = json_object_new_object();
9569 json_peer = json_object_new_object();
9570 json_nexthop_global = json_object_new_object();
9571 }
9572
44c69747 9573 if (path->extra) {
b57ba6d2 9574 char tag_buf[30];
d62a17ae 9575
d62a17ae 9576 tag_buf[0] = '\0';
9b6d8fcf
DS
9577 if (path->extra && path->extra->num_labels) {
9578 bgp_evpn_label2str(path->extra->label,
9579 path->extra->num_labels, tag_buf,
a4d82a8a 9580 sizeof(tag_buf));
d62a17ae 9581 }
d7325ee7 9582 if (safi == SAFI_EVPN) {
44c69747 9583 if (!json_paths) {
2dbe669b
DA
9584 vty_out(vty, " Route %pFX",
9585 (struct prefix_evpn *)
9586 bgp_dest_get_prefix(bn));
44c69747
LK
9587 if (tag_buf[0] != '\0')
9588 vty_out(vty, " VNI %s", tag_buf);
9589 vty_out(vty, "\n");
9590 } else {
9591 if (tag_buf[0])
9592 json_object_string_add(json_path, "VNI",
9593 tag_buf);
9594 }
d7325ee7
DD
9595 }
9596
44c69747 9597 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9598 struct bgp_path_info *parent_ri;
9bcb3eef 9599 struct bgp_dest *dest, *pdest;
d62a17ae 9600
9b6d8fcf 9601 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9602 dest = parent_ri->net;
9603 if (dest && dest->pdest) {
9604 pdest = dest->pdest;
9605 prefix_rd2str(
9606 (struct prefix_rd *)bgp_dest_get_prefix(
9607 pdest),
9608 buf1, sizeof(buf1));
d7325ee7 9609 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9610 vty_out(vty,
9611 " Imported from %s:%pFX, VNI %s\n",
9612 buf1,
9613 (struct prefix_evpn *)
9614 bgp_dest_get_prefix(
9615 dest),
9616 tag_buf);
d7325ee7 9617 } else
2dbe669b
DA
9618 vty_out(vty,
9619 " Imported from %s:%pFX\n",
9620 buf1,
9621 (struct prefix_evpn *)
9622 bgp_dest_get_prefix(
9623 dest));
d62a17ae 9624 }
9625 }
9626 }
d62a17ae 9627
05864da7
DS
9628 /* Line1 display AS-path, Aggregator */
9629 if (attr->aspath) {
9630 if (json_paths) {
9631 if (!attr->aspath->json)
9632 aspath_str_update(attr->aspath, true);
9633 json_object_lock(attr->aspath->json);
9634 json_object_object_add(json_path, "aspath",
9635 attr->aspath->json);
9636 } else {
9637 if (attr->aspath->segments)
9638 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9639 else
05864da7 9640 vty_out(vty, " Local");
d62a17ae 9641 }
05864da7 9642 }
d62a17ae 9643
05864da7
DS
9644 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9645 if (json_paths)
9646 json_object_boolean_true_add(json_path, "removed");
9647 else
9648 vty_out(vty, ", (removed)");
9649 }
d62a17ae 9650
05864da7
DS
9651 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9652 if (json_paths)
9653 json_object_boolean_true_add(json_path, "stale");
9654 else
9655 vty_out(vty, ", (stale)");
9656 }
d62a17ae 9657
05864da7
DS
9658 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9659 if (json_paths) {
23d0a753
DA
9660 char buf[BUFSIZ] = {0};
9661
05864da7
DS
9662 json_object_int_add(json_path, "aggregatorAs",
9663 attr->aggregator_as);
23d0a753
DA
9664 json_object_string_add(json_path, "aggregatorId",
9665 inet_ntop(AF_INET,
9666 &attr->aggregator_addr,
9667 buf, sizeof(buf)));
05864da7 9668 } else {
88d495a9
DA
9669 vty_out(vty, ", (aggregated by %u %pI4)",
9670 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9671 }
05864da7 9672 }
d62a17ae 9673
05864da7
DS
9674 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9675 PEER_FLAG_REFLECTOR_CLIENT)) {
9676 if (json_paths)
9677 json_object_boolean_true_add(json_path,
9678 "rxedFromRrClient");
9679 else
9680 vty_out(vty, ", (Received from a RR-client)");
9681 }
d62a17ae 9682
05864da7
DS
9683 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9684 PEER_FLAG_RSERVER_CLIENT)) {
9685 if (json_paths)
9686 json_object_boolean_true_add(json_path,
9687 "rxedFromRsClient");
9688 else
9689 vty_out(vty, ", (Received from a RS-client)");
9690 }
d62a17ae 9691
05864da7
DS
9692 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9693 if (json_paths)
9694 json_object_boolean_true_add(json_path,
9695 "dampeningHistoryEntry");
9696 else
9697 vty_out(vty, ", (history entry)");
9698 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9699 if (json_paths)
9700 json_object_boolean_true_add(json_path,
9701 "dampeningSuppressed");
9702 else
9703 vty_out(vty, ", (suppressed due to dampening)");
9704 }
d62a17ae 9705
05864da7
DS
9706 if (!json_paths)
9707 vty_out(vty, "\n");
d62a17ae 9708
05864da7
DS
9709 /* Line2 display Next-hop, Neighbor, Router-id */
9710 /* Display the nexthop */
9bcb3eef 9711 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9712
9713 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9714 || bn_p->family == AF_EVPN)
05864da7
DS
9715 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9716 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9717 char buf[BUFSIZ] = {0};
9718
05864da7
DS
9719 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9720 || safi == SAFI_EVPN) {
515c2602 9721 if (json_paths) {
d62a17ae 9722 json_object_string_add(
515c2602 9723 json_nexthop_global, "ip",
23d0a753
DA
9724 inet_ntop(AF_INET,
9725 &attr->mp_nexthop_global_in,
9726 buf, sizeof(buf)));
515c2602 9727
939a97f4 9728 if (path->peer->hostname)
515c2602
DA
9729 json_object_string_add(
9730 json_nexthop_global, "hostname",
939a97f4 9731 path->peer->hostname);
aef999a2
DA
9732 } else {
9733 if (nexthop_hostname)
9734 vty_out(vty, " %pI4(%s)",
9735 &attr->mp_nexthop_global_in,
9736 nexthop_hostname);
9737 else
9738 vty_out(vty, " %pI4",
9739 &attr->mp_nexthop_global_in);
9740 }
d62a17ae 9741 } else {
515c2602 9742 if (json_paths) {
05864da7 9743 json_object_string_add(
515c2602 9744 json_nexthop_global, "ip",
23d0a753
DA
9745 inet_ntop(AF_INET, &attr->nexthop, buf,
9746 sizeof(buf)));
515c2602 9747
939a97f4 9748 if (path->peer->hostname)
515c2602
DA
9749 json_object_string_add(
9750 json_nexthop_global, "hostname",
939a97f4 9751 path->peer->hostname);
aef999a2
DA
9752 } else {
9753 if (nexthop_hostname)
9754 vty_out(vty, " %pI4(%s)",
9755 &attr->nexthop,
9756 nexthop_hostname);
9757 else
9758 vty_out(vty, " %pI4",
9759 &attr->nexthop);
9760 }
d62a17ae 9761 }
9762
05864da7
DS
9763 if (json_paths)
9764 json_object_string_add(json_nexthop_global, "afi",
9765 "ipv4");
9766 } else {
9767 if (json_paths) {
9768 json_object_string_add(
515c2602
DA
9769 json_nexthop_global, "ip",
9770 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9771 buf, INET6_ADDRSTRLEN));
9772
939a97f4 9773 if (path->peer->hostname)
515c2602
DA
9774 json_object_string_add(json_nexthop_global,
9775 "hostname",
939a97f4 9776 path->peer->hostname);
515c2602 9777
05864da7
DS
9778 json_object_string_add(json_nexthop_global, "afi",
9779 "ipv6");
9780 json_object_string_add(json_nexthop_global, "scope",
9781 "global");
9782 } else {
aef999a2
DA
9783 if (nexthop_hostname)
9784 vty_out(vty, " %pI6(%s)",
9785 &attr->mp_nexthop_global,
9786 nexthop_hostname);
9787 else
9788 vty_out(vty, " %pI6",
9789 &attr->mp_nexthop_global);
d62a17ae 9790 }
05864da7 9791 }
d62a17ae 9792
05864da7
DS
9793 /* Display the IGP cost or 'inaccessible' */
9794 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9795 if (json_paths)
9796 json_object_boolean_false_add(json_nexthop_global,
9797 "accessible");
9798 else
9799 vty_out(vty, " (inaccessible)");
9800 } else {
9801 if (path->extra && path->extra->igpmetric) {
d62a17ae 9802 if (json_paths)
05864da7
DS
9803 json_object_int_add(json_nexthop_global,
9804 "metric",
9805 path->extra->igpmetric);
d62a17ae 9806 else
05864da7
DS
9807 vty_out(vty, " (metric %u)",
9808 path->extra->igpmetric);
d62a17ae 9809 }
9810
05864da7 9811 /* IGP cost is 0, display this only for json */
d62a17ae 9812 else {
d62a17ae 9813 if (json_paths)
05864da7
DS
9814 json_object_int_add(json_nexthop_global,
9815 "metric", 0);
d62a17ae 9816 }
d62a17ae 9817
05864da7
DS
9818 if (json_paths)
9819 json_object_boolean_true_add(json_nexthop_global,
9820 "accessible");
9821 }
d62a17ae 9822
05864da7
DS
9823 /* Display peer "from" output */
9824 /* This path was originated locally */
9825 if (path->peer == bgp->peer_self) {
d62a17ae 9826
05864da7 9827 if (safi == SAFI_EVPN
b54892e0 9828 || (bn_p->family == AF_INET
05864da7 9829 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9830 if (json_paths)
05864da7
DS
9831 json_object_string_add(json_peer, "peerId",
9832 "0.0.0.0");
d62a17ae 9833 else
05864da7
DS
9834 vty_out(vty, " from 0.0.0.0 ");
9835 } else {
d62a17ae 9836 if (json_paths)
05864da7
DS
9837 json_object_string_add(json_peer, "peerId",
9838 "::");
d62a17ae 9839 else
05864da7 9840 vty_out(vty, " from :: ");
d62a17ae 9841 }
d62a17ae 9842
23d0a753
DA
9843 if (json_paths) {
9844 char buf[BUFSIZ] = {0};
9845
05864da7 9846 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9847 inet_ntop(AF_INET,
9848 &bgp->router_id, buf,
9849 sizeof(buf)));
9850 } else {
9851 vty_out(vty, "(%pI4)", &bgp->router_id);
9852 }
05864da7 9853 }
d62a17ae 9854
05864da7
DS
9855 /* We RXed this path from one of our peers */
9856 else {
9857
9858 if (json_paths) {
9859 json_object_string_add(json_peer, "peerId",
9860 sockunion2str(&path->peer->su,
9861 buf,
9862 SU_ADDRSTRLEN));
9863 json_object_string_add(json_peer, "routerId",
9864 inet_ntop(AF_INET,
9865 &path->peer->remote_id,
9866 buf1, sizeof(buf1)));
9867
9868 if (path->peer->hostname)
9869 json_object_string_add(json_peer, "hostname",
9870 path->peer->hostname);
9871
9872 if (path->peer->domainname)
9873 json_object_string_add(json_peer, "domainname",
9874 path->peer->domainname);
9875
9876 if (path->peer->conf_if)
9877 json_object_string_add(json_peer, "interface",
9878 path->peer->conf_if);
9879 } else {
9880 if (path->peer->conf_if) {
9881 if (path->peer->hostname
892fedb6
DA
9882 && CHECK_FLAG(path->peer->bgp->flags,
9883 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9884 vty_out(vty, " from %s(%s)",
9885 path->peer->hostname,
9886 path->peer->conf_if);
d62a17ae 9887 else
05864da7 9888 vty_out(vty, " from %s",
9b6d8fcf 9889 path->peer->conf_if);
d62a17ae 9890 } else {
05864da7 9891 if (path->peer->hostname
892fedb6
DA
9892 && CHECK_FLAG(path->peer->bgp->flags,
9893 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9894 vty_out(vty, " from %s(%s)",
9895 path->peer->hostname,
9896 path->peer->host);
d62a17ae 9897 else
05864da7
DS
9898 vty_out(vty, " from %s",
9899 sockunion2str(&path->peer->su,
9900 buf,
9901 SU_ADDRSTRLEN));
d62a17ae 9902 }
d62a17ae 9903
05864da7 9904 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9905 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9906 else
9907 vty_out(vty, " (%s)",
9908 inet_ntop(AF_INET,
9909 &path->peer->remote_id, buf1,
9910 sizeof(buf1)));
d62a17ae 9911 }
05864da7 9912 }
9df8b37c 9913
05864da7
DS
9914 /*
9915 * Note when vrfid of nexthop is different from that of prefix
9916 */
9917 if (path->extra && path->extra->bgp_orig) {
9918 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9919
05864da7
DS
9920 if (json_paths) {
9921 const char *vn;
9df8b37c 9922
05864da7
DS
9923 if (path->extra->bgp_orig->inst_type
9924 == BGP_INSTANCE_TYPE_DEFAULT)
9925 vn = VRF_DEFAULT_NAME;
9926 else
9927 vn = path->extra->bgp_orig->name;
9df8b37c 9928
05864da7 9929 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9930
05864da7
DS
9931 if (nexthop_vrfid == VRF_UNKNOWN) {
9932 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9933 } else {
05864da7
DS
9934 json_object_int_add(json_path, "nhVrfId",
9935 (int)nexthop_vrfid);
9df8b37c 9936 }
05864da7
DS
9937 } else {
9938 if (nexthop_vrfid == VRF_UNKNOWN)
9939 vty_out(vty, " vrf ?");
137147c6
DS
9940 else {
9941 struct vrf *vrf;
9942
9943 vrf = vrf_lookup_by_id(nexthop_vrfid);
9944 vty_out(vty, " vrf %s(%u)",
9945 VRF_LOGNAME(vrf), nexthop_vrfid);
9946 }
9df8b37c 9947 }
05864da7 9948 }
9df8b37c 9949
05864da7
DS
9950 if (nexthop_self) {
9951 if (json_paths) {
9952 json_object_boolean_true_add(json_path,
9953 "announceNexthopSelf");
9954 } else {
9955 vty_out(vty, " announce-nh-self");
9df8b37c 9956 }
05864da7 9957 }
9df8b37c 9958
05864da7
DS
9959 if (!json_paths)
9960 vty_out(vty, "\n");
d62a17ae 9961
05864da7
DS
9962 /* display the link-local nexthop */
9963 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9964 if (json_paths) {
9965 json_nexthop_ll = json_object_new_object();
9966 json_object_string_add(
515c2602
DA
9967 json_nexthop_ll, "ip",
9968 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9969 buf, INET6_ADDRSTRLEN));
9970
939a97f4 9971 if (path->peer->hostname)
515c2602
DA
9972 json_object_string_add(json_nexthop_ll,
9973 "hostname",
939a97f4 9974 path->peer->hostname);
515c2602 9975
05864da7
DS
9976 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9977 json_object_string_add(json_nexthop_ll, "scope",
9978 "link-local");
d62a17ae 9979
05864da7
DS
9980 json_object_boolean_true_add(json_nexthop_ll,
9981 "accessible");
d62a17ae 9982
05864da7 9983 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9984 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9985 "used");
9986 else
9987 json_object_boolean_true_add(
9988 json_nexthop_global, "used");
9989 } else {
9990 vty_out(vty, " (%s) %s\n",
9991 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9992 buf, INET6_ADDRSTRLEN),
9993 attr->mp_nexthop_prefer_global
9994 ? "(prefer-global)"
9995 : "(used)");
d62a17ae 9996 }
05864da7
DS
9997 }
9998 /* If we do not have a link-local nexthop then we must flag the
9999 global as "used" */
10000 else {
10001 if (json_paths)
10002 json_object_boolean_true_add(json_nexthop_global,
10003 "used");
10004 }
d62a17ae 10005
b5e140c8 10006 if (safi == SAFI_EVPN &&
5e4d4c8a 10007 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10008 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10009 }
10010
05864da7
DS
10011 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10012 * Int/Ext/Local, Atomic, best */
10013 if (json_paths)
10014 json_object_string_add(json_path, "origin",
10015 bgp_origin_long_str[attr->origin]);
10016 else
10017 vty_out(vty, " Origin %s",
10018 bgp_origin_long_str[attr->origin]);
9df8b37c 10019
05864da7 10020 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10021 if (json_paths)
05864da7 10022 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10023 else
05864da7
DS
10024 vty_out(vty, ", metric %u", attr->med);
10025 }
9df8b37c 10026
05864da7
DS
10027 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10028 if (json_paths)
0fbac0b4 10029 json_object_int_add(json_path, "locPrf",
05864da7
DS
10030 attr->local_pref);
10031 else
10032 vty_out(vty, ", localpref %u", attr->local_pref);
10033 }
9df8b37c 10034
05864da7
DS
10035 if (attr->weight != 0) {
10036 if (json_paths)
10037 json_object_int_add(json_path, "weight", attr->weight);
10038 else
10039 vty_out(vty, ", weight %u", attr->weight);
10040 }
9df8b37c 10041
05864da7
DS
10042 if (attr->tag != 0) {
10043 if (json_paths)
10044 json_object_int_add(json_path, "tag", attr->tag);
10045 else
10046 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10047 }
9df8b37c 10048
05864da7
DS
10049 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10050 if (json_paths)
10051 json_object_boolean_false_add(json_path, "valid");
10052 else
10053 vty_out(vty, ", invalid");
10054 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10055 if (json_paths)
10056 json_object_boolean_true_add(json_path, "valid");
10057 else
10058 vty_out(vty, ", valid");
10059 }
9df8b37c 10060
05864da7
DS
10061 if (path->peer != bgp->peer_self) {
10062 if (path->peer->as == path->peer->local_as) {
10063 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10064 if (json_paths)
10065 json_object_string_add(
10066 json_peer, "type",
10067 "confed-internal");
d62a17ae 10068 else
05864da7 10069 vty_out(vty, ", confed-internal");
d62a17ae 10070 } else {
05864da7
DS
10071 if (json_paths)
10072 json_object_string_add(
10073 json_peer, "type", "internal");
10074 else
10075 vty_out(vty, ", internal");
9df8b37c 10076 }
05864da7
DS
10077 } else {
10078 if (bgp_confederation_peers_check(bgp,
10079 path->peer->as)) {
10080 if (json_paths)
10081 json_object_string_add(
10082 json_peer, "type",
10083 "confed-external");
d62a17ae 10084 else
05864da7 10085 vty_out(vty, ", confed-external");
d62a17ae 10086 } else {
05864da7
DS
10087 if (json_paths)
10088 json_object_string_add(
10089 json_peer, "type", "external");
10090 else
10091 vty_out(vty, ", external");
d62a17ae 10092 }
10093 }
05864da7
DS
10094 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10095 if (json_paths) {
10096 json_object_boolean_true_add(json_path, "aggregated");
10097 json_object_boolean_true_add(json_path, "local");
10098 } else {
10099 vty_out(vty, ", aggregated, local");
10100 }
10101 } else if (path->type != ZEBRA_ROUTE_BGP) {
10102 if (json_paths)
10103 json_object_boolean_true_add(json_path, "sourced");
10104 else
10105 vty_out(vty, ", sourced");
10106 } else {
10107 if (json_paths) {
10108 json_object_boolean_true_add(json_path, "sourced");
10109 json_object_boolean_true_add(json_path, "local");
10110 } else {
10111 vty_out(vty, ", sourced, local");
d62a17ae 10112 }
05864da7 10113 }
718e3744 10114
05864da7 10115 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10116 if (json_paths)
05864da7
DS
10117 json_object_boolean_true_add(json_path,
10118 "atomicAggregate");
d62a17ae 10119 else
05864da7
DS
10120 vty_out(vty, ", atomic-aggregate");
10121 }
d62a17ae 10122
05864da7
DS
10123 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10124 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10125 && bgp_path_info_mpath_count(path))) {
10126 if (json_paths)
10127 json_object_boolean_true_add(json_path, "multipath");
10128 else
10129 vty_out(vty, ", multipath");
10130 }
50e05855 10131
05864da7
DS
10132 // Mark the bestpath(s)
10133 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10134 first_as = aspath_get_first_as(attr->aspath);
718e3744 10135
05864da7
DS
10136 if (json_paths) {
10137 if (!json_bestpath)
10138 json_bestpath = json_object_new_object();
10139 json_object_int_add(json_bestpath, "bestpathFromAs",
10140 first_as);
10141 } else {
10142 if (first_as)
10143 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10144 else
05864da7 10145 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10146 }
05864da7 10147 }
718e3744 10148
05864da7
DS
10149 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10150 if (json_paths) {
10151 if (!json_bestpath)
10152 json_bestpath = json_object_new_object();
10153 json_object_boolean_true_add(json_bestpath, "overall");
10154 json_object_string_add(
10155 json_bestpath, "selectionReason",
10156 bgp_path_selection_reason2str(bn->reason));
10157 } else {
10158 vty_out(vty, ", best");
10159 vty_out(vty, " (%s)",
10160 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10161 }
05864da7 10162 }
718e3744 10163
05864da7
DS
10164 if (json_bestpath)
10165 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10166
05864da7
DS
10167 if (!json_paths)
10168 vty_out(vty, "\n");
10169
10170 /* Line 4 display Community */
10171 if (attr->community) {
10172 if (json_paths) {
10173 if (!attr->community->json)
10174 community_str(attr->community, true);
10175 json_object_lock(attr->community->json);
10176 json_object_object_add(json_path, "community",
10177 attr->community->json);
10178 } else {
10179 vty_out(vty, " Community: %s\n",
10180 attr->community->str);
d62a17ae 10181 }
05864da7 10182 }
718e3744 10183
05864da7
DS
10184 /* Line 5 display Extended-community */
10185 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10186 if (json_paths) {
10187 json_ext_community = json_object_new_object();
10188 json_object_string_add(json_ext_community, "string",
10189 attr->ecommunity->str);
10190 json_object_object_add(json_path, "extendedCommunity",
10191 json_ext_community);
d62a17ae 10192 } else {
05864da7
DS
10193 vty_out(vty, " Extended Community: %s\n",
10194 attr->ecommunity->str);
d62a17ae 10195 }
05864da7 10196 }
718e3744 10197
05864da7
DS
10198 /* Line 6 display Large community */
10199 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10200 if (json_paths) {
10201 if (!attr->lcommunity->json)
10202 lcommunity_str(attr->lcommunity, true);
10203 json_object_lock(attr->lcommunity->json);
10204 json_object_object_add(json_path, "largeCommunity",
10205 attr->lcommunity->json);
10206 } else {
10207 vty_out(vty, " Large Community: %s\n",
10208 attr->lcommunity->str);
d62a17ae 10209 }
05864da7 10210 }
718e3744 10211
05864da7
DS
10212 /* Line 7 display Originator, Cluster-id */
10213 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10214 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10215 char buf[BUFSIZ] = {0};
10216
05864da7 10217 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10218 if (json_paths)
05864da7
DS
10219 json_object_string_add(
10220 json_path, "originatorId",
23d0a753
DA
10221 inet_ntop(AF_INET, &attr->originator_id,
10222 buf, sizeof(buf)));
d62a17ae 10223 else
23d0a753
DA
10224 vty_out(vty, " Originator: %pI4",
10225 &attr->originator_id);
d62a17ae 10226 }
856ca177 10227
05864da7 10228 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10229 struct cluster_list *cluster =
10230 bgp_attr_get_cluster(attr);
05864da7 10231 int i;
d62a17ae 10232
10233 if (json_paths) {
05864da7
DS
10234 json_cluster_list = json_object_new_object();
10235 json_cluster_list_list =
10236 json_object_new_array();
10237
779fee93 10238 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10239 json_string = json_object_new_string(
779fee93
DS
10240 inet_ntop(AF_INET,
10241 &cluster->list[i],
10242 buf, sizeof(buf)));
05864da7
DS
10243 json_object_array_add(
10244 json_cluster_list_list,
10245 json_string);
10246 }
718e3744 10247
05864da7
DS
10248 /*
10249 * struct cluster_list does not have
10250 * "str" variable like aspath and community
10251 * do. Add this someday if someone asks
10252 * for it.
10253 * json_object_string_add(json_cluster_list,
779fee93 10254 * "string", cluster->str);
05864da7
DS
10255 */
10256 json_object_object_add(json_cluster_list,
10257 "list",
10258 json_cluster_list_list);
10259 json_object_object_add(json_path, "clusterList",
10260 json_cluster_list);
0dc8ee70 10261 } else {
05864da7
DS
10262 vty_out(vty, ", Cluster list: ");
10263
779fee93 10264 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10265 vty_out(vty, "%pI4 ",
779fee93 10266 &cluster->list[i]);
05864da7 10267 }
0dc8ee70 10268 }
d62a17ae 10269 }
718e3744 10270
d62a17ae 10271 if (!json_paths)
10272 vty_out(vty, "\n");
05864da7 10273 }
d62a17ae 10274
05864da7 10275 if (path->extra && path->extra->damp_info)
40ec3340 10276 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10277
05864da7
DS
10278 /* Remote Label */
10279 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10280 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10281 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10282
05864da7
DS
10283 if (json_paths)
10284 json_object_int_add(json_path, "remoteLabel", label);
10285 else
10286 vty_out(vty, " Remote label: %d\n", label);
10287 }
d62a17ae 10288
e496b420
HS
10289 /* Remote SID */
10290 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10291 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10292 if (json_paths)
10293 json_object_string_add(json_path, "remoteSid", buf);
10294 else
10295 vty_out(vty, " Remote SID: %s\n", buf);
10296 }
10297
05864da7
DS
10298 /* Label Index */
10299 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10300 if (json_paths)
10301 json_object_int_add(json_path, "labelIndex",
10302 attr->label_index);
10303 else
10304 vty_out(vty, " Label Index: %d\n",
10305 attr->label_index);
10306 }
d62a17ae 10307
05864da7
DS
10308 /* Line 8 display Addpath IDs */
10309 if (path->addpath_rx_id
10310 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10311 if (json_paths) {
10312 json_object_int_add(json_path, "addpathRxId",
10313 path->addpath_rx_id);
d62a17ae 10314
05864da7
DS
10315 /* Keep backwards compatibility with the old API
10316 * by putting TX All's ID in the old field
10317 */
10318 json_object_int_add(
10319 json_path, "addpathTxId",
10320 path->tx_addpath
10321 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10322
05864da7
DS
10323 /* ... but create a specific field for each
10324 * strategy
10325 */
10326 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10327 json_object_int_add(
10328 json_path,
10329 bgp_addpath_names(i)->id_json_name,
10330 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10331 }
05864da7
DS
10332 } else {
10333 vty_out(vty, " AddPath ID: RX %u, ",
10334 path->addpath_rx_id);
d62a17ae 10335
05864da7 10336 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10337 }
05864da7 10338 }
520d5d76 10339
05864da7
DS
10340 /* If we used addpath to TX a non-bestpath we need to display
10341 * "Advertised to" on a path-by-path basis
10342 */
10343 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10344 first = 1;
dcc68b5e 10345
05864da7
DS
10346 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10347 addpath_capable =
10348 bgp_addpath_encode_tx(peer, afi, safi);
10349 has_adj = bgp_adj_out_lookup(
10350 peer, path->net,
10351 bgp_addpath_id_for_peer(peer, afi, safi,
10352 &path->tx_addpath));
10353
10354 if ((addpath_capable && has_adj)
10355 || (!addpath_capable && has_adj
10356 && CHECK_FLAG(path->flags,
10357 BGP_PATH_SELECTED))) {
10358 if (json_path && !json_adv_to)
10359 json_adv_to = json_object_new_object();
dcc68b5e 10360
05864da7
DS
10361 route_vty_out_advertised_to(
10362 vty, peer, &first,
10363 " Advertised to:", json_adv_to);
d62a17ae 10364 }
10365 }
718e3744 10366
05864da7
DS
10367 if (json_path) {
10368 if (json_adv_to) {
10369 json_object_object_add(
10370 json_path, "advertisedTo", json_adv_to);
d62a17ae 10371 }
05864da7
DS
10372 } else {
10373 if (!first) {
10374 vty_out(vty, "\n");
d62a17ae 10375 }
10376 }
05864da7 10377 }
b05a1c8b 10378
05864da7
DS
10379 /* Line 9 display Uptime */
10380 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10381 if (json_paths) {
10382 json_last_update = json_object_new_object();
10383 json_object_int_add(json_last_update, "epoch", tbuf);
10384 json_object_string_add(json_last_update, "string",
10385 ctime(&tbuf));
10386 json_object_object_add(json_path, "lastUpdate",
10387 json_last_update);
10388 } else
10389 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10390
05864da7
DS
10391 /* Line 10 display PMSI tunnel attribute, if present */
10392 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10393 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10394 bgp_attr_get_pmsi_tnl_type(attr),
10395 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10396
05864da7
DS
10397 if (json_paths) {
10398 json_pmsi = json_object_new_object();
10399 json_object_string_add(json_pmsi, "tunnelType", str);
10400 json_object_int_add(json_pmsi, "label",
10401 label2vni(&attr->label));
10402 json_object_object_add(json_path, "pmsi", json_pmsi);
10403 } else
10404 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10405 str, label2vni(&attr->label));
d62a17ae 10406 }
f1aa5d8a 10407
92269aa2
DS
10408 /* Output some debug about internal state of the dest flags */
10409 if (json_paths) {
10410 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10411 json_object_boolean_true_add(json_path, "processScheduled");
10412 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10413 json_object_boolean_true_add(json_path, "userCleared");
10414 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10415 json_object_boolean_true_add(json_path, "labelChanged");
10416 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10417 json_object_boolean_true_add(json_path, "registeredForLabel");
10418 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10419 json_object_boolean_true_add(json_path, "selectDefered");
10420 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10421 json_object_boolean_true_add(json_path, "fibInstalled");
10422 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10423 json_object_boolean_true_add(json_path, "fibPending");
10424 }
10425
d62a17ae 10426 /* We've constructed the json object for this path, add it to the json
10427 * array of paths
10428 */
10429 if (json_paths) {
10430 if (json_nexthop_global || json_nexthop_ll) {
10431 json_nexthops = json_object_new_array();
f1aa5d8a 10432
d62a17ae 10433 if (json_nexthop_global)
10434 json_object_array_add(json_nexthops,
10435 json_nexthop_global);
f1aa5d8a 10436
d62a17ae 10437 if (json_nexthop_ll)
10438 json_object_array_add(json_nexthops,
10439 json_nexthop_ll);
f1aa5d8a 10440
d62a17ae 10441 json_object_object_add(json_path, "nexthops",
10442 json_nexthops);
10443 }
10444
10445 json_object_object_add(json_path, "peer", json_peer);
10446 json_object_array_add(json_paths, json_path);
05864da7 10447 }
b366b518
BB
10448}
10449
96ade3ed 10450#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10451#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10452#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10453
d62a17ae 10454static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10455 const char *prefix_list_str, afi_t afi,
10456 safi_t safi, enum bgp_show_type type);
10457static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10458 const char *filter, afi_t afi, safi_t safi,
10459 enum bgp_show_type type);
10460static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10461 const char *rmap_str, afi_t afi, safi_t safi,
10462 enum bgp_show_type type);
10463static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10464 const char *com, int exact, afi_t afi,
10465 safi_t safi);
10466static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10467 const char *prefix, afi_t afi, safi_t safi,
10468 enum bgp_show_type type);
a4d82a8a 10469static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10470 afi_t afi, safi_t safi, enum bgp_show_type type,
10471 bool use_json);
7f323236
DW
10472static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10473 const char *comstr, int exact, afi_t afi,
96f3485c 10474 safi_t safi, uint8_t show_flags);
d62a17ae 10475
1ae44dfc
LB
10476
10477static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10478 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10479 void *output_arg, char *rd, int is_last,
10480 unsigned long *output_cum, unsigned long *total_cum,
10481 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10482{
40381db7 10483 struct bgp_path_info *pi;
9bcb3eef 10484 struct bgp_dest *dest;
d62a17ae 10485 int header = 1;
10486 int display;
1ae44dfc
LB
10487 unsigned long output_count = 0;
10488 unsigned long total_count = 0;
d62a17ae 10489 struct prefix *p;
d62a17ae 10490 json_object *json_paths = NULL;
10491 int first = 1;
96f3485c
MK
10492 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10493 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10494 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10495
1ae44dfc
LB
10496 if (output_cum && *output_cum != 0)
10497 header = 0;
10498
9386b588 10499 if (use_json && !*json_header_depth) {
96f3485c
MK
10500 if (all)
10501 *json_header_depth = 1;
10502 else {
10503 vty_out(vty, "{\n");
10504 *json_header_depth = 2;
10505 }
10506
d62a17ae 10507 vty_out(vty,
23d0a753
DA
10508 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10509 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10510 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10511 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10512 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10513 ? VRF_DEFAULT_NAME
10514 : bgp->name,
10515 table->version, &bgp->router_id,
01eced22 10516 bgp->default_local_pref, bgp->as);
9386b588 10517 if (rd) {
445c2480 10518 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10519 ++*json_header_depth;
10520 }
d62a17ae 10521 }
718e3744 10522
445c2480
DS
10523 if (use_json && rd) {
10524 vty_out(vty, " \"%s\" : { ", rd);
10525 }
10526
d62a17ae 10527 /* Start processing of routes. */
9bcb3eef
DS
10528 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10529 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10530
9bcb3eef 10531 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10532 if (pi == NULL)
98ce9a06 10533 continue;
d62a17ae 10534
98ce9a06 10535 display = 0;
98ce9a06
DS
10536 if (use_json)
10537 json_paths = json_object_new_array();
10538 else
10539 json_paths = NULL;
d62a17ae 10540
6f94b685 10541 for (; pi; pi = pi->next) {
98ce9a06
DS
10542 total_count++;
10543 if (type == bgp_show_type_flap_statistics
10544 || type == bgp_show_type_flap_neighbor
10545 || type == bgp_show_type_dampend_paths
10546 || type == bgp_show_type_damp_neighbor) {
40381db7 10547 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10548 continue;
10549 }
10550 if (type == bgp_show_type_regexp) {
10551 regex_t *regex = output_arg;
d62a17ae 10552
40381db7 10553 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10554 == REG_NOMATCH)
10555 continue;
10556 }
10557 if (type == bgp_show_type_prefix_list) {
10558 struct prefix_list *plist = output_arg;
d62a17ae 10559
9bcb3eef 10560 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10561 != PREFIX_PERMIT)
10562 continue;
10563 }
10564 if (type == bgp_show_type_filter_list) {
10565 struct as_list *as_list = output_arg;
d62a17ae 10566
40381db7 10567 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10568 != AS_FILTER_PERMIT)
10569 continue;
10570 }
10571 if (type == bgp_show_type_route_map) {
10572 struct route_map *rmap = output_arg;
9b6d8fcf 10573 struct bgp_path_info path;
98ce9a06 10574 struct attr dummy_attr;
b68885f9 10575 route_map_result_t ret;
d62a17ae 10576
6f4f49b2 10577 dummy_attr = *pi->attr;
d62a17ae 10578
40381db7 10579 path.peer = pi->peer;
9b6d8fcf 10580 path.attr = &dummy_attr;
d62a17ae 10581
1782514f 10582 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10583 if (ret == RMAP_DENYMATCH)
10584 continue;
10585 }
10586 if (type == bgp_show_type_neighbor
10587 || type == bgp_show_type_flap_neighbor
10588 || type == bgp_show_type_damp_neighbor) {
10589 union sockunion *su = output_arg;
10590
40381db7
DS
10591 if (pi->peer == NULL
10592 || pi->peer->su_remote == NULL
10593 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10594 continue;
10595 }
10596 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10597 uint32_t destination;
d62a17ae 10598
9bcb3eef 10599 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10600 if (IN_CLASSC(destination)
9bcb3eef 10601 && dest_p->prefixlen == 24)
98ce9a06
DS
10602 continue;
10603 if (IN_CLASSB(destination)
9bcb3eef 10604 && dest_p->prefixlen == 16)
98ce9a06
DS
10605 continue;
10606 if (IN_CLASSA(destination)
9bcb3eef 10607 && dest_p->prefixlen == 8)
98ce9a06
DS
10608 continue;
10609 }
10610 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10611 p = output_arg;
9bcb3eef 10612 if (!prefix_match(p, dest_p))
98ce9a06
DS
10613 continue;
10614 }
10615 if (type == bgp_show_type_community_all) {
40381db7 10616 if (!pi->attr->community)
98ce9a06
DS
10617 continue;
10618 }
10619 if (type == bgp_show_type_community) {
10620 struct community *com = output_arg;
d62a17ae 10621
40381db7
DS
10622 if (!pi->attr->community
10623 || !community_match(pi->attr->community,
98ce9a06
DS
10624 com))
10625 continue;
10626 }
10627 if (type == bgp_show_type_community_exact) {
10628 struct community *com = output_arg;
d62a17ae 10629
40381db7
DS
10630 if (!pi->attr->community
10631 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10632 continue;
10633 }
10634 if (type == bgp_show_type_community_list) {
10635 struct community_list *list = output_arg;
d62a17ae 10636
40381db7 10637 if (!community_list_match(pi->attr->community,
a4d82a8a 10638 list))
98ce9a06
DS
10639 continue;
10640 }
a4d82a8a 10641 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10642 struct community_list *list = output_arg;
d62a17ae 10643
98ce9a06 10644 if (!community_list_exact_match(
40381db7 10645 pi->attr->community, list))
98ce9a06
DS
10646 continue;
10647 }
10648 if (type == bgp_show_type_lcommunity) {
10649 struct lcommunity *lcom = output_arg;
d62a17ae 10650
40381db7
DS
10651 if (!pi->attr->lcommunity
10652 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10653 lcom))
10654 continue;
10655 }
36a206db 10656
10657 if (type == bgp_show_type_lcommunity_exact) {
10658 struct lcommunity *lcom = output_arg;
10659
10660 if (!pi->attr->lcommunity
10661 || !lcommunity_cmp(pi->attr->lcommunity,
10662 lcom))
10663 continue;
10664 }
98ce9a06
DS
10665 if (type == bgp_show_type_lcommunity_list) {
10666 struct community_list *list = output_arg;
d62a17ae 10667
40381db7 10668 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10669 list))
98ce9a06
DS
10670 continue;
10671 }
36a206db 10672 if (type
10673 == bgp_show_type_lcommunity_list_exact) {
10674 struct community_list *list = output_arg;
10675
10676 if (!lcommunity_list_exact_match(
10677 pi->attr->lcommunity, list))
10678 continue;
10679 }
98ce9a06 10680 if (type == bgp_show_type_lcommunity_all) {
40381db7 10681 if (!pi->attr->lcommunity)
98ce9a06
DS
10682 continue;
10683 }
10684 if (type == bgp_show_type_dampend_paths
10685 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10686 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10687 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10688 continue;
10689 }
10690
10691 if (!use_json && header) {
23d0a753
DA
10692 vty_out(vty,
10693 "BGP table version is %" PRIu64
10694 ", local router ID is %pI4, vrf id ",
10695 table->version, &bgp->router_id);
9df8b37c
PZ
10696 if (bgp->vrf_id == VRF_UNKNOWN)
10697 vty_out(vty, "%s", VRFID_NONE_STR);
10698 else
10699 vty_out(vty, "%u", bgp->vrf_id);
10700 vty_out(vty, "\n");
01eced22
AD
10701 vty_out(vty, "Default local pref %u, ",
10702 bgp->default_local_pref);
10703 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10704 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10705 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10706 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10707 if (type == bgp_show_type_dampend_paths
10708 || type == bgp_show_type_damp_neighbor)
98ce9a06 10709 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10710 else if (type == bgp_show_type_flap_statistics
10711 || type == bgp_show_type_flap_neighbor)
98ce9a06 10712 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10713 else
ae248832
MK
10714 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10715 : BGP_SHOW_HEADER));
98ce9a06 10716 header = 0;
d62a17ae 10717 }
98ce9a06
DS
10718 if (rd != NULL && !display && !output_count) {
10719 if (!use_json)
10720 vty_out(vty,
10721 "Route Distinguisher: %s\n",
10722 rd);
d62a17ae 10723 }
98ce9a06
DS
10724 if (type == bgp_show_type_dampend_paths
10725 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10726 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10727 AFI_IP, safi, use_json,
10728 json_paths);
98ce9a06
DS
10729 else if (type == bgp_show_type_flap_statistics
10730 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10731 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10732 AFI_IP, safi, use_json,
10733 json_paths);
98ce9a06 10734 else
9bcb3eef 10735 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10736 json_paths, wide);
98ce9a06 10737 display++;
d62a17ae 10738 }
10739
98ce9a06
DS
10740 if (display) {
10741 output_count++;
10742 if (!use_json)
10743 continue;
10744
625d2931 10745 /* encode prefix */
9bcb3eef 10746 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10747 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10748
1840384b 10749
b54892e0
DS
10750 bgp_fs_nlri_get_string(
10751 (unsigned char *)
9bcb3eef
DS
10752 dest_p->u.prefix_flowspec.ptr,
10753 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10754 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10755 family2afi(dest_p->u
10756 .prefix_flowspec.family));
625d2931 10757 if (first)
b54892e0 10758 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10759 dest_p->u.prefix_flowspec
b54892e0 10760 .prefixlen);
625d2931 10761 else
b54892e0 10762 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10763 dest_p->u.prefix_flowspec
b54892e0 10764 .prefixlen);
625d2931 10765 } else {
625d2931 10766 if (first)
1b78780b 10767 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10768 else
1b78780b 10769 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10770 }
98ce9a06 10771 vty_out(vty, "%s",
f4ec52f7
DA
10772 json_object_to_json_string_ext(
10773 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10774 json_object_free(json_paths);
449feb8e 10775 json_paths = NULL;
98ce9a06 10776 first = 0;
1f83ed02
DS
10777 } else
10778 json_object_free(json_paths);
98ce9a06
DS
10779 }
10780
1ae44dfc
LB
10781 if (output_cum) {
10782 output_count += *output_cum;
10783 *output_cum = output_count;
10784 }
10785 if (total_cum) {
10786 total_count += *total_cum;
10787 *total_cum = total_count;
10788 }
d62a17ae 10789 if (use_json) {
9386b588 10790 if (rd) {
a4d82a8a 10791 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10792 }
10793 if (is_last) {
a4d82a8a
PZ
10794 unsigned long i;
10795 for (i = 0; i < *json_header_depth; ++i)
10796 vty_out(vty, " } ");
96f3485c
MK
10797 if (!all)
10798 vty_out(vty, "\n");
9386b588 10799 }
d62a17ae 10800 } else {
1ae44dfc
LB
10801 if (is_last) {
10802 /* No route is displayed */
10803 if (output_count == 0) {
10804 if (type == bgp_show_type_normal)
10805 vty_out(vty,
10806 "No BGP prefixes displayed, %ld exist\n",
10807 total_count);
10808 } else
d62a17ae 10809 vty_out(vty,
1ae44dfc
LB
10810 "\nDisplayed %ld routes and %ld total paths\n",
10811 output_count, total_count);
10812 }
d62a17ae 10813 }
718e3744 10814
d62a17ae 10815 return CMD_SUCCESS;
718e3744 10816}
10817
1ae44dfc
LB
10818int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10819 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10820 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10821{
9bcb3eef 10822 struct bgp_dest *dest, *next;
1ae44dfc
LB
10823 unsigned long output_cum = 0;
10824 unsigned long total_cum = 0;
9386b588 10825 unsigned long json_header_depth = 0;
67009e22 10826 struct bgp_table *itable;
0136788c 10827 bool show_msg;
96f3485c 10828 uint8_t show_flags = 0;
0136788c
LB
10829
10830 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10831
96f3485c
MK
10832 if (use_json)
10833 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10834
9bcb3eef
DS
10835 for (dest = bgp_table_top(table); dest; dest = next) {
10836 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10837
9bcb3eef
DS
10838 next = bgp_route_next(dest);
10839 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10840 continue;
67009e22 10841
9bcb3eef 10842 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10843 if (itable != NULL) {
1ae44dfc 10844 struct prefix_rd prd;
06b9f471 10845 char rd[RD_ADDRSTRLEN];
1ae44dfc 10846
9bcb3eef 10847 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10848 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10849 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10850 rd, next == NULL, &output_cum,
10851 &total_cum, &json_header_depth,
10852 show_flags);
0136788c
LB
10853 if (next == NULL)
10854 show_msg = false;
1ae44dfc
LB
10855 }
10856 }
0136788c
LB
10857 if (show_msg) {
10858 if (output_cum == 0)
10859 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10860 total_cum);
10861 else
10862 vty_out(vty,
10863 "\nDisplayed %ld routes and %ld total paths\n",
10864 output_cum, total_cum);
10865 }
1ae44dfc
LB
10866 return CMD_SUCCESS;
10867}
d62a17ae 10868static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10869 enum bgp_show_type type, void *output_arg,
10870 uint8_t show_flags)
fee0f4c6 10871{
d62a17ae 10872 struct bgp_table *table;
9386b588 10873 unsigned long json_header_depth = 0;
96f3485c 10874 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10875
d62a17ae 10876 if (bgp == NULL) {
10877 bgp = bgp_get_default();
10878 }
fee0f4c6 10879
d62a17ae 10880 if (bgp == NULL) {
10881 if (!use_json)
10882 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10883 else
10884 vty_out(vty, "{}\n");
d62a17ae 10885 return CMD_WARNING;
10886 }
4dd6177e 10887
1ae44dfc 10888 table = bgp->rib[afi][safi];
d62a17ae 10889 /* use MPLS and ENCAP specific shows until they are merged */
10890 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10891 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10892 output_arg, use_json);
d62a17ae 10893 }
dba3c1d3
PG
10894
10895 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10896 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10897 output_arg, use_json,
10898 1, NULL, NULL);
10899 }
d62a17ae 10900 /* labeled-unicast routes live in the unicast table */
10901 else if (safi == SAFI_LABELED_UNICAST)
10902 safi = SAFI_UNICAST;
fee0f4c6 10903
96f3485c
MK
10904 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10905 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10906}
10907
d62a17ae 10908static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10909 safi_t safi, uint8_t show_flags)
f186de26 10910{
d62a17ae 10911 struct listnode *node, *nnode;
10912 struct bgp *bgp;
10913 int is_first = 1;
9f049418 10914 bool route_output = false;
96f3485c 10915 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10916
d62a17ae 10917 if (use_json)
10918 vty_out(vty, "{\n");
9f689658 10919
d62a17ae 10920 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10921 route_output = true;
d62a17ae 10922 if (use_json) {
10923 if (!is_first)
10924 vty_out(vty, ",\n");
10925 else
10926 is_first = 0;
10927
10928 vty_out(vty, "\"%s\":",
10929 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10930 ? VRF_DEFAULT_NAME
d62a17ae 10931 : bgp->name);
10932 } else {
10933 vty_out(vty, "\nInstance %s:\n",
10934 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10935 ? VRF_DEFAULT_NAME
d62a17ae 10936 : bgp->name);
10937 }
10938 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10939 show_flags);
d62a17ae 10940 }
9f689658 10941
d62a17ae 10942 if (use_json)
10943 vty_out(vty, "}\n");
9f049418
DS
10944 else if (!route_output)
10945 vty_out(vty, "%% BGP instance not found\n");
f186de26 10946}
10947
718e3744 10948/* Header of detailed BGP route information */
d62a17ae 10949void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10950 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10951 afi_t afi, safi_t safi, json_object *json)
10952{
40381db7 10953 struct bgp_path_info *pi;
b54892e0 10954 const struct prefix *p;
d62a17ae 10955 struct peer *peer;
10956 struct listnode *node, *nnode;
06b9f471 10957 char buf1[RD_ADDRSTRLEN];
0291c246 10958 char prefix_str[BUFSIZ];
d62a17ae 10959 int count = 0;
10960 int best = 0;
10961 int suppress = 0;
c5f1e1b2
C
10962 int accept_own = 0;
10963 int route_filter_translated_v4 = 0;
10964 int route_filter_v4 = 0;
10965 int route_filter_translated_v6 = 0;
10966 int route_filter_v6 = 0;
10967 int llgr_stale = 0;
10968 int no_llgr = 0;
10969 int accept_own_nexthop = 0;
10970 int blackhole = 0;
d62a17ae 10971 int no_export = 0;
10972 int no_advertise = 0;
10973 int local_as = 0;
c5f1e1b2 10974 int no_peer = 0;
d62a17ae 10975 int first = 1;
10976 int has_valid_label = 0;
10977 mpls_label_t label = 0;
10978 json_object *json_adv_to = NULL;
9bedbb1e 10979
9bcb3eef
DS
10980 p = bgp_dest_get_prefix(dest);
10981 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10982
10983 if (has_valid_label)
9bcb3eef 10984 label = label_pton(&dest->local_label);
d62a17ae 10985
44c69747 10986 if (safi == SAFI_EVPN) {
d62a17ae 10987
44c69747 10988 if (!json) {
2dbe669b 10989 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 10990 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 10991 : "",
2dbe669b 10992 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
10993 } else {
10994 json_object_string_add(json, "rd",
10995 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10996 "");
10997 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10998 }
10999 } else {
11000 if (!json) {
8228a9a7 11001 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 11002 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11003 ? prefix_rd2str(prd, buf1,
11004 sizeof(buf1))
11005 : ""),
11006 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 11007
44c69747
LK
11008 } else
11009 json_object_string_add(json, "prefix",
11010 prefix2str(p, prefix_str, sizeof(prefix_str)));
11011 }
11012
11013 if (has_valid_label) {
11014 if (json)
11015 json_object_int_add(json, "localLabel", label);
11016 else
d62a17ae 11017 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11018 }
11019
11020 if (!json)
d62a17ae 11021 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11022 vty_out(vty, "not allocated\n");
718e3744 11023
9bcb3eef 11024 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11025 count++;
40381db7 11026 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11027 best = count;
4056a5f6 11028 if (bgp_path_suppressed(pi))
d62a17ae 11029 suppress = 1;
cee9c031 11030
40381db7 11031 if (pi->attr->community == NULL)
cee9c031
QY
11032 continue;
11033
11034 no_advertise += community_include(
40381db7
DS
11035 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11036 no_export += community_include(pi->attr->community,
cee9c031 11037 COMMUNITY_NO_EXPORT);
40381db7 11038 local_as += community_include(pi->attr->community,
cee9c031 11039 COMMUNITY_LOCAL_AS);
40381db7 11040 accept_own += community_include(pi->attr->community,
cee9c031
QY
11041 COMMUNITY_ACCEPT_OWN);
11042 route_filter_translated_v4 += community_include(
40381db7 11043 pi->attr->community,
cee9c031
QY
11044 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11045 route_filter_translated_v6 += community_include(
40381db7 11046 pi->attr->community,
cee9c031
QY
11047 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11048 route_filter_v4 += community_include(
40381db7 11049 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11050 route_filter_v6 += community_include(
40381db7
DS
11051 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11052 llgr_stale += community_include(pi->attr->community,
cee9c031 11053 COMMUNITY_LLGR_STALE);
40381db7 11054 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11055 COMMUNITY_NO_LLGR);
11056 accept_own_nexthop +=
40381db7 11057 community_include(pi->attr->community,
cee9c031 11058 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11059 blackhole += community_include(pi->attr->community,
cee9c031 11060 COMMUNITY_BLACKHOLE);
40381db7 11061 no_peer += community_include(pi->attr->community,
cee9c031 11062 COMMUNITY_NO_PEER);
d62a17ae 11063 }
718e3744 11064 }
718e3744 11065
d62a17ae 11066 if (!json) {
11067 vty_out(vty, "Paths: (%d available", count);
11068 if (best) {
11069 vty_out(vty, ", best #%d", best);
b84060bb
PG
11070 if (safi == SAFI_UNICAST) {
11071 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11072 vty_out(vty, ", table %s",
11073 VRF_DEFAULT_NAME);
11074 else
11075 vty_out(vty, ", vrf %s",
11076 bgp->name);
11077 }
d62a17ae 11078 } else
11079 vty_out(vty, ", no best path");
11080
c5f1e1b2
C
11081 if (accept_own)
11082 vty_out(vty,
11083 ", accept own local route exported and imported in different VRF");
11084 else if (route_filter_translated_v4)
11085 vty_out(vty,
11086 ", mark translated RTs for VPNv4 route filtering");
11087 else if (route_filter_v4)
11088 vty_out(vty,
11089 ", attach RT as-is for VPNv4 route filtering");
11090 else if (route_filter_translated_v6)
11091 vty_out(vty,
11092 ", mark translated RTs for VPNv6 route filtering");
11093 else if (route_filter_v6)
11094 vty_out(vty,
11095 ", attach RT as-is for VPNv6 route filtering");
11096 else if (llgr_stale)
11097 vty_out(vty,
11098 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11099 else if (no_llgr)
11100 vty_out(vty,
11101 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11102 else if (accept_own_nexthop)
11103 vty_out(vty,
11104 ", accept local nexthop");
11105 else if (blackhole)
11106 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11107 else if (no_export)
11108 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11109 else if (no_advertise)
11110 vty_out(vty, ", not advertised to any peer");
d62a17ae 11111 else if (local_as)
11112 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11113 else if (no_peer)
11114 vty_out(vty,
11115 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11116
11117 if (suppress)
11118 vty_out(vty,
11119 ", Advertisements suppressed by an aggregate.");
11120 vty_out(vty, ")\n");
11121 }
718e3744 11122
d62a17ae 11123 /* If we are not using addpath then we can display Advertised to and
11124 * that will
11125 * show what peers we advertised the bestpath to. If we are using
11126 * addpath
11127 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11128 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11129 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11130 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11131 if (json && !json_adv_to)
11132 json_adv_to = json_object_new_object();
11133
11134 route_vty_out_advertised_to(
11135 vty, peer, &first,
11136 " Advertised to non peer-group peers:\n ",
11137 json_adv_to);
11138 }
11139 }
11140
11141 if (json) {
11142 if (json_adv_to) {
11143 json_object_object_add(json, "advertisedTo",
11144 json_adv_to);
11145 }
11146 } else {
11147 if (first)
11148 vty_out(vty, " Not advertised to any peer");
11149 vty_out(vty, "\n");
11150 }
11151 }
718e3744 11152}
11153
44c69747 11154static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11155 struct bgp_dest *bgp_node, struct vty *vty,
11156 struct bgp *bgp, afi_t afi, safi_t safi,
11157 json_object *json, enum bgp_path_type pathtype,
11158 int *display)
44c69747
LK
11159{
11160 struct bgp_path_info *pi;
11161 int header = 1;
11162 char rdbuf[RD_ADDRSTRLEN];
11163 json_object *json_header = NULL;
11164 json_object *json_paths = NULL;
11165
9bcb3eef 11166 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
11167
11168 if (json && !json_paths) {
11169 /* Instantiate json_paths only if path is valid */
11170 json_paths = json_object_new_array();
11171 if (pfx_rd) {
11172 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11173 json_header = json_object_new_object();
11174 } else
11175 json_header = json;
11176 }
11177
11178 if (header) {
11179 route_vty_out_detail_header(
11180 vty, bgp, bgp_node, pfx_rd,
11181 AFI_IP, safi, json_header);
11182 header = 0;
11183 }
11184 (*display)++;
11185
11186 if (pathtype == BGP_PATH_SHOW_ALL
11187 || (pathtype == BGP_PATH_SHOW_BESTPATH
11188 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11189 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11190 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11191 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11192 route_vty_out_detail(vty, bgp, bgp_node,
11193 pi, AFI_IP, safi,
11194 json_paths);
11195 }
11196
11197 if (json && json_paths) {
11198 json_object_object_add(json_header, "paths", json_paths);
11199
11200 if (pfx_rd)
11201 json_object_object_add(json, rdbuf, json_header);
11202 }
11203}
11204
718e3744 11205/* Display specified route of BGP table. */
d62a17ae 11206static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11207 struct bgp_table *rib, const char *ip_str,
11208 afi_t afi, safi_t safi,
11209 struct prefix_rd *prd, int prefix_check,
9f049418 11210 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11211{
11212 int ret;
d62a17ae 11213 int display = 0;
11214 struct prefix match;
9bcb3eef
DS
11215 struct bgp_dest *dest;
11216 struct bgp_dest *rm;
d62a17ae 11217 struct bgp_table *table;
11218 json_object *json = NULL;
11219 json_object *json_paths = NULL;
11220
11221 /* Check IP address argument. */
11222 ret = str2prefix(ip_str, &match);
11223 if (!ret) {
11224 vty_out(vty, "address is malformed\n");
11225 return CMD_WARNING;
11226 }
718e3744 11227
d62a17ae 11228 match.family = afi2family(afi);
b05a1c8b 11229
44c69747 11230 if (use_json)
d62a17ae 11231 json = json_object_new_object();
718e3744 11232
44c69747 11233 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11234 for (dest = bgp_table_top(rib); dest;
11235 dest = bgp_route_next(dest)) {
11236 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11237
9bcb3eef 11238 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11239 continue;
9bcb3eef 11240 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11241 if (!table)
ea47320b 11242 continue;
d62a17ae 11243
ea47320b
DL
11244 if ((rm = bgp_node_match(table, &match)) == NULL)
11245 continue;
d62a17ae 11246
9bcb3eef 11247 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11248 if (prefix_check
b54892e0 11249 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11250 bgp_dest_unlock_node(rm);
ea47320b
DL
11251 continue;
11252 }
d62a17ae 11253
9bcb3eef 11254 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11255 bgp, afi, safi, json, pathtype,
11256 &display);
44c69747 11257
9bcb3eef 11258 bgp_dest_unlock_node(rm);
44c69747
LK
11259 }
11260 } else if (safi == SAFI_EVPN) {
9bcb3eef 11261 struct bgp_dest *longest_pfx;
cded3b72 11262 bool is_exact_pfxlen_match = false;
44c69747 11263
9bcb3eef
DS
11264 for (dest = bgp_table_top(rib); dest;
11265 dest = bgp_route_next(dest)) {
11266 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11267
9bcb3eef 11268 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11269 continue;
9bcb3eef 11270 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11271 if (!table)
11272 continue;
11273
11274 longest_pfx = NULL;
cded3b72 11275 is_exact_pfxlen_match = false;
44c69747
LK
11276 /*
11277 * Search through all the prefixes for a match. The
11278 * pfx's are enumerated in ascending order of pfxlens.
11279 * So, the last pfx match is the longest match. Set
11280 * is_exact_pfxlen_match when we get exact pfxlen match
11281 */
11282 for (rm = bgp_table_top(table); rm;
11283 rm = bgp_route_next(rm)) {
b54892e0 11284 const struct prefix *rm_p =
9bcb3eef 11285 bgp_dest_get_prefix(rm);
44c69747
LK
11286 /*
11287 * Get prefixlen of the ip-prefix within type5
11288 * evpn route
11289 */
b54892e0
DS
11290 if (evpn_type5_prefix_match(rm_p, &match)
11291 && rm->info) {
44c69747
LK
11292 longest_pfx = rm;
11293 int type5_pfxlen =
b54892e0
DS
11294 bgp_evpn_get_type5_prefixlen(
11295 rm_p);
44c69747 11296 if (type5_pfxlen == match.prefixlen) {
cded3b72 11297 is_exact_pfxlen_match = true;
9bcb3eef 11298 bgp_dest_unlock_node(rm);
44c69747
LK
11299 break;
11300 }
d62a17ae 11301 }
11302 }
ea47320b 11303
44c69747
LK
11304 if (!longest_pfx)
11305 continue;
11306
11307 if (prefix_check && !is_exact_pfxlen_match)
11308 continue;
11309
11310 rm = longest_pfx;
9bcb3eef 11311 bgp_dest_lock_node(rm);
44c69747 11312
9bcb3eef 11313 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11314 bgp, afi, safi, json, pathtype,
11315 &display);
44c69747 11316
9bcb3eef 11317 bgp_dest_unlock_node(rm);
d62a17ae 11318 }
98a9dbc7 11319 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11320 if (use_json)
11321 json_paths = json_object_new_array();
11322
63a0b7a9
PG
11323 display = bgp_flowspec_display_match_per_ip(afi, rib,
11324 &match, prefix_check,
11325 vty,
11326 use_json,
11327 json_paths);
d5f20468
SP
11328 if (use_json) {
11329 if (display)
11330 json_object_object_add(json, "paths",
11331 json_paths);
11332 else
11333 json_object_free(json_paths);
11334 }
d62a17ae 11335 } else {
9bcb3eef
DS
11336 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11337 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11338 if (!prefix_check
9bcb3eef
DS
11339 || dest_p->prefixlen == match.prefixlen) {
11340 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11341 safi, json, pathtype,
11342 &display);
d62a17ae 11343 }
11344
9bcb3eef 11345 bgp_dest_unlock_node(dest);
d62a17ae 11346 }
11347 }
e5eee9af 11348
d62a17ae 11349 if (use_json) {
996c9314 11350 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11351 json, JSON_C_TO_STRING_PRETTY |
11352 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11353 json_object_free(json);
11354 } else {
11355 if (!display) {
11356 vty_out(vty, "%% Network not in table\n");
11357 return CMD_WARNING;
11358 }
11359 }
b05a1c8b 11360
d62a17ae 11361 return CMD_SUCCESS;
718e3744 11362}
11363
fee0f4c6 11364/* Display specified route of Main RIB */
d62a17ae 11365static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11366 afi_t afi, safi_t safi, struct prefix_rd *prd,
11367 int prefix_check, enum bgp_path_type pathtype,
9f049418 11368 bool use_json)
d62a17ae 11369{
9b86009a 11370 if (!bgp) {
d62a17ae 11371 bgp = bgp_get_default();
9b86009a
RW
11372 if (!bgp) {
11373 if (!use_json)
11374 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11375 else
11376 vty_out(vty, "{}\n");
9b86009a
RW
11377 return CMD_WARNING;
11378 }
11379 }
d62a17ae 11380
11381 /* labeled-unicast routes live in the unicast table */
11382 if (safi == SAFI_LABELED_UNICAST)
11383 safi = SAFI_UNICAST;
11384
11385 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11386 afi, safi, prd, prefix_check, pathtype,
11387 use_json);
11388}
11389
11390static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11391 struct cmd_token **argv, bool exact, afi_t afi,
11392 safi_t safi, bool uj)
d62a17ae 11393{
11394 struct lcommunity *lcom;
11395 struct buffer *b;
11396 int i;
11397 char *str;
11398 int first = 0;
96f3485c 11399 uint8_t show_flags = 0;
4f28b2b5 11400 int ret;
96f3485c
MK
11401
11402 if (uj)
11403 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11404
11405 b = buffer_new(1024);
11406 for (i = 0; i < argc; i++) {
11407 if (first)
11408 buffer_putc(b, ' ');
11409 else {
11410 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11411 first = 1;
11412 buffer_putstr(b, argv[i]->arg);
11413 }
11414 }
11415 }
11416 buffer_putc(b, '\0');
57d187bc 11417
d62a17ae 11418 str = buffer_getstr(b);
11419 buffer_free(b);
57d187bc 11420
d62a17ae 11421 lcom = lcommunity_str2com(str);
11422 XFREE(MTYPE_TMP, str);
11423 if (!lcom) {
11424 vty_out(vty, "%% Large-community malformed\n");
11425 return CMD_WARNING;
11426 }
57d187bc 11427
4f28b2b5 11428 ret = bgp_show(vty, bgp, afi, safi,
36a206db 11429 (exact ? bgp_show_type_lcommunity_exact
ae248832 11430 : bgp_show_type_lcommunity),
96f3485c 11431 lcom, show_flags);
4f28b2b5
DS
11432
11433 lcommunity_free(&lcom);
11434 return ret;
57d187bc
JS
11435}
11436
d62a17ae 11437static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11438 const char *lcom, bool exact, afi_t afi,
11439 safi_t safi, bool uj)
57d187bc 11440{
d62a17ae 11441 struct community_list *list;
96f3485c
MK
11442 uint8_t show_flags = 0;
11443
11444 if (uj)
11445 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11446
57d187bc 11447
e237b0d2 11448 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11449 LARGE_COMMUNITY_LIST_MASTER);
11450 if (list == NULL) {
11451 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11452 lcom);
11453 return CMD_WARNING;
11454 }
57d187bc 11455
36a206db 11456 return bgp_show(vty, bgp, afi, safi,
11457 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11458 : bgp_show_type_lcommunity_list),
96f3485c 11459 list, show_flags);
fee0f4c6 11460}
11461
52951b63
DS
11462DEFUN (show_ip_bgp_large_community_list,
11463 show_ip_bgp_large_community_list_cmd,
36a206db 11464 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
52951b63
DS
11465 SHOW_STR
11466 IP_STR
11467 BGP_STR
11468 BGP_INSTANCE_HELP_STR
9bedbb1e 11469 BGP_AFI_HELP_STR
4dd6177e 11470 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11471 "Display routes matching the large-community-list\n"
11472 "large-community-list number\n"
11473 "large-community-list name\n"
36a206db 11474 "Exact match of the large-communities\n"
52951b63
DS
11475 JSON_STR)
11476{
d62a17ae 11477 afi_t afi = AFI_IP6;
11478 safi_t safi = SAFI_UNICAST;
11479 int idx = 0;
36a206db 11480 bool exact_match = 0;
4d678463 11481 struct bgp *bgp = NULL;
9f049418 11482 bool uj = use_json(argc, argv);
d62a17ae 11483
4d678463
KA
11484 if (uj)
11485 argc--;
11486
11487 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11488 &bgp, uj);
11489 if (!idx)
11490 return CMD_WARNING;
d62a17ae 11491
11492 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11493
11494 const char *clist_number_or_name = argv[++idx]->arg;
11495
11496 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11497 exact_match = 1;
11498
11499 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11500 exact_match, afi, safi, uj);
52951b63
DS
11501}
11502DEFUN (show_ip_bgp_large_community,
11503 show_ip_bgp_large_community_cmd,
36a206db 11504 "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
11505 SHOW_STR
11506 IP_STR
11507 BGP_STR
11508 BGP_INSTANCE_HELP_STR
9bedbb1e 11509 BGP_AFI_HELP_STR
4dd6177e 11510 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11511 "Display routes matching the large-communities\n"
11512 "List of large-community numbers\n"
36a206db 11513 "Exact match of the large-communities\n"
52951b63
DS
11514 JSON_STR)
11515{
d62a17ae 11516 afi_t afi = AFI_IP6;
11517 safi_t safi = SAFI_UNICAST;
11518 int idx = 0;
36a206db 11519 bool exact_match = 0;
4d678463 11520 struct bgp *bgp = NULL;
9f049418 11521 bool uj = use_json(argc, argv);
96f3485c 11522 uint8_t show_flags = 0;
d62a17ae 11523
96f3485c
MK
11524 if (uj) {
11525 argc--;
11526 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11527 }
4d678463 11528
96f3485c
MK
11529 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11530 &bgp, uj);
11531 if (!idx)
11532 return CMD_WARNING;
d62a17ae 11533
36a206db 11534 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11535 if (argv_find(argv, argc, "exact-match", &idx))
11536 exact_match = 1;
11537 return bgp_show_lcommunity(vty, bgp, argc, argv,
11538 exact_match, afi, safi, uj);
11539 } else
d62a17ae 11540 return bgp_show(vty, bgp, afi, safi,
96f3485c 11541 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11542}
11543
71f1613a
DA
11544static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11545 safi_t safi, struct json_object *json_array);
d62a17ae 11546static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11547 safi_t safi, struct json_object *json);
e01ca200 11548
7b2ff250 11549
9ab0cf58
PG
11550DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11551 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11552 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11553 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11554{
11555 bool uj = use_json(argc, argv);
11556 struct bgp *bgp = NULL;
ec76a1d1
DA
11557 safi_t safi = SAFI_UNICAST;
11558 afi_t afi = AFI_IP6;
4265b261 11559 int idx = 0;
6c9d22e2
PG
11560 struct json_object *json_all = NULL;
11561 struct json_object *json_afi_safi = NULL;
4265b261
PG
11562
11563 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11564 &bgp, false);
71f1613a 11565 if (!idx)
4265b261 11566 return CMD_WARNING;
6c9d22e2 11567
4265b261 11568 if (uj)
6c9d22e2 11569 json_all = json_object_new_object();
4265b261 11570
9ab0cf58
PG
11571 FOREACH_AFI_SAFI (afi, safi) {
11572 /*
11573 * So limit output to those afi/safi pairs that
11574 * actually have something interesting in them
11575 */
11576 if (strmatch(get_afi_safi_str(afi, safi, true),
11577 "Unknown")) {
11578 continue;
11579 }
11580 if (uj) {
11581 json_afi_safi = json_object_new_array();
11582 json_object_object_add(
11583 json_all,
11584 get_afi_safi_str(afi, safi, true),
11585 json_afi_safi);
11586 } else {
11587 json_afi_safi = NULL;
6c9d22e2 11588 }
9ab0cf58
PG
11589
11590 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11591 }
6c9d22e2
PG
11592
11593 if (uj) {
9ab0cf58
PG
11594 vty_out(vty, "%s",
11595 json_object_to_json_string_ext(
11596 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11597 json_object_free(json_all);
4265b261 11598 }
6c9d22e2 11599
4265b261
PG
11600 return CMD_SUCCESS;
11601}
11602
7b2ff250 11603/* BGP route print out function without JSON */
14718643
PG
11604DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11605 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11606 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11607 SHOW_STR
11608 IP_STR
11609 BGP_STR
11610 BGP_INSTANCE_HELP_STR
11611 L2VPN_HELP_STR
11612 EVPN_HELP_STR
11613 "BGP RIB advertisement statistics\n"
11614 JSON_STR)
11615{
ec76a1d1
DA
11616 afi_t afi = AFI_IP6;
11617 safi_t safi = SAFI_UNICAST;
14718643
PG
11618 struct bgp *bgp = NULL;
11619 int idx = 0, ret;
11620 bool uj = use_json(argc, argv);
11621 struct json_object *json_afi_safi = NULL, *json = NULL;
11622
11623 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11624 &bgp, false);
11625 if (!idx)
11626 return CMD_WARNING;
11627
11628 if (uj)
11629 json_afi_safi = json_object_new_array();
11630 else
11631 json_afi_safi = NULL;
11632
11633 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11634
11635 if (uj) {
11636 json = json_object_new_object();
11637 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11638 json_afi_safi);
11639 vty_out(vty, "%s", json_object_to_json_string_ext(
11640 json, JSON_C_TO_STRING_PRETTY));
11641 json_object_free(json);
11642 }
11643 return ret;
11644}
11645
893cccd0 11646/* BGP route print out function without JSON */
9ab0cf58
PG
11647DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11648 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11649 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11650 "]]\
893cccd0 11651 statistics [json]",
9ab0cf58
PG
11652 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11653 BGP_SAFI_WITH_LABEL_HELP_STR
11654 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11655{
ec76a1d1
DA
11656 afi_t afi = AFI_IP6;
11657 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11658 struct bgp *bgp = NULL;
11659 int idx = 0, ret;
11660 bool uj = use_json(argc, argv);
6c9d22e2 11661 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11662
11663 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11664 &bgp, false);
11665 if (!idx)
11666 return CMD_WARNING;
6c9d22e2 11667
893cccd0 11668 if (uj)
6c9d22e2
PG
11669 json_afi_safi = json_object_new_array();
11670 else
11671 json_afi_safi = NULL;
11672
11673 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11674
11675 if (uj) {
11676 json = json_object_new_object();
11677 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11678 json_afi_safi);
9ab0cf58
PG
11679 vty_out(vty, "%s",
11680 json_object_to_json_string_ext(
11681 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11682 json_object_free(json);
11683 }
11684 return ret;
893cccd0 11685}
7b2ff250
DW
11686
11687/* BGP route print out function without JSON */
96f3485c 11688DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11689 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11690 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11691 "]]\
96f3485c 11692 <[all$all] dampening <parameters>\
7b2ff250
DW
11693 |route-map WORD\
11694 |prefix-list WORD\
11695 |filter-list WORD\
7b2ff250
DW
11696 |community-list <(1-500)|WORD> [exact-match]\
11697 |A.B.C.D/M longer-prefixes\
11698 |X:X::X:X/M longer-prefixes\
893cccd0 11699 >",
9ab0cf58
PG
11700 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11701 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11702 "Display the entries for all address families\n"
9ab0cf58
PG
11703 "Display detailed information about dampening\n"
11704 "Display detail of configured dampening parameters\n"
11705 "Display routes matching the route-map\n"
11706 "A route-map to match on\n"
11707 "Display routes conforming to the prefix-list\n"
11708 "Prefix-list name\n"
11709 "Display routes conforming to the filter-list\n"
11710 "Regular expression access list name\n"
11711 "Display routes matching the community-list\n"
11712 "community-list number\n"
11713 "community-list name\n"
11714 "Exact match of the communities\n"
11715 "IPv4 prefix\n"
11716 "Display route and more specific routes\n"
11717 "IPv6 prefix\n"
11718 "Display route and more specific routes\n")
718e3744 11719{
d62a17ae 11720 afi_t afi = AFI_IP6;
11721 safi_t safi = SAFI_UNICAST;
11722 int exact_match = 0;
d62a17ae 11723 struct bgp *bgp = NULL;
11724 int idx = 0;
96f3485c
MK
11725 uint8_t show_flags = 0;
11726
11727 /* [<ipv4|ipv6> [all]] */
11728 if (all) {
11729 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11730 if (argv_find(argv, argc, "ipv4", &idx))
11731 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11732
11733 if (argv_find(argv, argc, "ipv6", &idx))
11734 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11735 }
d62a17ae 11736
11737 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11738 &bgp, false);
d62a17ae 11739 if (!idx)
11740 return CMD_WARNING;
11741
d62a17ae 11742 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11743 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11744 return bgp_show_dampening_parameters(vty, afi, safi,
11745 show_flags);
d62a17ae 11746 }
c016b6c7 11747
d62a17ae 11748 if (argv_find(argv, argc, "prefix-list", &idx))
11749 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11750 safi, bgp_show_type_prefix_list);
11751
11752 if (argv_find(argv, argc, "filter-list", &idx))
11753 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11754 safi, bgp_show_type_filter_list);
11755
d62a17ae 11756 if (argv_find(argv, argc, "route-map", &idx))
11757 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11758 safi, bgp_show_type_route_map);
11759
d62a17ae 11760 if (argv_find(argv, argc, "community-list", &idx)) {
11761 const char *clist_number_or_name = argv[++idx]->arg;
11762 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11763 exact_match = 1;
11764 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11765 exact_match, afi, safi);
11766 }
11767 /* prefix-longer */
11768 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11769 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11770 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11771 safi,
11772 bgp_show_type_prefix_longer);
11773
7b2ff250
DW
11774 return CMD_WARNING;
11775}
11776
11777/* BGP route print out function with JSON */
ae248832 11778DEFPY (show_ip_bgp_json,
7b2ff250
DW
11779 show_ip_bgp_json_cmd,
11780 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11781 [all$all]\
cf4898bc
QY
11782 [cidr-only\
11783 |dampening <flap-statistics|dampened-paths>\
11784 |community [AA:NN|local-AS|no-advertise|no-export\
11785 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11786 |accept-own|accept-own-nexthop|route-filter-v6\
11787 |route-filter-v4|route-filter-translated-v6\
11788 |route-filter-translated-v4] [exact-match]\
ae248832 11789 ] [json$uj | wide$wide]",
7b2ff250
DW
11790 SHOW_STR
11791 IP_STR
11792 BGP_STR
11793 BGP_INSTANCE_HELP_STR
11794 BGP_AFI_HELP_STR
11795 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11796 "Display the entries for all address families\n"
7b2ff250
DW
11797 "Display only routes with non-natural netmasks\n"
11798 "Display detailed information about dampening\n"
11799 "Display flap statistics of routes\n"
11800 "Display paths suppressed due to dampening\n"
11801 "Display routes matching the communities\n"
d0086e8e
AD
11802 COMMUNITY_AANN_STR
11803 "Do not send outside local AS (well-known community)\n"
11804 "Do not advertise to any peer (well-known community)\n"
11805 "Do not export to next AS (well-known community)\n"
11806 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11807 "Do not export to any peer (well-known community)\n"
11808 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11809 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11810 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11811 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11812 "Should accept VPN route with local nexthop (well-known community)\n"
11813 "RT VPNv6 route filtering (well-known community)\n"
11814 "RT VPNv4 route filtering (well-known community)\n"
11815 "RT translated VPNv6 route filtering (well-known community)\n"
11816 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11817 "Exact match of the communities\n"
ae248832
MK
11818 JSON_STR
11819 "Increase table width for longer prefixes\n")
7b2ff250
DW
11820{
11821 afi_t afi = AFI_IP6;
11822 safi_t safi = SAFI_UNICAST;
11823 enum bgp_show_type sh_type = bgp_show_type_normal;
11824 struct bgp *bgp = NULL;
11825 int idx = 0;
d0086e8e 11826 int exact_match = 0;
96f3485c
MK
11827 char *community = NULL;
11828 bool first = true;
11829 uint8_t show_flags = 0;
9f049418 11830
96f3485c
MK
11831
11832 if (uj) {
9f049418 11833 argc--;
96f3485c
MK
11834 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11835 }
11836
11837 /* [<ipv4|ipv6> [all]] */
11838 if (all) {
11839 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11840
11841 if (argv_find(argv, argc, "ipv4", &idx))
11842 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11843
11844 if (argv_find(argv, argc, "ipv6", &idx))
11845 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11846 }
11847
11848 if (wide)
11849 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11850
11851 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11852 &bgp, uj);
7b2ff250
DW
11853 if (!idx)
11854 return CMD_WARNING;
11855
7b2ff250 11856 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11857 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11858
11859 if (argv_find(argv, argc, "dampening", &idx)) {
11860 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11861 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11862 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11863 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11864 }
11865
11866 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11867 char *maybecomm = NULL;
d0086e8e 11868
79bc257a
RW
11869 if (idx + 1 < argc) {
11870 if (argv[idx + 1]->type == VARIABLE_TKN)
11871 maybecomm = argv[idx + 1]->arg;
11872 else
11873 maybecomm = argv[idx + 1]->text;
11874 }
11875
cf4898bc
QY
11876 if (maybecomm && !strmatch(maybecomm, "json")
11877 && !strmatch(maybecomm, "exact-match"))
11878 community = maybecomm;
d0086e8e 11879
cf4898bc
QY
11880 if (argv_find(argv, argc, "exact-match", &idx))
11881 exact_match = 1;
d0086e8e 11882
96f3485c
MK
11883 if (!community)
11884 sh_type = bgp_show_type_community_all;
11885 }
11886
11887 if (!all) {
11888 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11889 if (community)
11890 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11891 exact_match, afi, safi,
11892 show_flags);
cf4898bc 11893 else
96f3485c
MK
11894 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11895 show_flags);
11896 } else {
11897 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11898 * AFI_IP6 */
11899
11900 if (uj)
11901 vty_out(vty, "{\n");
11902
11903 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11904 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11905 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11906 ? AFI_IP
11907 : AFI_IP6;
11908 FOREACH_SAFI (safi) {
96f3485c
MK
11909 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11910 continue;
11911
11912 if (uj) {
11913 if (first)
11914 first = false;
11915 else
11916 vty_out(vty, ",\n");
11917 vty_out(vty, "\"%s\":{\n",
11918 get_afi_safi_str(afi, safi,
11919 true));
11920 } else
11921 vty_out(vty,
11922 "\nFor address family: %s\n",
11923 get_afi_safi_str(afi, safi,
11924 false));
11925
11926 if (community)
11927 bgp_show_community(vty, bgp, community,
11928 exact_match, afi,
11929 safi, show_flags);
11930 else
11931 bgp_show(vty, bgp, afi, safi, sh_type,
11932 NULL, show_flags);
11933 if (uj)
11934 vty_out(vty, "}\n");
11935 }
11936 } else {
11937 /* show <ip> bgp all: for each AFI and SAFI*/
11938 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
11939 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11940 continue;
11941
11942 if (uj) {
11943 if (first)
11944 first = false;
11945 else
11946 vty_out(vty, ",\n");
d0086e8e 11947
96f3485c
MK
11948 vty_out(vty, "\"%s\":{\n",
11949 get_afi_safi_str(afi, safi,
11950 true));
11951 } else
11952 vty_out(vty,
11953 "\nFor address family: %s\n",
11954 get_afi_safi_str(afi, safi,
11955 false));
11956
11957 if (community)
11958 bgp_show_community(vty, bgp, community,
11959 exact_match, afi,
11960 safi, show_flags);
11961 else
11962 bgp_show(vty, bgp, afi, safi, sh_type,
11963 NULL, show_flags);
11964 if (uj)
11965 vty_out(vty, "}\n");
11966 }
11967 }
11968 if (uj)
11969 vty_out(vty, "}\n");
11970 }
11971 return CMD_SUCCESS;
a636c635 11972}
47fc97cc 11973
718e3744 11974DEFUN (show_ip_bgp_route,
11975 show_ip_bgp_route_cmd,
3efd0893 11976 "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>] [json]",
718e3744 11977 SHOW_STR
11978 IP_STR
11979 BGP_STR
a636c635 11980 BGP_INSTANCE_HELP_STR
4f280b15 11981 BGP_AFI_HELP_STR
4dd6177e 11982 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11983 "Network in the BGP routing table to display\n"
0c7b1b01 11984 "IPv4 prefix\n"
8c3deaae 11985 "Network in the BGP routing table to display\n"
0c7b1b01 11986 "IPv6 prefix\n"
4092b06c 11987 "Display only the bestpath\n"
b05a1c8b 11988 "Display only multipaths\n"
9973d184 11989 JSON_STR)
4092b06c 11990{
d62a17ae 11991 int prefix_check = 0;
ae19d7dd 11992
d62a17ae 11993 afi_t afi = AFI_IP6;
11994 safi_t safi = SAFI_UNICAST;
11995 char *prefix = NULL;
11996 struct bgp *bgp = NULL;
11997 enum bgp_path_type path_type;
9f049418 11998 bool uj = use_json(argc, argv);
b05a1c8b 11999
d62a17ae 12000 int idx = 0;
ae19d7dd 12001
d62a17ae 12002 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12003 &bgp, uj);
d62a17ae 12004 if (!idx)
12005 return CMD_WARNING;
c41247f5 12006
d62a17ae 12007 if (!bgp) {
12008 vty_out(vty,
12009 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12010 return CMD_WARNING;
12011 }
a636c635 12012
d62a17ae 12013 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12014 if (argv_find(argv, argc, "A.B.C.D", &idx)
12015 || argv_find(argv, argc, "X:X::X:X", &idx))
12016 prefix_check = 0;
12017 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12018 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12019 prefix_check = 1;
12020
12021 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12022 && afi != AFI_IP6) {
12023 vty_out(vty,
12024 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12025 return CMD_WARNING;
12026 }
12027 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12028 && afi != AFI_IP) {
12029 vty_out(vty,
12030 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12031 return CMD_WARNING;
12032 }
12033
12034 prefix = argv[idx]->arg;
12035
12036 /* [<bestpath|multipath>] */
12037 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12038 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12039 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12040 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12041 else
360660c6 12042 path_type = BGP_PATH_SHOW_ALL;
a636c635 12043
d62a17ae 12044 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
12045 path_type, uj);
4092b06c
DS
12046}
12047
8c3deaae
QY
12048DEFUN (show_ip_bgp_regexp,
12049 show_ip_bgp_regexp_cmd,
3e5b31b3 12050 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12051 SHOW_STR
12052 IP_STR
12053 BGP_STR
b00b230a 12054 BGP_INSTANCE_HELP_STR
4f280b15 12055 BGP_AFI_HELP_STR
4dd6177e 12056 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12057 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12058 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12059 JSON_STR)
8c3deaae 12060{
d62a17ae 12061 afi_t afi = AFI_IP6;
12062 safi_t safi = SAFI_UNICAST;
12063 struct bgp *bgp = NULL;
3e5b31b3
DA
12064 bool uj = use_json(argc, argv);
12065 char *regstr = NULL;
8c3deaae 12066
d62a17ae 12067 int idx = 0;
12068 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12069 &bgp, false);
d62a17ae 12070 if (!idx)
12071 return CMD_WARNING;
8c3deaae 12072
d62a17ae 12073 // get index of regex
3e5b31b3
DA
12074 if (argv_find(argv, argc, "REGEX", &idx))
12075 regstr = argv[idx]->arg;
8c3deaae 12076
5f71d11c 12077 assert(regstr);
3e5b31b3
DA
12078 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12079 bgp_show_type_regexp, uj);
8c3deaae
QY
12080}
12081
ae248832 12082DEFPY (show_ip_bgp_instance_all,
a636c635 12083 show_ip_bgp_instance_all_cmd,
ae248832 12084 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12085 SHOW_STR
a636c635 12086 IP_STR
4092b06c 12087 BGP_STR
a636c635 12088 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12089 BGP_AFI_HELP_STR
4dd6177e 12090 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12091 JSON_STR
12092 "Increase table width for longer prefixes\n")
4092b06c 12093{
d62a17ae 12094 afi_t afi = AFI_IP;
12095 safi_t safi = SAFI_UNICAST;
12096 struct bgp *bgp = NULL;
d62a17ae 12097 int idx = 0;
96f3485c 12098 uint8_t show_flags = 0;
ae19d7dd 12099
96f3485c 12100 if (uj) {
d62a17ae 12101 argc--;
96f3485c
MK
12102 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12103 }
12104
12105 if (wide)
12106 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12107
9f049418
DS
12108 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12109 &bgp, uj);
12110 if (!idx)
12111 return CMD_WARNING;
12112
96f3485c 12113 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12114 return CMD_SUCCESS;
e3e29b32
LB
12115}
12116
a4d82a8a 12117static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12118 afi_t afi, safi_t safi, enum bgp_show_type type,
12119 bool use_json)
718e3744 12120{
d62a17ae 12121 regex_t *regex;
12122 int rc;
96f3485c
MK
12123 uint8_t show_flags = 0;
12124
12125 if (use_json)
12126 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12127
c3900853 12128 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12129 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12130 regstr);
12131 return CMD_WARNING_CONFIG_FAILED;
12132 }
12133
d62a17ae 12134 regex = bgp_regcomp(regstr);
12135 if (!regex) {
12136 vty_out(vty, "Can't compile regexp %s\n", regstr);
12137 return CMD_WARNING;
12138 }
a636c635 12139
96f3485c 12140 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 12141 bgp_regex_free(regex);
12142 return rc;
e3e29b32
LB
12143}
12144
d62a17ae 12145static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12146 const char *prefix_list_str, afi_t afi,
12147 safi_t safi, enum bgp_show_type type)
e3e29b32 12148{
d62a17ae 12149 struct prefix_list *plist;
96f3485c 12150 uint8_t show_flags = 0;
718e3744 12151
d62a17ae 12152 plist = prefix_list_lookup(afi, prefix_list_str);
12153 if (plist == NULL) {
12154 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12155 prefix_list_str);
12156 return CMD_WARNING;
12157 }
718e3744 12158
96f3485c 12159 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
12160}
12161
d62a17ae 12162static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12163 const char *filter, afi_t afi, safi_t safi,
12164 enum bgp_show_type type)
4092b06c 12165{
d62a17ae 12166 struct as_list *as_list;
96f3485c 12167 uint8_t show_flags = 0;
718e3744 12168
d62a17ae 12169 as_list = as_list_lookup(filter);
12170 if (as_list == NULL) {
12171 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12172 filter);
12173 return CMD_WARNING;
12174 }
a636c635 12175
96f3485c 12176 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12177}
12178
d62a17ae 12179static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12180 const char *rmap_str, afi_t afi, safi_t safi,
12181 enum bgp_show_type type)
718e3744 12182{
d62a17ae 12183 struct route_map *rmap;
96f3485c 12184 uint8_t show_flags = 0;
bb46e94f 12185
d62a17ae 12186 rmap = route_map_lookup_by_name(rmap_str);
12187 if (!rmap) {
12188 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12189 return CMD_WARNING;
12190 }
12191
96f3485c 12192 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12193}
12194
7f323236
DW
12195static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12196 const char *comstr, int exact, afi_t afi,
96f3485c 12197 safi_t safi, uint8_t show_flags)
d62a17ae 12198{
12199 struct community *com;
d62a17ae 12200 int ret = 0;
12201
7f323236 12202 com = community_str2com(comstr);
d62a17ae 12203 if (!com) {
7f323236 12204 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12205 return CMD_WARNING;
12206 }
12207
12208 ret = bgp_show(vty, bgp, afi, safi,
12209 (exact ? bgp_show_type_community_exact
12210 : bgp_show_type_community),
96f3485c 12211 com, show_flags);
3c1f53de 12212 community_free(&com);
46c3ce83 12213
d62a17ae 12214 return ret;
718e3744 12215}
12216
d62a17ae 12217static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12218 const char *com, int exact, afi_t afi,
12219 safi_t safi)
50ef26d4 12220{
d62a17ae 12221 struct community_list *list;
96f3485c 12222 uint8_t show_flags = 0;
50ef26d4 12223
e237b0d2 12224 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12225 if (list == NULL) {
12226 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12227 return CMD_WARNING;
12228 }
718e3744 12229
d62a17ae 12230 return bgp_show(vty, bgp, afi, safi,
12231 (exact ? bgp_show_type_community_list_exact
12232 : bgp_show_type_community_list),
96f3485c 12233 list, show_flags);
50ef26d4 12234}
12235
d62a17ae 12236static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12237 const char *prefix, afi_t afi, safi_t safi,
12238 enum bgp_show_type type)
718e3744 12239{
d62a17ae 12240 int ret;
12241 struct prefix *p;
96f3485c 12242 uint8_t show_flags = 0;
47fc97cc 12243
d62a17ae 12244 p = prefix_new();
95cbbd2a 12245
d62a17ae 12246 ret = str2prefix(prefix, p);
12247 if (!ret) {
12248 vty_out(vty, "%% Malformed Prefix\n");
12249 return CMD_WARNING;
12250 }
47e9b292 12251
96f3485c 12252 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12253 prefix_free(&p);
d62a17ae 12254 return ret;
12255}
12256
d62a17ae 12257enum bgp_stats {
12258 BGP_STATS_MAXBITLEN = 0,
12259 BGP_STATS_RIB,
12260 BGP_STATS_PREFIXES,
12261 BGP_STATS_TOTPLEN,
12262 BGP_STATS_UNAGGREGATEABLE,
12263 BGP_STATS_MAX_AGGREGATEABLE,
12264 BGP_STATS_AGGREGATES,
12265 BGP_STATS_SPACE,
12266 BGP_STATS_ASPATH_COUNT,
12267 BGP_STATS_ASPATH_MAXHOPS,
12268 BGP_STATS_ASPATH_TOTHOPS,
12269 BGP_STATS_ASPATH_MAXSIZE,
12270 BGP_STATS_ASPATH_TOTSIZE,
12271 BGP_STATS_ASN_HIGHEST,
12272 BGP_STATS_MAX,
a636c635 12273};
2815e61f 12274
9ab0cf58 12275#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12276#define TABLE_STATS_IDX_JSON 1
12277
12278static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12279 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12280 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12281 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12282 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12283 "unaggregateablePrefixes"},
12284 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12285 "maximumAggregateablePrefixes"},
12286 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12287 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12288 [BGP_STATS_SPACE] = {"Address space advertised",
12289 "addressSpaceAdvertised"},
9ab0cf58
PG
12290 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12291 "advertisementsWithPaths"},
12292 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12293 "longestAsPath"},
12294 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12295 "largestAsPath"},
12296 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12297 "averageAsPathLengthHops"},
12298 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12299 "averageAsPathSizeBytes"},
12300 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12301 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12302};
2815e61f 12303
d62a17ae 12304struct bgp_table_stats {
12305 struct bgp_table *table;
12306 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12307 double total_space;
ff7924f6
PJ
12308};
12309
9bcb3eef 12310static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12311 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12312{
9bcb3eef 12313 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12314 struct bgp_path_info *pi;
b54892e0 12315 const struct prefix *rn_p;
d62a17ae 12316
9bcb3eef 12317 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12318 return;
d62a17ae 12319
9bcb3eef 12320 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12321 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12322 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12323
9c14ec72 12324 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12325 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12326 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12327
9bcb3eef 12328 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12329 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12330 /* announced address space */
12331 if (space)
b54892e0 12332 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12333 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12334 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12335
9c14ec72 12336
9bcb3eef 12337 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12338 ts->counts[BGP_STATS_RIB]++;
12339
05864da7
DS
12340 if (CHECK_FLAG(pi->attr->flag,
12341 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12342 ts->counts[BGP_STATS_AGGREGATES]++;
12343
12344 /* as-path stats */
05864da7 12345 if (pi->attr->aspath) {
9c14ec72
RW
12346 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12347 unsigned int size = aspath_size(pi->attr->aspath);
12348 as_t highest = aspath_highest(pi->attr->aspath);
12349
12350 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12351
12352 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12353 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12354
12355 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12356 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12357
12358 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12359 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12360 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12361 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12362 }
12363 }
12364}
12365
12366static int bgp_table_stats_walker(struct thread *t)
12367{
9bcb3eef
DS
12368 struct bgp_dest *dest, *ndest;
12369 struct bgp_dest *top;
9c14ec72
RW
12370 struct bgp_table_stats *ts = THREAD_ARG(t);
12371 unsigned int space = 0;
12372
12373 if (!(top = bgp_table_top(ts->table)))
12374 return 0;
12375
12376 switch (ts->table->afi) {
12377 case AFI_IP:
12378 space = IPV4_MAX_BITLEN;
12379 break;
12380 case AFI_IP6:
12381 space = IPV6_MAX_BITLEN;
12382 break;
12383 default:
12384 return 0;
12385 }
12386
12387 ts->counts[BGP_STATS_MAXBITLEN] = space;
12388
9bcb3eef 12389 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12390 if (ts->table->safi == SAFI_MPLS_VPN
12391 || ts->table->safi == SAFI_ENCAP
12392 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12393 struct bgp_table *table;
12394
9bcb3eef 12395 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12396 if (!table)
12397 continue;
12398
12399 top = bgp_table_top(table);
9bcb3eef
DS
12400 for (ndest = bgp_table_top(table); ndest;
12401 ndest = bgp_route_next(ndest))
12402 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12403 } else {
9bcb3eef 12404 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12405 }
12406 }
9c14ec72 12407
d62a17ae 12408 return 0;
2815e61f 12409}
ff7924f6 12410
71f1613a
DA
12411static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12412 struct json_object *json_array)
12413{
12414 struct listnode *node, *nnode;
12415 struct bgp *bgp;
12416
12417 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12418 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12419}
12420
12421static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12422 safi_t safi, struct json_object *json_array)
2815e61f 12423{
d62a17ae 12424 struct bgp_table_stats ts;
12425 unsigned int i;
893cccd0
PG
12426 int ret = CMD_SUCCESS;
12427 char temp_buf[20];
6c9d22e2
PG
12428 struct json_object *json = NULL;
12429
12430 if (json_array)
12431 json = json_object_new_object();
019386c2 12432
d62a17ae 12433 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12434 char warning_msg[50];
12435
12436 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12437 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12438 safi);
6c9d22e2
PG
12439
12440 if (!json)
893cccd0
PG
12441 vty_out(vty, "%s\n", warning_msg);
12442 else
9ab0cf58 12443 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12444
893cccd0
PG
12445 ret = CMD_WARNING;
12446 goto end_table_stats;
d62a17ae 12447 }
019386c2 12448
893cccd0 12449 if (!json)
5290ceab
DA
12450 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12451 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12452 else
12453 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12454
d62a17ae 12455 /* labeled-unicast routes live in the unicast table */
12456 if (safi == SAFI_LABELED_UNICAST)
12457 safi = SAFI_UNICAST;
019386c2 12458
d62a17ae 12459 memset(&ts, 0, sizeof(ts));
12460 ts.table = bgp->rib[afi][safi];
12461 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12462
d62a17ae 12463 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12464 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12465 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12466 continue;
12467
12468 switch (i) {
d62a17ae 12469 case BGP_STATS_ASPATH_TOTHOPS:
12470 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12471 if (!json) {
9ab0cf58
PG
12472 snprintf(
12473 temp_buf, sizeof(temp_buf), "%12.2f",
12474 ts.counts[i]
12475 ? (float)ts.counts[i]
12476 / (float)ts.counts
12477 [BGP_STATS_ASPATH_COUNT]
12478 : 0);
893cccd0 12479 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12480 table_stats_strs[i]
12481 [TABLE_STATS_IDX_VTY],
893cccd0 12482 temp_buf);
9ab0cf58
PG
12483 } else {
12484 json_object_double_add(
12485 json,
12486 table_stats_strs[i]
12487 [TABLE_STATS_IDX_JSON],
12488 ts.counts[i]
12489 ? (double)ts.counts[i]
12490 / (double)ts.counts
d62a17ae 12491 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12492 : 0);
12493 }
d62a17ae 12494 break;
12495 case BGP_STATS_TOTPLEN:
6c9d22e2 12496 if (!json) {
9ab0cf58
PG
12497 snprintf(
12498 temp_buf, sizeof(temp_buf), "%12.2f",
12499 ts.counts[i]
12500 ? (float)ts.counts[i]
12501 / (float)ts.counts
12502 [BGP_STATS_PREFIXES]
12503 : 0);
893cccd0 12504 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12505 table_stats_strs[i]
12506 [TABLE_STATS_IDX_VTY],
893cccd0 12507 temp_buf);
9ab0cf58
PG
12508 } else {
12509 json_object_double_add(
12510 json,
12511 table_stats_strs[i]
12512 [TABLE_STATS_IDX_JSON],
12513 ts.counts[i]
12514 ? (double)ts.counts[i]
12515 / (double)ts.counts
d62a17ae 12516 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12517 : 0);
12518 }
d62a17ae 12519 break;
12520 case BGP_STATS_SPACE:
6c9d22e2
PG
12521 if (!json) {
12522 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12523 ts.total_space);
893cccd0 12524 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12525 table_stats_strs[i]
12526 [TABLE_STATS_IDX_VTY],
893cccd0 12527 temp_buf);
9ab0cf58
PG
12528 } else {
12529 json_object_double_add(
12530 json,
12531 table_stats_strs[i]
12532 [TABLE_STATS_IDX_JSON],
12533 (double)ts.total_space);
12534 }
8d0ab76d 12535 if (afi == AFI_IP6) {
6c9d22e2
PG
12536 if (!json) {
12537 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12538 "%12g",
12539 ts.total_space
12540 * pow(2.0, -128 + 32));
6c9d22e2
PG
12541 vty_out(vty, "%30s: %s\n",
12542 "/32 equivalent %s\n",
12543 temp_buf);
9ab0cf58
PG
12544 } else {
12545 json_object_double_add(
12546 json, "/32equivalent",
12547 (double)(ts.total_space
12548 * pow(2.0,
12549 -128 + 32)));
12550 }
6c9d22e2
PG
12551 if (!json) {
12552 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12553 "%12g",
12554 ts.total_space
12555 * pow(2.0, -128 + 48));
6c9d22e2
PG
12556 vty_out(vty, "%30s: %s\n",
12557 "/48 equivalent %s\n",
12558 temp_buf);
9ab0cf58
PG
12559 } else {
12560 json_object_double_add(
12561 json, "/48equivalent",
12562 (double)(ts.total_space
12563 * pow(2.0,
12564 -128 + 48)));
12565 }
8d0ab76d 12566 } else {
6c9d22e2
PG
12567 if (!json) {
12568 snprintf(temp_buf, sizeof(temp_buf),
12569 "%12.2f",
9ab0cf58
PG
12570 ts.total_space * 100.
12571 * pow(2.0, -32));
6c9d22e2 12572 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12573 "% announced ", temp_buf);
12574 } else {
12575 json_object_double_add(
12576 json, "%announced",
12577 (double)(ts.total_space * 100.
12578 * pow(2.0, -32)));
12579 }
6c9d22e2
PG
12580 if (!json) {
12581 snprintf(temp_buf, sizeof(temp_buf),
12582 "%12.2f",
9ab0cf58
PG
12583 ts.total_space
12584 * pow(2.0, -32 + 8));
6c9d22e2
PG
12585 vty_out(vty, "%30s: %s\n",
12586 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12587 } else {
12588 json_object_double_add(
12589 json, "/8equivalent",
12590 (double)(ts.total_space
12591 * pow(2.0, -32 + 8)));
12592 }
6c9d22e2
PG
12593 if (!json) {
12594 snprintf(temp_buf, sizeof(temp_buf),
12595 "%12.2f",
9ab0cf58
PG
12596 ts.total_space
12597 * pow(2.0, -32 + 24));
6c9d22e2 12598 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12599 "/24 equivalent ", temp_buf);
12600 } else {
12601 json_object_double_add(
12602 json, "/24equivalent",
12603 (double)(ts.total_space
12604 * pow(2.0, -32 + 24)));
12605 }
8d0ab76d 12606 }
d62a17ae 12607 break;
12608 default:
6c9d22e2
PG
12609 if (!json) {
12610 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12611 ts.counts[i]);
893cccd0 12612 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12613 table_stats_strs[i]
12614 [TABLE_STATS_IDX_VTY],
12615 temp_buf);
12616 } else {
12617 json_object_int_add(
12618 json,
12619 table_stats_strs[i]
12620 [TABLE_STATS_IDX_JSON],
12621 ts.counts[i]);
12622 }
d62a17ae 12623 }
893cccd0
PG
12624 if (!json)
12625 vty_out(vty, "\n");
d62a17ae 12626 }
9ab0cf58 12627end_table_stats:
6c9d22e2
PG
12628 if (json)
12629 json_object_array_add(json_array, json);
893cccd0 12630 return ret;
d62a17ae 12631}
12632
71f1613a
DA
12633static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12634 safi_t safi, struct json_object *json_array)
12635{
12636 if (!bgp) {
12637 bgp_table_stats_all(vty, afi, safi, json_array);
12638 return CMD_SUCCESS;
12639 }
12640
12641 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12642}
12643
d62a17ae 12644enum bgp_pcounts {
12645 PCOUNT_ADJ_IN = 0,
12646 PCOUNT_DAMPED,
12647 PCOUNT_REMOVED,
12648 PCOUNT_HISTORY,
12649 PCOUNT_STALE,
12650 PCOUNT_VALID,
12651 PCOUNT_ALL,
12652 PCOUNT_COUNTED,
7e3d9632 12653 PCOUNT_BPATH_SELECTED,
d62a17ae 12654 PCOUNT_PFCNT, /* the figure we display to users */
12655 PCOUNT_MAX,
a636c635 12656};
718e3744 12657
2b64873d 12658static const char *const pcount_strs[] = {
9d303b37
DL
12659 [PCOUNT_ADJ_IN] = "Adj-in",
12660 [PCOUNT_DAMPED] = "Damped",
12661 [PCOUNT_REMOVED] = "Removed",
12662 [PCOUNT_HISTORY] = "History",
12663 [PCOUNT_STALE] = "Stale",
12664 [PCOUNT_VALID] = "Valid",
12665 [PCOUNT_ALL] = "All RIB",
12666 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12667 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12668 [PCOUNT_PFCNT] = "Useable",
12669 [PCOUNT_MAX] = NULL,
a636c635 12670};
718e3744 12671
d62a17ae 12672struct peer_pcounts {
12673 unsigned int count[PCOUNT_MAX];
12674 const struct peer *peer;
12675 const struct bgp_table *table;
54317cba 12676 safi_t safi;
a636c635 12677};
47fc97cc 12678
9bcb3eef 12679static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12680{
54317cba
JW
12681 const struct bgp_adj_in *ain;
12682 const struct bgp_path_info *pi;
d62a17ae 12683 const struct peer *peer = pc->peer;
12684
54317cba
JW
12685 for (ain = rn->adj_in; ain; ain = ain->next)
12686 if (ain->peer == peer)
12687 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12688
9bcb3eef 12689 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12690
54317cba
JW
12691 if (pi->peer != peer)
12692 continue;
d62a17ae 12693
54317cba 12694 pc->count[PCOUNT_ALL]++;
d62a17ae 12695
54317cba
JW
12696 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12697 pc->count[PCOUNT_DAMPED]++;
12698 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12699 pc->count[PCOUNT_HISTORY]++;
12700 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12701 pc->count[PCOUNT_REMOVED]++;
12702 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12703 pc->count[PCOUNT_STALE]++;
12704 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12705 pc->count[PCOUNT_VALID]++;
12706 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12707 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12708 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12709 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12710
12711 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12712 pc->count[PCOUNT_COUNTED]++;
12713 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12714 flog_err(
12715 EC_LIB_DEVELOPMENT,
12716 "Attempting to count but flags say it is unusable");
12717 } else {
40381db7 12718 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12719 flog_err(
12720 EC_LIB_DEVELOPMENT,
12721 "Not counted but flags say we should");
d62a17ae 12722 }
12723 }
54317cba
JW
12724}
12725
12726static int bgp_peer_count_walker(struct thread *t)
12727{
9bcb3eef 12728 struct bgp_dest *rn, *rm;
54317cba
JW
12729 const struct bgp_table *table;
12730 struct peer_pcounts *pc = THREAD_ARG(t);
12731
12732 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12733 || pc->safi == SAFI_EVPN) {
12734 /* Special handling for 2-level routing tables. */
12735 for (rn = bgp_table_top(pc->table); rn;
12736 rn = bgp_route_next(rn)) {
9bcb3eef 12737 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12738 if (table != NULL)
12739 for (rm = bgp_table_top(table); rm;
12740 rm = bgp_route_next(rm))
12741 bgp_peer_count_proc(rm, pc);
12742 }
12743 } else
12744 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12745 bgp_peer_count_proc(rn, pc);
12746
d62a17ae 12747 return 0;
718e3744 12748}
12749
d62a17ae 12750static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12751 safi_t safi, bool use_json)
856ca177 12752{
d62a17ae 12753 struct peer_pcounts pcounts = {.peer = peer};
12754 unsigned int i;
12755 json_object *json = NULL;
12756 json_object *json_loop = NULL;
856ca177 12757
d62a17ae 12758 if (use_json) {
12759 json = json_object_new_object();
12760 json_loop = json_object_new_object();
12761 }
718e3744 12762
d62a17ae 12763 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12764 || !peer->bgp->rib[afi][safi]) {
12765 if (use_json) {
12766 json_object_string_add(
12767 json, "warning",
12768 "No such neighbor or address family");
12769 vty_out(vty, "%s\n", json_object_to_json_string(json));
12770 json_object_free(json);
d5f20468 12771 json_object_free(json_loop);
d62a17ae 12772 } else
12773 vty_out(vty, "%% No such neighbor or address family\n");
12774
12775 return CMD_WARNING;
12776 }
2a71e9ce 12777
d62a17ae 12778 memset(&pcounts, 0, sizeof(pcounts));
12779 pcounts.peer = peer;
12780 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12781 pcounts.safi = safi;
d62a17ae 12782
12783 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12784 * stats for the thread-walk (i.e. ensure this can't be blamed on
12785 * on just vty_read()).
12786 */
d62a17ae 12787 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12788
12789 if (use_json) {
12790 json_object_string_add(json, "prefixCountsFor", peer->host);
12791 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12792 get_afi_safi_str(afi, safi, true));
d62a17ae 12793 json_object_int_add(json, "pfxCounter",
12794 peer->pcount[afi][safi]);
12795
12796 for (i = 0; i < PCOUNT_MAX; i++)
12797 json_object_int_add(json_loop, pcount_strs[i],
12798 pcounts.count[i]);
12799
12800 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12801
12802 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12803 json_object_string_add(json, "pfxctDriftFor",
12804 peer->host);
12805 json_object_string_add(
12806 json, "recommended",
12807 "Please report this bug, with the above command output");
12808 }
996c9314
LB
12809 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12810 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12811 json_object_free(json);
12812 } else {
12813
12814 if (peer->hostname
892fedb6 12815 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12816 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12817 peer->hostname, peer->host,
5cb5f4d0 12818 get_afi_safi_str(afi, safi, false));
d62a17ae 12819 } else {
12820 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12821 get_afi_safi_str(afi, safi, false));
d62a17ae 12822 }
12823
6cde4b45 12824 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12825 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12826
12827 for (i = 0; i < PCOUNT_MAX; i++)
12828 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12829 pcounts.count[i]);
12830
12831 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12832 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12833 vty_out(vty,
12834 "Please report this bug, with the above command output\n");
12835 }
12836 }
12837
12838 return CMD_SUCCESS;
718e3744 12839}
12840
a636c635
DW
12841DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12842 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12843 "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 12844 SHOW_STR
12845 IP_STR
12846 BGP_STR
8386ac43 12847 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12848 BGP_AFI_HELP_STR
12849 BGP_SAFI_HELP_STR
0b16f239
DS
12850 "Detailed information on TCP and BGP neighbor connections\n"
12851 "Neighbor to display information about\n"
12852 "Neighbor to display information about\n"
91d37724 12853 "Neighbor on BGP configured interface\n"
a636c635 12854 "Display detailed prefix count information\n"
9973d184 12855 JSON_STR)
0b16f239 12856{
d62a17ae 12857 afi_t afi = AFI_IP6;
12858 safi_t safi = SAFI_UNICAST;
12859 struct peer *peer;
12860 int idx = 0;
12861 struct bgp *bgp = NULL;
9f049418
DS
12862 bool uj = use_json(argc, argv);
12863
12864 if (uj)
12865 argc--;
856ca177 12866
d62a17ae 12867 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12868 &bgp, uj);
d62a17ae 12869 if (!idx)
12870 return CMD_WARNING;
0b16f239 12871
d62a17ae 12872 argv_find(argv, argc, "neighbors", &idx);
12873 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12874 if (!peer)
12875 return CMD_WARNING;
bb46e94f 12876
29c8d9da 12877 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12878}
0b16f239 12879
d6902373
PG
12880#ifdef KEEP_OLD_VPN_COMMANDS
12881DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12882 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12883 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12884 SHOW_STR
12885 IP_STR
12886 BGP_STR
d6902373 12887 BGP_VPNVX_HELP_STR
91d37724 12888 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12889 "Detailed information on TCP and BGP neighbor connections\n"
12890 "Neighbor to display information about\n"
12891 "Neighbor to display information about\n"
91d37724 12892 "Neighbor on BGP configured interface\n"
a636c635 12893 "Display detailed prefix count information\n"
9973d184 12894 JSON_STR)
a636c635 12895{
d62a17ae 12896 int idx_peer = 6;
12897 struct peer *peer;
9f049418 12898 bool uj = use_json(argc, argv);
a636c635 12899
d62a17ae 12900 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12901 if (!peer)
12902 return CMD_WARNING;
12903
12904 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12905}
12906
d6902373
PG
12907DEFUN (show_ip_bgp_vpn_all_route_prefix,
12908 show_ip_bgp_vpn_all_route_prefix_cmd,
12909 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12910 SHOW_STR
12911 IP_STR
12912 BGP_STR
d6902373 12913 BGP_VPNVX_HELP_STR
91d37724
QY
12914 "Display information about all VPNv4 NLRIs\n"
12915 "Network in the BGP routing table to display\n"
3a2d747c 12916 "Network in the BGP routing table to display\n"
9973d184 12917 JSON_STR)
91d37724 12918{
d62a17ae 12919 int idx = 0;
12920 char *network = NULL;
12921 struct bgp *bgp = bgp_get_default();
12922 if (!bgp) {
12923 vty_out(vty, "Can't find default instance\n");
12924 return CMD_WARNING;
12925 }
87e34b58 12926
d62a17ae 12927 if (argv_find(argv, argc, "A.B.C.D", &idx))
12928 network = argv[idx]->arg;
12929 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12930 network = argv[idx]->arg;
12931 else {
12932 vty_out(vty, "Unable to figure out Network\n");
12933 return CMD_WARNING;
12934 }
87e34b58 12935
d62a17ae 12936 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12937 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12938}
d6902373 12939#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12940
44c69747
LK
12941DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12942 show_bgp_l2vpn_evpn_route_prefix_cmd,
12943 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12944 SHOW_STR
4c63a661
PG
12945 BGP_STR
12946 L2VPN_HELP_STR
12947 EVPN_HELP_STR
44c69747
LK
12948 "Network in the BGP routing table to display\n"
12949 "Network in the BGP routing table to display\n"
4c63a661
PG
12950 "Network in the BGP routing table to display\n"
12951 "Network in the BGP routing table to display\n"
12952 JSON_STR)
12953{
d62a17ae 12954 int idx = 0;
12955 char *network = NULL;
44c69747 12956 int prefix_check = 0;
a636c635 12957
44c69747
LK
12958 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12959 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12960 network = argv[idx]->arg;
44c69747 12961 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12962 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12963 network = argv[idx]->arg;
44c69747
LK
12964 prefix_check = 1;
12965 } else {
d62a17ae 12966 vty_out(vty, "Unable to figure out Network\n");
12967 return CMD_WARNING;
12968 }
44c69747
LK
12969 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12970 prefix_check, BGP_PATH_SHOW_ALL,
12971 use_json(argc, argv));
d62a17ae 12972}
12973
2f9bc755
DS
12974static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12975 struct bgp_table *table, int *header1,
12976 int *header2, json_object *json,
12977 json_object *json_scode,
12978 json_object *json_ocode, bool wide)
12979{
12980 uint64_t version = table ? table->version : 0;
23d0a753 12981 char buf[BUFSIZ] = {0};
2f9bc755
DS
12982
12983 if (*header1) {
12984 if (json) {
12985 json_object_int_add(json, "bgpTableVersion", version);
12986 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12987 inet_ntop(AF_INET,
12988 &bgp->router_id, buf,
12989 sizeof(buf)));
2f9bc755
DS
12990 json_object_int_add(json, "defaultLocPrf",
12991 bgp->default_local_pref);
12992 json_object_int_add(json, "localAS", bgp->as);
12993 json_object_object_add(json, "bgpStatusCodes",
12994 json_scode);
12995 json_object_object_add(json, "bgpOriginCodes",
12996 json_ocode);
12997 } else {
12998 vty_out(vty,
23d0a753
DA
12999 "BGP table version is %" PRIu64
13000 ", local router ID is %pI4, vrf id ",
13001 version, &bgp->router_id);
2f9bc755
DS
13002 if (bgp->vrf_id == VRF_UNKNOWN)
13003 vty_out(vty, "%s", VRFID_NONE_STR);
13004 else
13005 vty_out(vty, "%u", bgp->vrf_id);
13006 vty_out(vty, "\n");
13007 vty_out(vty, "Default local pref %u, ",
13008 bgp->default_local_pref);
13009 vty_out(vty, "local AS %u\n", bgp->as);
13010 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13011 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13012 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13013 }
13014 *header1 = 0;
13015 }
13016 if (*header2) {
13017 if (!json)
13018 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13019 : BGP_SHOW_HEADER));
13020 *header2 = 0;
13021 }
13022}
13023
d62a17ae 13024static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13025 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
13026 const char *rmap_name, json_object *json,
13027 uint8_t show_flags)
d62a17ae 13028{
13029 struct bgp_table *table;
13030 struct bgp_adj_in *ain;
13031 struct bgp_adj_out *adj;
74a630b6
NT
13032 unsigned long output_count = 0;
13033 unsigned long filtered_count = 0;
9bcb3eef 13034 struct bgp_dest *dest;
d62a17ae 13035 int header1 = 1;
13036 struct bgp *bgp;
13037 int header2 = 1;
13038 struct attr attr;
13039 int ret;
13040 struct update_subgroup *subgrp;
13041 json_object *json_scode = NULL;
13042 json_object *json_ocode = NULL;
13043 json_object *json_ar = NULL;
13044 struct peer_af *paf;
f99def61 13045 bool route_filtered;
96f3485c
MK
13046 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13047 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 13048
13049 if (use_json) {
13050 json_scode = json_object_new_object();
13051 json_ocode = json_object_new_object();
13052 json_ar = json_object_new_object();
13053
13054 json_object_string_add(json_scode, "suppressed", "s");
13055 json_object_string_add(json_scode, "damped", "d");
13056 json_object_string_add(json_scode, "history", "h");
13057 json_object_string_add(json_scode, "valid", "*");
13058 json_object_string_add(json_scode, "best", ">");
13059 json_object_string_add(json_scode, "multipath", "=");
13060 json_object_string_add(json_scode, "internal", "i");
13061 json_object_string_add(json_scode, "ribFailure", "r");
13062 json_object_string_add(json_scode, "stale", "S");
13063 json_object_string_add(json_scode, "removed", "R");
13064
13065 json_object_string_add(json_ocode, "igp", "i");
13066 json_object_string_add(json_ocode, "egp", "e");
13067 json_object_string_add(json_ocode, "incomplete", "?");
13068 }
a636c635 13069
d62a17ae 13070 bgp = peer->bgp;
a636c635 13071
d62a17ae 13072 if (!bgp) {
13073 if (use_json) {
13074 json_object_string_add(json, "alert", "no BGP");
13075 vty_out(vty, "%s\n", json_object_to_json_string(json));
13076 json_object_free(json);
13077 } else
13078 vty_out(vty, "%% No bgp\n");
13079 return;
13080 }
a636c635 13081
c512a642
EDP
13082 /* labeled-unicast routes live in the unicast table */
13083 if (safi == SAFI_LABELED_UNICAST)
13084 table = bgp->rib[afi][SAFI_UNICAST];
13085 else
13086 table = bgp->rib[afi][safi];
d62a17ae 13087
13088 output_count = filtered_count = 0;
13089 subgrp = peer_subgroup(peer, afi, safi);
13090
6392aaa6 13091 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13092 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13093 char buf[BUFSIZ] = {0};
13094
d62a17ae 13095 if (use_json) {
13096 json_object_int_add(json, "bgpTableVersion",
13097 table->version);
13098 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13099 inet_ntop(AF_INET,
13100 &bgp->router_id, buf,
13101 sizeof(buf)));
01eced22
AD
13102 json_object_int_add(json, "defaultLocPrf",
13103 bgp->default_local_pref);
13104 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13105 json_object_object_add(json, "bgpStatusCodes",
13106 json_scode);
13107 json_object_object_add(json, "bgpOriginCodes",
13108 json_ocode);
07d0c4ed
DA
13109 json_object_string_add(
13110 json, "bgpOriginatingDefaultNetwork",
13111 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13112 } else {
23d0a753
DA
13113 vty_out(vty,
13114 "BGP table version is %" PRIu64
13115 ", local router ID is %pI4, vrf id ",
13116 table->version, &bgp->router_id);
9df8b37c
PZ
13117 if (bgp->vrf_id == VRF_UNKNOWN)
13118 vty_out(vty, "%s", VRFID_NONE_STR);
13119 else
13120 vty_out(vty, "%u", bgp->vrf_id);
13121 vty_out(vty, "\n");
01eced22
AD
13122 vty_out(vty, "Default local pref %u, ",
13123 bgp->default_local_pref);
13124 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13125 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13126 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13127 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13128
07d0c4ed
DA
13129 vty_out(vty, "Originating default network %s\n\n",
13130 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13131 }
13132 header1 = 0;
13133 }
a636c635 13134
9bcb3eef 13135 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13136 if (type == bgp_show_adj_route_received
13137 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13138 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13139 if (ain->peer != peer)
ea47320b 13140 continue;
6392aaa6 13141
2f9bc755
DS
13142 show_adj_route_header(
13143 vty, bgp, table, &header1, &header2,
13144 json, json_scode, json_ocode, wide);
6392aaa6 13145
6f4f49b2 13146 attr = *ain->attr;
f99def61
AD
13147 route_filtered = false;
13148
13149 /* Filter prefix using distribute list,
13150 * filter list or prefix list
13151 */
b54892e0 13152 const struct prefix *rn_p =
9bcb3eef 13153 bgp_dest_get_prefix(dest);
b54892e0
DS
13154 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13155 safi))
13156 == FILTER_DENY)
f99def61
AD
13157 route_filtered = true;
13158
13159 /* Filter prefix using route-map */
b54892e0
DS
13160 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13161 safi, rmap_name, NULL,
13162 0, NULL);
6392aaa6 13163
13c8e163
AD
13164 if (type == bgp_show_adj_route_filtered &&
13165 !route_filtered && ret != RMAP_DENY) {
b755861b 13166 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13167 continue;
d62a17ae 13168 }
6392aaa6 13169
13c8e163
AD
13170 if (type == bgp_show_adj_route_received &&
13171 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
13172 filtered_count++;
13173
b54892e0 13174 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13175 use_json, json_ar, wide);
b755861b 13176 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13177 output_count++;
d62a17ae 13178 }
6392aaa6 13179 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13180 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13181 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13182 if (paf->peer != peer || !adj->attr)
924c3f6a 13183 continue;
d62a17ae 13184
2f9bc755
DS
13185 show_adj_route_header(
13186 vty, bgp, table, &header1,
13187 &header2, json, json_scode,
13188 json_ocode, wide);
d62a17ae 13189
b54892e0 13190 const struct prefix *rn_p =
9bcb3eef 13191 bgp_dest_get_prefix(dest);
b54892e0 13192
6f4f49b2 13193 attr = *adj->attr;
b755861b 13194 ret = bgp_output_modifier(
b54892e0 13195 peer, rn_p, &attr, afi, safi,
b755861b 13196 rmap_name);
f46d8e1e 13197
b755861b 13198 if (ret != RMAP_DENY) {
b54892e0
DS
13199 route_vty_out_tmp(
13200 vty, rn_p, &attr, safi,
ae248832
MK
13201 use_json, json_ar,
13202 wide);
b755861b
PM
13203 output_count++;
13204 } else {
13205 filtered_count++;
a2addae8 13206 }
b755861b
PM
13207
13208 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13209 }
f20ce998
DS
13210 } else if (type == bgp_show_adj_route_bestpath) {
13211 struct bgp_path_info *pi;
13212
13213 show_adj_route_header(vty, bgp, table, &header1,
13214 &header2, json, json_scode,
13215 json_ocode, wide);
13216
13217 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13218 pi = pi->next) {
13219 if (pi->peer != peer)
13220 continue;
13221
13222 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13223 continue;
13224
13225 route_vty_out_tmp(vty,
13226 bgp_dest_get_prefix(dest),
13227 pi->attr, safi, use_json,
13228 json_ar, wide);
13229 output_count++;
13230 }
d62a17ae 13231 }
13232 }
d62a17ae 13233
d62a17ae 13234 if (use_json) {
6392aaa6
PM
13235 json_object_object_add(json, "advertisedRoutes", json_ar);
13236 json_object_int_add(json, "totalPrefixCounter", output_count);
13237 json_object_int_add(json, "filteredPrefixCounter",
13238 filtered_count);
13239
996c9314
LB
13240 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13241 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13242
13243 if (!output_count && !filtered_count) {
13244 json_object_free(json_scode);
13245 json_object_free(json_ocode);
13246 }
13247
d62a17ae 13248 json_object_free(json);
6392aaa6
PM
13249 } else if (output_count > 0) {
13250 if (filtered_count > 0)
13251 vty_out(vty,
13252 "\nTotal number of prefixes %ld (%ld filtered)\n",
13253 output_count, filtered_count);
13254 else
13255 vty_out(vty, "\nTotal number of prefixes %ld\n",
13256 output_count);
d62a17ae 13257 }
a636c635 13258}
2a71e9ce 13259
d62a17ae 13260static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13261 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13262 const char *rmap_name, uint8_t show_flags)
0b16f239 13263{
d62a17ae 13264 json_object *json = NULL;
96f3485c 13265 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13266
d62a17ae 13267 if (use_json)
13268 json = json_object_new_object();
0b16f239 13269
d62a17ae 13270 if (!peer || !peer->afc[afi][safi]) {
13271 if (use_json) {
13272 json_object_string_add(
13273 json, "warning",
13274 "No such neighbor or address family");
13275 vty_out(vty, "%s\n", json_object_to_json_string(json));
13276 json_object_free(json);
13277 } else
13278 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13279
d62a17ae 13280 return CMD_WARNING;
13281 }
13282
6392aaa6
PM
13283 if ((type == bgp_show_adj_route_received
13284 || type == bgp_show_adj_route_filtered)
d62a17ae 13285 && !CHECK_FLAG(peer->af_flags[afi][safi],
13286 PEER_FLAG_SOFT_RECONFIG)) {
13287 if (use_json) {
13288 json_object_string_add(
13289 json, "warning",
13290 "Inbound soft reconfiguration not enabled");
13291 vty_out(vty, "%s\n", json_object_to_json_string(json));
13292 json_object_free(json);
13293 } else
13294 vty_out(vty,
13295 "%% Inbound soft reconfiguration not enabled\n");
13296
13297 return CMD_WARNING;
13298 }
0b16f239 13299
96f3485c 13300 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13301
d62a17ae 13302 return CMD_SUCCESS;
a636c635 13303}
50ef26d4 13304
f20ce998
DS
13305DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13306 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13307 "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]",
13308 SHOW_STR
13309 IP_STR
13310 BGP_STR
13311 BGP_INSTANCE_HELP_STR
13312 BGP_AFI_HELP_STR
13313 BGP_SAFI_WITH_LABEL_HELP_STR
13314 "Detailed information on TCP and BGP neighbor connections\n"
13315 "Neighbor to display information about\n"
13316 "Neighbor to display information about\n"
13317 "Neighbor on BGP configured interface\n"
13318 "Display the routes selected by best path\n"
13319 JSON_STR
13320 "Increase table width for longer prefixes\n")
13321{
13322 afi_t afi = AFI_IP6;
13323 safi_t safi = SAFI_UNICAST;
13324 char *rmap_name = NULL;
13325 char *peerstr = NULL;
13326 struct bgp *bgp = NULL;
13327 struct peer *peer;
13328 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13329 int idx = 0;
96f3485c
MK
13330 uint8_t show_flags = 0;
13331
13332 if (uj)
13333 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13334
13335 if (wide)
13336 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13337
13338 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13339 &bgp, uj);
13340
13341 if (!idx)
13342 return CMD_WARNING;
13343
13344 argv_find(argv, argc, "neighbors", &idx);
13345 peerstr = argv[++idx]->arg;
13346
13347 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13348 if (!peer)
13349 return CMD_WARNING;
13350
96f3485c
MK
13351 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13352 show_flags);
f20ce998
DS
13353}
13354
ae248832 13355DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13356 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13357 "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 13358 SHOW_STR
13359 IP_STR
13360 BGP_STR
a636c635 13361 BGP_INSTANCE_HELP_STR
7395a2c9 13362 BGP_AFI_HELP_STR
4dd6177e 13363 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13364 "Display the entries for all address families\n"
718e3744 13365 "Detailed information on TCP and BGP neighbor connections\n"
13366 "Neighbor to display information about\n"
13367 "Neighbor to display information about\n"
91d37724 13368 "Neighbor on BGP configured interface\n"
a636c635 13369 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13370 "Display the received routes from neighbor\n"
13371 "Display the filtered routes received from neighbor\n"
a636c635
DW
13372 "Route-map to modify the attributes\n"
13373 "Name of the route map\n"
ae248832
MK
13374 JSON_STR
13375 "Increase table width for longer prefixes\n")
718e3744 13376{
d62a17ae 13377 afi_t afi = AFI_IP6;
13378 safi_t safi = SAFI_UNICAST;
13379 char *rmap_name = NULL;
13380 char *peerstr = NULL;
d62a17ae 13381 struct bgp *bgp = NULL;
13382 struct peer *peer;
6392aaa6 13383 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13384 int idx = 0;
96f3485c
MK
13385 bool first = true;
13386 uint8_t show_flags = 0;
6392aaa6 13387
96f3485c 13388 if (uj) {
d62a17ae 13389 argc--;
96f3485c
MK
13390 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13391 }
13392
13393 if (all) {
13394 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13395 if (argv_find(argv, argc, "ipv4", &idx))
13396 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13397
13398 if (argv_find(argv, argc, "ipv6", &idx))
13399 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13400 }
13401
13402 if (wide)
13403 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13404
9f049418
DS
13405 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13406 &bgp, uj);
13407 if (!idx)
13408 return CMD_WARNING;
13409
d62a17ae 13410 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13411 argv_find(argv, argc, "neighbors", &idx);
13412 peerstr = argv[++idx]->arg;
8c3deaae 13413
d62a17ae 13414 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13415 if (!peer)
13416 return CMD_WARNING;
856ca177 13417
d62a17ae 13418 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13419 type = bgp_show_adj_route_advertised;
13420 else if (argv_find(argv, argc, "received-routes", &idx))
13421 type = bgp_show_adj_route_received;
13422 else if (argv_find(argv, argc, "filtered-routes", &idx))
13423 type = bgp_show_adj_route_filtered;
13424
d62a17ae 13425 if (argv_find(argv, argc, "route-map", &idx))
13426 rmap_name = argv[++idx]->arg;
95cbbd2a 13427
96f3485c
MK
13428 if (!all)
13429 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13430 show_flags);
13431 if (uj)
13432 vty_out(vty, "{\n");
13433
13434 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13435 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13436 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13437 : AFI_IP6;
13438 FOREACH_SAFI (safi) {
96f3485c
MK
13439 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13440 continue;
13441
13442 if (uj) {
13443 if (first)
13444 first = false;
13445 else
13446 vty_out(vty, ",\n");
13447 vty_out(vty, "\"%s\":",
13448 get_afi_safi_str(afi, safi, true));
13449 } else
13450 vty_out(vty, "\nFor address family: %s\n",
13451 get_afi_safi_str(afi, safi, false));
13452
13453 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13454 show_flags);
13455 }
13456 } else {
13457 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13458 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13459 continue;
13460
13461 if (uj) {
13462 if (first)
13463 first = false;
13464 else
13465 vty_out(vty, ",\n");
13466 vty_out(vty, "\"%s\":",
13467 get_afi_safi_str(afi, safi, true));
13468 } else
13469 vty_out(vty, "\nFor address family: %s\n",
13470 get_afi_safi_str(afi, safi, false));
13471
13472 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13473 show_flags);
13474 }
13475 }
13476 if (uj)
13477 vty_out(vty, "}\n");
13478
13479 return CMD_SUCCESS;
95cbbd2a
ML
13480}
13481
718e3744 13482DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13483 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13484 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13485 SHOW_STR
13486 IP_STR
13487 BGP_STR
8c3deaae
QY
13488 "Address Family\n"
13489 "Address Family\n"
718e3744 13490 "Address Family modifier\n"
13491 "Detailed information on TCP and BGP neighbor connections\n"
13492 "Neighbor to display information about\n"
13493 "Neighbor to display information about\n"
91d37724 13494 "Neighbor on BGP configured interface\n"
718e3744 13495 "Display information received from a BGP neighbor\n"
856ca177 13496 "Display the prefixlist filter\n"
9973d184 13497 JSON_STR)
718e3744 13498{
d62a17ae 13499 afi_t afi = AFI_IP6;
13500 safi_t safi = SAFI_UNICAST;
13501 char *peerstr = NULL;
13502
13503 char name[BUFSIZ];
13504 union sockunion su;
13505 struct peer *peer;
13506 int count, ret;
13507
13508 int idx = 0;
13509
13510 /* show [ip] bgp */
13511 if (argv_find(argv, argc, "ip", &idx))
13512 afi = AFI_IP;
13513 /* [<ipv4|ipv6> [unicast]] */
13514 if (argv_find(argv, argc, "ipv4", &idx))
13515 afi = AFI_IP;
13516 if (argv_find(argv, argc, "ipv6", &idx))
13517 afi = AFI_IP6;
13518 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13519 argv_find(argv, argc, "neighbors", &idx);
13520 peerstr = argv[++idx]->arg;
13521
9f049418 13522 bool uj = use_json(argc, argv);
d62a17ae 13523
13524 ret = str2sockunion(peerstr, &su);
13525 if (ret < 0) {
13526 peer = peer_lookup_by_conf_if(NULL, peerstr);
13527 if (!peer) {
13528 if (uj)
13529 vty_out(vty, "{}\n");
13530 else
13531 vty_out(vty,
13532 "%% Malformed address or name: %s\n",
13533 peerstr);
13534 return CMD_WARNING;
13535 }
13536 } else {
13537 peer = peer_lookup(NULL, &su);
13538 if (!peer) {
13539 if (uj)
13540 vty_out(vty, "{}\n");
13541 else
13542 vty_out(vty, "No peer\n");
13543 return CMD_WARNING;
13544 }
13545 }
718e3744 13546
4ced1a2c 13547 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13548 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13549 if (count) {
13550 if (!uj)
13551 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13552 get_afi_safi_str(afi, safi, false));
d62a17ae 13553 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13554 } else {
13555 if (uj)
13556 vty_out(vty, "{}\n");
13557 else
13558 vty_out(vty, "No functional output\n");
13559 }
718e3744 13560
d62a17ae 13561 return CMD_SUCCESS;
13562}
13563
13564static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13565 afi_t afi, safi_t safi,
9f049418 13566 enum bgp_show_type type, bool use_json)
d62a17ae 13567{
96f3485c
MK
13568 uint8_t show_flags = 0;
13569
13570 if (use_json)
13571 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13572
d62a17ae 13573 if (!peer || !peer->afc[afi][safi]) {
13574 if (use_json) {
13575 json_object *json_no = NULL;
13576 json_no = json_object_new_object();
13577 json_object_string_add(
13578 json_no, "warning",
13579 "No such neighbor or address family");
13580 vty_out(vty, "%s\n",
13581 json_object_to_json_string(json_no));
13582 json_object_free(json_no);
13583 } else
13584 vty_out(vty, "%% No such neighbor or address family\n");
13585 return CMD_WARNING;
13586 }
47fc97cc 13587
7daf25a3
TA
13588 /* labeled-unicast routes live in the unicast table */
13589 if (safi == SAFI_LABELED_UNICAST)
13590 safi = SAFI_UNICAST;
13591
96f3485c 13592 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13593}
13594
dba3c1d3
PG
13595DEFUN (show_ip_bgp_flowspec_routes_detailed,
13596 show_ip_bgp_flowspec_routes_detailed_cmd,
13597 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13598 SHOW_STR
13599 IP_STR
13600 BGP_STR
13601 BGP_INSTANCE_HELP_STR
13602 BGP_AFI_HELP_STR
13603 "SAFI Flowspec\n"
13604 "Detailed information on flowspec entries\n"
13605 JSON_STR)
13606{
13607 afi_t afi = AFI_IP;
13608 safi_t safi = SAFI_UNICAST;
13609 struct bgp *bgp = NULL;
13610 int idx = 0;
9f049418 13611 bool uj = use_json(argc, argv);
96f3485c 13612 uint8_t show_flags = 0;
9f049418 13613
96f3485c 13614 if (uj) {
9f049418 13615 argc--;
96f3485c
MK
13616 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13617 }
dba3c1d3
PG
13618
13619 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13620 &bgp, uj);
dba3c1d3
PG
13621 if (!idx)
13622 return CMD_WARNING;
13623
96f3485c
MK
13624 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13625 show_flags);
dba3c1d3
PG
13626}
13627
718e3744 13628DEFUN (show_ip_bgp_neighbor_routes,
13629 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13630 "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 13631 SHOW_STR
13632 IP_STR
13633 BGP_STR
8386ac43 13634 BGP_INSTANCE_HELP_STR
4f280b15 13635 BGP_AFI_HELP_STR
4dd6177e 13636 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13637 "Detailed information on TCP and BGP neighbor connections\n"
13638 "Neighbor to display information about\n"
13639 "Neighbor to display information about\n"
91d37724 13640 "Neighbor on BGP configured interface\n"
2525cf39 13641 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13642 "Display the dampened routes received from neighbor\n"
13643 "Display routes learned from neighbor\n"
9973d184 13644 JSON_STR)
718e3744 13645{
d62a17ae 13646 char *peerstr = NULL;
13647 struct bgp *bgp = NULL;
13648 afi_t afi = AFI_IP6;
13649 safi_t safi = SAFI_UNICAST;
13650 struct peer *peer;
13651 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13652 int idx = 0;
9f049418
DS
13653 bool uj = use_json(argc, argv);
13654
13655 if (uj)
13656 argc--;
bb46e94f 13657
d62a17ae 13658 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13659 &bgp, uj);
d62a17ae 13660 if (!idx)
13661 return CMD_WARNING;
c493f2d8 13662
d62a17ae 13663 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13664 argv_find(argv, argc, "neighbors", &idx);
13665 peerstr = argv[++idx]->arg;
8c3deaae 13666
d62a17ae 13667 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13668 if (!peer)
d62a17ae 13669 return CMD_WARNING;
bb46e94f 13670
d62a17ae 13671 if (argv_find(argv, argc, "flap-statistics", &idx))
13672 sh_type = bgp_show_type_flap_neighbor;
13673 else if (argv_find(argv, argc, "dampened-routes", &idx))
13674 sh_type = bgp_show_type_damp_neighbor;
13675 else if (argv_find(argv, argc, "routes", &idx))
13676 sh_type = bgp_show_type_neighbor;
2525cf39 13677
d62a17ae 13678 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13679}
6b0655a2 13680
734b349e 13681struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13682
d62a17ae 13683struct bgp_distance {
13684 /* Distance value for the IP source prefix. */
d7c0a89a 13685 uint8_t distance;
718e3744 13686
d62a17ae 13687 /* Name of the access-list to be matched. */
13688 char *access_list;
718e3744 13689};
13690
4f280b15
LB
13691DEFUN (show_bgp_afi_vpn_rd_route,
13692 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13693 "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
4f280b15
LB
13694 SHOW_STR
13695 BGP_STR
13696 BGP_AFI_HELP_STR
13697 "Address Family modifier\n"
13698 "Display information for a route distinguisher\n"
13699 "Route Distinguisher\n"
7395a2c9
DS
13700 "Network in the BGP routing table to display\n"
13701 "Network in the BGP routing table to display\n"
13702 JSON_STR)
4f280b15 13703{
d62a17ae 13704 int ret;
13705 struct prefix_rd prd;
13706 afi_t afi = AFI_MAX;
13707 int idx = 0;
4f280b15 13708
ff6566f3
DS
13709 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13710 vty_out(vty, "%% Malformed Address Family\n");
13711 return CMD_WARNING;
13712 }
13713
d62a17ae 13714 ret = str2prefix_rd(argv[5]->arg, &prd);
13715 if (!ret) {
13716 vty_out(vty, "%% Malformed Route Distinguisher\n");
13717 return CMD_WARNING;
13718 }
ff6566f3 13719
d62a17ae 13720 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13721 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13722}
13723
d62a17ae 13724static struct bgp_distance *bgp_distance_new(void)
718e3744 13725{
d62a17ae 13726 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13727}
13728
d62a17ae 13729static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13730{
d62a17ae 13731 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13732}
13733
37a87b8f
CS
13734int bgp_distance_set(uint8_t distance, const char *ip_str,
13735 const char *access_list_str, afi_t afi, safi_t safi,
13736 char *errmsg, size_t errmsg_len)
718e3744 13737{
d62a17ae 13738 int ret;
d62a17ae 13739 struct prefix p;
9bcb3eef 13740 struct bgp_dest *dest;
d62a17ae 13741 struct bgp_distance *bdistance;
718e3744 13742
d62a17ae 13743 ret = str2prefix(ip_str, &p);
13744 if (ret == 0) {
37a87b8f 13745 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13746 return CMD_WARNING_CONFIG_FAILED;
13747 }
718e3744 13748
d62a17ae 13749 /* Get BGP distance node. */
9bcb3eef
DS
13750 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13751 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13752 if (bdistance)
9bcb3eef 13753 bgp_dest_unlock_node(dest);
ca2e160d 13754 else {
d62a17ae 13755 bdistance = bgp_distance_new();
9bcb3eef 13756 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13757 }
718e3744 13758
d62a17ae 13759 /* Set distance value. */
13760 bdistance->distance = distance;
718e3744 13761
d62a17ae 13762 /* Reset access-list configuration. */
e1b36e13 13763 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13764 if (access_list_str)
13765 bdistance->access_list =
13766 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13767
d62a17ae 13768 return CMD_SUCCESS;
718e3744 13769}
13770
37a87b8f
CS
13771int bgp_distance_unset(uint8_t distance, const char *ip_str,
13772 const char *access_list_str, afi_t afi, safi_t safi,
13773 char *errmsg, size_t errmsg_len)
718e3744 13774{
d62a17ae 13775 int ret;
d62a17ae 13776 struct prefix p;
9bcb3eef 13777 struct bgp_dest *dest;
d62a17ae 13778 struct bgp_distance *bdistance;
718e3744 13779
d62a17ae 13780 ret = str2prefix(ip_str, &p);
13781 if (ret == 0) {
37a87b8f 13782 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13783 return CMD_WARNING_CONFIG_FAILED;
13784 }
718e3744 13785
9bcb3eef
DS
13786 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13787 if (!dest) {
37a87b8f 13788 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13789 return CMD_WARNING_CONFIG_FAILED;
13790 }
718e3744 13791
9bcb3eef 13792 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13793
d62a17ae 13794 if (bdistance->distance != distance) {
37a87b8f
CS
13795 snprintf(errmsg, errmsg_len,
13796 "Distance does not match configured\n");
d62a17ae 13797 return CMD_WARNING_CONFIG_FAILED;
13798 }
718e3744 13799
0a22ddfb 13800 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13801 bgp_distance_free(bdistance);
718e3744 13802
9bcb3eef
DS
13803 bgp_dest_set_bgp_path_info(dest, NULL);
13804 bgp_dest_unlock_node(dest);
13805 bgp_dest_unlock_node(dest);
718e3744 13806
d62a17ae 13807 return CMD_SUCCESS;
718e3744 13808}
13809
718e3744 13810/* Apply BGP information to distance method. */
b8685f9b 13811uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13812 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13813{
9bcb3eef 13814 struct bgp_dest *dest;
801bb996 13815 struct prefix q = {0};
d62a17ae 13816 struct peer *peer;
13817 struct bgp_distance *bdistance;
13818 struct access_list *alist;
13819 struct bgp_static *bgp_static;
13820
13821 if (!bgp)
13822 return 0;
13823
40381db7 13824 peer = pinfo->peer;
d62a17ae 13825
7b7d48e5
DS
13826 if (pinfo->attr->distance)
13827 return pinfo->attr->distance;
13828
801bb996
CS
13829 /* Check source address.
13830 * Note: for aggregate route, peer can have unspec af type.
13831 */
13832 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13833 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
13834 return 0;
13835
9bcb3eef
DS
13836 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13837 if (dest) {
13838 bdistance = bgp_dest_get_bgp_distance_info(dest);
13839 bgp_dest_unlock_node(dest);
d62a17ae 13840
13841 if (bdistance->access_list) {
13842 alist = access_list_lookup(afi, bdistance->access_list);
13843 if (alist
13844 && access_list_apply(alist, p) == FILTER_PERMIT)
13845 return bdistance->distance;
13846 } else
13847 return bdistance->distance;
718e3744 13848 }
718e3744 13849
d62a17ae 13850 /* Backdoor check. */
9bcb3eef
DS
13851 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13852 if (dest) {
13853 bgp_static = bgp_dest_get_bgp_static_info(dest);
13854 bgp_dest_unlock_node(dest);
718e3744 13855
d62a17ae 13856 if (bgp_static->backdoor) {
13857 if (bgp->distance_local[afi][safi])
13858 return bgp->distance_local[afi][safi];
13859 else
13860 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13861 }
718e3744 13862 }
718e3744 13863
d62a17ae 13864 if (peer->sort == BGP_PEER_EBGP) {
13865 if (bgp->distance_ebgp[afi][safi])
13866 return bgp->distance_ebgp[afi][safi];
13867 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 13868 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 13869 if (bgp->distance_ibgp[afi][safi])
13870 return bgp->distance_ibgp[afi][safi];
13871 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
13872 } else {
13873 if (bgp->distance_local[afi][safi])
13874 return bgp->distance_local[afi][safi];
13875 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 13876 }
718e3744 13877}
13878
a612fb77
DA
13879/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13880 * we should tell ZEBRA update the routes for a specific
13881 * AFI/SAFI to reflect changes in RIB.
13882 */
37a87b8f
CS
13883void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13884 safi_t update_safi)
a612fb77
DA
13885{
13886 afi_t afi;
13887 safi_t safi;
13888
13889 FOREACH_AFI_SAFI (afi, safi) {
13890 if (!bgp_fibupd_safi(safi))
13891 continue;
13892
8b54bc30
DA
13893 if (afi != update_afi && safi != update_safi)
13894 continue;
13895
13896 if (BGP_DEBUG(zebra, ZEBRA))
13897 zlog_debug(
13898 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13899 __func__, afi, safi);
13900 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13901 }
13902}
13903
37a87b8f
CS
13904DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13905 "distance bgp (1-255) (1-255) (1-255)",
13906 "Define an administrative distance\n"
13907 "BGP distance\n"
13908 "Distance for routes external to the AS\n"
13909 "Distance for routes internal to the AS\n"
13910 "Distance for local routes\n")
718e3744 13911{
d62a17ae 13912 int idx_number = 2;
13913 int idx_number_2 = 3;
13914 int idx_number_3 = 4;
13915 afi_t afi;
13916 safi_t safi;
37a87b8f 13917 char xpath[XPATH_MAXLEN];
718e3744 13918
d62a17ae 13919 afi = bgp_node_afi(vty);
13920 safi = bgp_node_safi(vty);
718e3744 13921
37a87b8f
CS
13922 snprintf(
13923 xpath, sizeof(xpath),
13924 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13925 yang_afi_safi_value2identity(afi, safi),
13926 bgp_afi_safi_get_container_str(afi, safi));
13927 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13928 snprintf(
13929 xpath, sizeof(xpath),
13930 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13931 yang_afi_safi_value2identity(afi, safi),
13932 bgp_afi_safi_get_container_str(afi, safi));
13933 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13934 argv[idx_number_2]->arg);
13935 snprintf(
13936 xpath, sizeof(xpath),
13937 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13938 yang_afi_safi_value2identity(afi, safi),
13939 bgp_afi_safi_get_container_str(afi, safi));
13940
13941 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13942 argv[idx_number_3]->arg);
13943
13944 return nb_cli_apply_changes(vty, NULL);
13945}
13946
13947DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13948 "no distance bgp [(1-255) (1-255) (1-255)]",
13949 NO_STR
13950 "Define an administrative distance\n"
13951 "BGP distance\n"
13952 "Distance for routes external to the AS\n"
13953 "Distance for routes internal to the AS\n"
13954 "Distance for local routes\n")
13955{
13956 afi_t afi;
13957 safi_t safi;
13958 char xpath[XPATH_MAXLEN];
13959
13960 afi = bgp_node_afi(vty);
13961 safi = bgp_node_safi(vty);
13962
13963 snprintf(
13964 xpath, sizeof(xpath),
13965 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13966 yang_afi_safi_value2identity(afi, safi),
13967 bgp_afi_safi_get_container_str(afi, safi));
13968 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13969 snprintf(
13970 xpath, sizeof(xpath),
13971 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13972 yang_afi_safi_value2identity(afi, safi),
13973 bgp_afi_safi_get_container_str(afi, safi));
13974 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13975 snprintf(
13976 xpath, sizeof(xpath),
13977 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13978 yang_afi_safi_value2identity(afi, safi),
13979 bgp_afi_safi_get_container_str(afi, safi));
13980
13981 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13982
13983 return nb_cli_apply_changes(vty, NULL);
718e3744 13984}
13985
37a87b8f
CS
13986void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
13987 struct lyd_node *dnode,
13988 bool show_defaults)
718e3744 13989{
37a87b8f
CS
13990 uint8_t distance_ebgp, distance_ibgp, distance_local;
13991
13992 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
13993 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
13994 distance_local = yang_dnode_get_uint8(dnode, "./local");
13995
13996 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
13997 distance_local);
13998}
13999
8cc7152a
CS
14000DEFPY_YANG(bgp_distance_source,
14001 bgp_distance_source_cmd,
14002 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14003 NO_STR
14004 "Define an administrative distance\n"
8cc7152a 14005 "Distance value\n"
e12affc1
SW
14006 "IPv4 source prefix\n"
14007 "IPv6 source prefix\n"
37a87b8f 14008 "Access list name\n")
718e3744 14009{
37a87b8f
CS
14010 afi_t afi;
14011 safi_t safi;
14012 char xpath[XPATH_MAXLEN];
14013
14014 afi = bgp_node_afi(vty);
14015 safi = bgp_node_safi(vty);
14016
8cc7152a
CS
14017 if (!no) {
14018 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14019 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14020 distance_str);
14021 if (acl)
14022 nb_cli_enqueue_change(vty,
14023 "./access-list-policy-export",
14024 NB_OP_CREATE, acl);
14025 else
14026 nb_cli_enqueue_change(vty,
14027 "./access-list-policy-export",
14028 NB_OP_DESTROY, NULL);
14029 } else {
14030 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14031 }
37a87b8f
CS
14032
14033 snprintf(
14034 xpath, sizeof(xpath),
14035 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14036 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14037 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14038
14039 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14040}
14041
37a87b8f
CS
14042void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14043 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14044{
14045 vty_out(vty, " distance %d %s %s\n",
14046 yang_dnode_get_uint8(dnode, "./distance"),
14047 yang_dnode_get_string(dnode, "./prefix"),
14048 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14049 ? yang_dnode_get_string(dnode,
14050 "./access-list-policy-export")
14051 : "");
14052}
14053
7c98d487
DA
14054DEFPY_YANG(
14055 bgp_dampening, bgp_dampening_cmd,
14056 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14057 NO_STR
14058 "BGP Specific commands\n"
14059 "Enable route-flap dampening\n"
14060 "Half-life time for the penalty\n"
14061 "Value to start reusing a route\n"
14062 "Value to start suppressing a route\n"
14063 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14064{
14065 afi_t afi;
14066 safi_t safi;
14067 char xpath[XPATH_MAXLEN];
718e3744 14068
37a87b8f
CS
14069 afi = bgp_node_afi(vty);
14070 safi = bgp_node_safi(vty);
14071
d9ce5113
CS
14072 if (!no) {
14073 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14074 if (argc == 6) {
14075 nb_cli_enqueue_change(vty, "./reach-decay",
14076 NB_OP_MODIFY, halflife_str);
14077 nb_cli_enqueue_change(vty, "./reuse-above",
14078 NB_OP_MODIFY, reuse_str);
14079 nb_cli_enqueue_change(vty, "./suppress-above",
14080 NB_OP_MODIFY, suppress_str);
14081 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14082 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14083 } if (argc == 3) {
14084 nb_cli_enqueue_change(vty, "./reach-decay",
14085 NB_OP_MODIFY, halflife_str);
14086 }
14087 } else {
14088 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14089 }
7ebe9748 14090
37a87b8f
CS
14091 snprintf(
14092 xpath, sizeof(xpath),
14093 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14094 yang_afi_safi_value2identity(afi, safi),
14095 bgp_afi_safi_get_container_str(afi, safi));
14096
14097 return nb_cli_apply_changes(vty, xpath);
718e3744 14098}
14099
37a87b8f
CS
14100void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14101 struct lyd_node *dnode,
14102 bool show_defaults)
718e3744 14103{
37a87b8f
CS
14104 if (!yang_dnode_get_bool(dnode, "./enable"))
14105 return;
14106
14107 int half = DEFAULT_HALF_LIFE * 60;
14108 int reuse = DEFAULT_REUSE;
14109 int suppress = DEFAULT_SUPPRESS;
14110 int max;
14111
14112 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14113 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14114 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14115 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14116
14117 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14118 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14119 vty_out(vty, " bgp dampening\n");
14120 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14121 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14122 vty_out(vty, " bgp dampening %u\n", half);
14123 else
14124 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14125 suppress, max);
718e3744 14126}
14127
718e3744 14128/* Display specified route of BGP table. */
d62a17ae 14129static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14130 const char *ip_str, afi_t afi, safi_t safi,
14131 struct prefix_rd *prd, int prefix_check)
14132{
14133 int ret;
14134 struct prefix match;
9bcb3eef
DS
14135 struct bgp_dest *dest;
14136 struct bgp_dest *rm;
40381db7
DS
14137 struct bgp_path_info *pi;
14138 struct bgp_path_info *pi_temp;
d62a17ae 14139 struct bgp *bgp;
14140 struct bgp_table *table;
14141
14142 /* BGP structure lookup. */
14143 if (view_name) {
14144 bgp = bgp_lookup_by_name(view_name);
14145 if (bgp == NULL) {
14146 vty_out(vty, "%% Can't find BGP instance %s\n",
14147 view_name);
14148 return CMD_WARNING;
14149 }
14150 } else {
14151 bgp = bgp_get_default();
14152 if (bgp == NULL) {
14153 vty_out(vty, "%% No BGP process is configured\n");
14154 return CMD_WARNING;
14155 }
718e3744 14156 }
718e3744 14157
d62a17ae 14158 /* Check IP address argument. */
14159 ret = str2prefix(ip_str, &match);
14160 if (!ret) {
14161 vty_out(vty, "%% address is malformed\n");
14162 return CMD_WARNING;
14163 }
718e3744 14164
d62a17ae 14165 match.family = afi2family(afi);
14166
14167 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14168 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14169 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14170 dest = bgp_route_next(dest)) {
14171 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14172
9bcb3eef 14173 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14174 continue;
9bcb3eef 14175 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14176 if (!table)
ea47320b
DL
14177 continue;
14178 if ((rm = bgp_node_match(table, &match)) == NULL)
14179 continue;
d62a17ae 14180
9bcb3eef 14181 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14182
ea47320b 14183 if (!prefix_check
b54892e0 14184 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14185 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14186 while (pi) {
14187 if (pi->extra && pi->extra->damp_info) {
14188 pi_temp = pi->next;
ea47320b 14189 bgp_damp_info_free(
40ec3340
DS
14190 &pi->extra->damp_info,
14191 &bgp->damp[afi][safi],
a935f597 14192 1, afi, safi);
40381db7 14193 pi = pi_temp;
ea47320b 14194 } else
40381db7 14195 pi = pi->next;
d62a17ae 14196 }
ea47320b
DL
14197 }
14198
9bcb3eef 14199 bgp_dest_unlock_node(rm);
d62a17ae 14200 }
14201 } else {
9bcb3eef 14202 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14203 != NULL) {
9bcb3eef 14204 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14205
d62a17ae 14206 if (!prefix_check
9bcb3eef
DS
14207 || dest_p->prefixlen == match.prefixlen) {
14208 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14209 while (pi) {
14210 if (pi->extra && pi->extra->damp_info) {
14211 pi_temp = pi->next;
d62a17ae 14212 bgp_damp_info_free(
40ec3340
DS
14213 &pi->extra->damp_info,
14214 &bgp->damp[afi][safi],
a935f597 14215 1, afi, safi);
40381db7 14216 pi = pi_temp;
d62a17ae 14217 } else
40381db7 14218 pi = pi->next;
d62a17ae 14219 }
14220 }
14221
9bcb3eef 14222 bgp_dest_unlock_node(dest);
d62a17ae 14223 }
14224 }
718e3744 14225
d62a17ae 14226 return CMD_SUCCESS;
718e3744 14227}
14228
14229DEFUN (clear_ip_bgp_dampening,
14230 clear_ip_bgp_dampening_cmd,
14231 "clear ip bgp dampening",
14232 CLEAR_STR
14233 IP_STR
14234 BGP_STR
14235 "Clear route flap dampening information\n")
14236{
40ec3340
DS
14237 VTY_DECLVAR_CONTEXT(bgp, bgp);
14238 bgp_damp_info_clean(&bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
14239 SAFI_UNICAST);
d62a17ae 14240 return CMD_SUCCESS;
718e3744 14241}
14242
14243DEFUN (clear_ip_bgp_dampening_prefix,
14244 clear_ip_bgp_dampening_prefix_cmd,
14245 "clear ip bgp dampening A.B.C.D/M",
14246 CLEAR_STR
14247 IP_STR
14248 BGP_STR
14249 "Clear route flap dampening information\n"
0c7b1b01 14250 "IPv4 prefix\n")
718e3744 14251{
d62a17ae 14252 int idx_ipv4_prefixlen = 4;
14253 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14254 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14255}
14256
14257DEFUN (clear_ip_bgp_dampening_address,
14258 clear_ip_bgp_dampening_address_cmd,
14259 "clear ip bgp dampening A.B.C.D",
14260 CLEAR_STR
14261 IP_STR
14262 BGP_STR
14263 "Clear route flap dampening information\n"
14264 "Network to clear damping information\n")
14265{
d62a17ae 14266 int idx_ipv4 = 4;
14267 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14268 SAFI_UNICAST, NULL, 0);
718e3744 14269}
14270
14271DEFUN (clear_ip_bgp_dampening_address_mask,
14272 clear_ip_bgp_dampening_address_mask_cmd,
14273 "clear ip bgp dampening A.B.C.D A.B.C.D",
14274 CLEAR_STR
14275 IP_STR
14276 BGP_STR
14277 "Clear route flap dampening information\n"
14278 "Network to clear damping information\n"
14279 "Network mask\n")
14280{
d62a17ae 14281 int idx_ipv4 = 4;
14282 int idx_ipv4_2 = 5;
14283 int ret;
14284 char prefix_str[BUFSIZ];
718e3744 14285
d62a17ae 14286 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14287 prefix_str);
14288 if (!ret) {
14289 vty_out(vty, "%% Inconsistent address and mask\n");
14290 return CMD_WARNING;
14291 }
718e3744 14292
d62a17ae 14293 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14294 NULL, 0);
718e3744 14295}
6b0655a2 14296
e3b78da8 14297static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14298{
14299 struct vty *vty = arg;
e3b78da8 14300 struct peer *peer = bucket->data;
825d9834
DS
14301 char buf[SU_ADDRSTRLEN];
14302
14303 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14304 sockunion2str(&peer->su, buf, sizeof(buf)));
14305}
14306
2a0e69ae
DS
14307DEFUN (show_bgp_listeners,
14308 show_bgp_listeners_cmd,
14309 "show bgp listeners",
14310 SHOW_STR
14311 BGP_STR
14312 "Display Listen Sockets and who created them\n")
14313{
14314 bgp_dump_listener_info(vty);
14315
14316 return CMD_SUCCESS;
14317}
14318
825d9834
DS
14319DEFUN (show_bgp_peerhash,
14320 show_bgp_peerhash_cmd,
14321 "show bgp peerhash",
14322 SHOW_STR
14323 BGP_STR
14324 "Display information about the BGP peerhash\n")
14325{
14326 struct list *instances = bm->bgp;
14327 struct listnode *node;
14328 struct bgp *bgp;
14329
14330 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14331 vty_out(vty, "BGP: %s\n", bgp->name);
14332 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14333 vty);
14334 }
14335
14336 return CMD_SUCCESS;
14337}
14338
587ff0fd 14339/* also used for encap safi */
2b791107
DL
14340static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14341 afi_t afi, safi_t safi)
d62a17ae 14342{
9bcb3eef
DS
14343 struct bgp_dest *pdest;
14344 struct bgp_dest *dest;
d62a17ae 14345 struct bgp_table *table;
b54892e0
DS
14346 const struct prefix *p;
14347 const struct prefix_rd *prd;
d62a17ae 14348 struct bgp_static *bgp_static;
14349 mpls_label_t label;
d62a17ae 14350 char rdbuf[RD_ADDRSTRLEN];
14351
14352 /* Network configuration. */
9bcb3eef
DS
14353 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14354 pdest = bgp_route_next(pdest)) {
14355 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14356 if (!table)
ea47320b 14357 continue;
d62a17ae 14358
9bcb3eef
DS
14359 for (dest = bgp_table_top(table); dest;
14360 dest = bgp_route_next(dest)) {
14361 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14362 if (bgp_static == NULL)
ea47320b 14363 continue;
d62a17ae 14364
9bcb3eef
DS
14365 p = bgp_dest_get_prefix(dest);
14366 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14367 pdest);
d62a17ae 14368
ea47320b 14369 /* "network" configuration display. */
06b9f471 14370 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14371 label = decode_label(&bgp_static->label);
14372
8228a9a7 14373 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14374 if (safi == SAFI_MPLS_VPN)
14375 vty_out(vty, " label %u", label);
14376
14377 if (bgp_static->rmap.name)
14378 vty_out(vty, " route-map %s",
14379 bgp_static->rmap.name);
e2a86ad9
DS
14380
14381 if (bgp_static->backdoor)
14382 vty_out(vty, " backdoor");
14383
ea47320b
DL
14384 vty_out(vty, "\n");
14385 }
14386 }
d62a17ae 14387}
14388
2b791107
DL
14389static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14390 afi_t afi, safi_t safi)
d62a17ae 14391{
9bcb3eef
DS
14392 struct bgp_dest *pdest;
14393 struct bgp_dest *dest;
d62a17ae 14394 struct bgp_table *table;
b54892e0
DS
14395 const struct prefix *p;
14396 const struct prefix_rd *prd;
d62a17ae 14397 struct bgp_static *bgp_static;
ff44f570 14398 char buf[PREFIX_STRLEN * 2];
d62a17ae 14399 char buf2[SU_ADDRSTRLEN];
14400 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14401 char esi_buf[ESI_BYTES];
d62a17ae 14402
14403 /* Network configuration. */
9bcb3eef
DS
14404 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14405 pdest = bgp_route_next(pdest)) {
14406 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14407 if (!table)
ea47320b 14408 continue;
d62a17ae 14409
9bcb3eef
DS
14410 for (dest = bgp_table_top(table); dest;
14411 dest = bgp_route_next(dest)) {
14412 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14413 if (bgp_static == NULL)
ea47320b 14414 continue;
d62a17ae 14415
ea47320b 14416 char *macrouter = NULL;
d62a17ae 14417
ea47320b
DL
14418 if (bgp_static->router_mac)
14419 macrouter = prefix_mac2str(
14420 bgp_static->router_mac, NULL, 0);
14421 if (bgp_static->eth_s_id)
0a50c248
AK
14422 esi_to_str(bgp_static->eth_s_id,
14423 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14424 p = bgp_dest_get_prefix(dest);
14425 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14426
ea47320b 14427 /* "network" configuration display. */
06b9f471 14428 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14429 if (p->u.prefix_evpn.route_type == 5) {
14430 char local_buf[PREFIX_STRLEN];
3714a385 14431 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14432 struct prefix_evpn *)p)
14433 ? AF_INET
14434 : AF_INET6;
3714a385 14435 inet_ntop(family,
14436 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14437 local_buf, PREFIX_STRLEN);
772270f3
QY
14438 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14439 p->u.prefix_evpn.prefix_addr
14440 .ip_prefix_length);
197cb530
PG
14441 } else {
14442 prefix2str(p, buf, sizeof(buf));
14443 }
ea47320b 14444
a4d82a8a
PZ
14445 if (bgp_static->gatewayIp.family == AF_INET
14446 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14447 inet_ntop(bgp_static->gatewayIp.family,
14448 &bgp_static->gatewayIp.u.prefix, buf2,
14449 sizeof(buf2));
ea47320b 14450 vty_out(vty,
7bcc8dac 14451 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14452 buf, rdbuf,
14453 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14454 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14455 macrouter);
14456
0a22ddfb 14457 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14458 }
14459 }
3da6fcd5
PG
14460}
14461
718e3744 14462/* Configuration of static route announcement and aggregate
14463 information. */
2b791107
DL
14464void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14465 safi_t safi)
d62a17ae 14466{
9bcb3eef 14467 struct bgp_dest *dest;
b54892e0 14468 const struct prefix *p;
d62a17ae 14469 struct bgp_static *bgp_static;
14470 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14471
2b791107
DL
14472 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14473 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14474 return;
14475 }
d62a17ae 14476
2b791107
DL
14477 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14478 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14479 return;
14480 }
d62a17ae 14481
14482 /* Network configuration. */
9bcb3eef
DS
14483 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14484 dest = bgp_route_next(dest)) {
14485 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14486 if (bgp_static == NULL)
ea47320b 14487 continue;
d62a17ae 14488
9bcb3eef 14489 p = bgp_dest_get_prefix(dest);
d62a17ae 14490
8228a9a7 14491 vty_out(vty, " network %pFX", p);
d62a17ae 14492
ea47320b
DL
14493 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14494 vty_out(vty, " label-index %u",
14495 bgp_static->label_index);
d62a17ae 14496
ea47320b
DL
14497 if (bgp_static->rmap.name)
14498 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14499
14500 if (bgp_static->backdoor)
14501 vty_out(vty, " backdoor");
718e3744 14502
ea47320b
DL
14503 vty_out(vty, "\n");
14504 }
14505
d62a17ae 14506 /* Aggregate-address configuration. */
9bcb3eef
DS
14507 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14508 dest = bgp_route_next(dest)) {
14509 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14510 if (bgp_aggregate == NULL)
ea47320b 14511 continue;
d62a17ae 14512
9bcb3eef 14513 p = bgp_dest_get_prefix(dest);
d62a17ae 14514
8228a9a7 14515 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14516
ea47320b
DL
14517 if (bgp_aggregate->as_set)
14518 vty_out(vty, " as-set");
d62a17ae 14519
ea47320b
DL
14520 if (bgp_aggregate->summary_only)
14521 vty_out(vty, " summary-only");
718e3744 14522
20894f50
DA
14523 if (bgp_aggregate->rmap.name)
14524 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14525
229757f1
DA
14526 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14527 vty_out(vty, " origin %s",
14528 bgp_origin2str(bgp_aggregate->origin));
14529
6aabb15d
RZ
14530 if (bgp_aggregate->match_med)
14531 vty_out(vty, " matching-MED-only");
14532
365ab2e7
RZ
14533 if (bgp_aggregate->suppress_map_name)
14534 vty_out(vty, " suppress-map %s",
14535 bgp_aggregate->suppress_map_name);
14536
ea47320b
DL
14537 vty_out(vty, "\n");
14538 }
d62a17ae 14539}
734b349e 14540
2b791107 14541void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14542 safi_t safi)
d62a17ae 14543{
9bcb3eef 14544 struct bgp_dest *dest;
d62a17ae 14545 struct bgp_distance *bdistance;
14546
14547 /* Distance configuration. */
14548 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14549 && bgp->distance_local[afi][safi]
14550 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14551 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14552 || bgp->distance_local[afi][safi]
14553 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14554 vty_out(vty, " distance bgp %d %d %d\n",
14555 bgp->distance_ebgp[afi][safi],
14556 bgp->distance_ibgp[afi][safi],
14557 bgp->distance_local[afi][safi]);
14558 }
734b349e 14559
9bcb3eef
DS
14560 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14561 dest = bgp_route_next(dest)) {
14562 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14563 if (bdistance != NULL)
56ca3b5b 14564 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14565 bdistance->distance, dest,
d62a17ae 14566 bdistance->access_list ? bdistance->access_list
14567 : "");
ca2e160d 14568 }
718e3744 14569}
14570
14571/* Allocate routing table structure and install commands. */
d62a17ae 14572void bgp_route_init(void)
14573{
14574 afi_t afi;
14575 safi_t safi;
14576
14577 /* Init BGP distance table. */
05c7a1cc 14578 FOREACH_AFI_SAFI (afi, safi)
960035b2 14579 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14580
14581 /* IPv4 BGP commands. */
14582 install_element(BGP_NODE, &bgp_table_map_cmd);
14583 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14584 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14585
554b3b10 14586 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14587
14588 /* IPv4 unicast configuration. */
14589 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14590 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14591 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14592
554b3b10 14593 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14594
14595 /* IPv4 multicast configuration. */
14596 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14597 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14598 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14599 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14600
14601 /* IPv4 labeled-unicast configuration. */
fb985e0c 14602 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14603 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14604
d62a17ae 14605 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14606 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14607 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14608 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14609 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14610 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14611 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14612 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14613
14614 install_element(VIEW_NODE,
14615 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14616 install_element(VIEW_NODE,
14617 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14618 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14619 install_element(VIEW_NODE,
14620 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14621#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14622 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14623#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14624 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14625 install_element(VIEW_NODE,
44c69747 14626 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14627
d62a17ae 14628 /* BGP dampening clear commands */
14629 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14630 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14631
d62a17ae 14632 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14633 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14634
14635 /* prefix count */
14636 install_element(ENABLE_NODE,
14637 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14638#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14639 install_element(ENABLE_NODE,
14640 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14641#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14642
d62a17ae 14643 /* New config IPv6 BGP commands. */
14644 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14645 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14646 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14647
554b3b10 14648 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14649
14650 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14651
fb985e0c
DA
14652 /* IPv6 labeled unicast address family. */
14653 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14654 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14655
d62a17ae 14656 install_element(BGP_NODE, &bgp_distance_cmd);
14657 install_element(BGP_NODE, &no_bgp_distance_cmd);
14658 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14659 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14660 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14661 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14662 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14663 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14664 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14665 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14666 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14667 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14668 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14669 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14670 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14671
ef5f4b23 14672 /* BGP dampening */
d9ce5113
CS
14673 install_element(BGP_NODE, &bgp_dampening_cmd);
14674 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14675 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14676 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14677 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14678 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14679 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14680
14681 /* Large Communities */
14682 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14683 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14684
14685 /* show bgp ipv4 flowspec detailed */
14686 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14687
2a0e69ae 14688 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14689 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14690}
14691
14692void bgp_route_finish(void)
14693{
14694 afi_t afi;
14695 safi_t safi;
14696
05c7a1cc
QY
14697 FOREACH_AFI_SAFI (afi, safi) {
14698 bgp_table_unlock(bgp_distance_table[afi][safi]);
14699 bgp_distance_table[afi][safi] = NULL;
14700 }
228da428 14701}