]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
tests: Check if BLACKHOLE community prefixes are visible inside local AS
[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
718e3744 96/* Extern from bgp_dump.c */
dde72586
SH
97extern const char *bgp_origin_str[];
98extern const char *bgp_origin_long_str[];
3742de8d 99
b7d08f5a 100/* PMSI strings. */
101#define PMSI_TNLTYPE_STR_NO_INFO "No info"
102#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
103static const struct message bgp_pmsi_tnltype_str[] = {
104 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
105 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
106 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
107 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
108 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
109 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
110 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
111 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 112 {0}
113};
b7d08f5a 114
9df8b37c
PZ
115#define VRFID_NONE_STR "-"
116
4a11bf2c 117DEFINE_HOOK(bgp_process,
9bcb3eef
DS
118 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
119 struct peer *peer, bool withdraw),
120 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c 121
4056a5f6
RZ
122/** Test if path is suppressed. */
123static bool bgp_path_suppressed(struct bgp_path_info *pi)
124{
125 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
126 return false;
127
128 return listcount(pi->extra->aggr_suppressors) > 0;
129}
4a11bf2c 130
9bcb3eef 131struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 132 safi_t safi, const struct prefix *p,
d62a17ae 133 struct prefix_rd *prd)
134{
9bcb3eef
DS
135 struct bgp_dest *dest;
136 struct bgp_dest *pdest = NULL;
d62a17ae 137
138 assert(table);
d62a17ae 139
140 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
141 || (safi == SAFI_EVPN)) {
9bcb3eef 142 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 143
9bcb3eef
DS
144 if (!bgp_dest_has_bgp_path_info_data(pdest))
145 bgp_dest_set_bgp_table_info(
146 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 147 else
9bcb3eef
DS
148 bgp_dest_unlock_node(pdest);
149 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 150 }
718e3744 151
9bcb3eef 152 dest = bgp_node_get(table, p);
718e3744 153
d62a17ae 154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN))
9bcb3eef 156 dest->pdest = pdest;
718e3744 157
9bcb3eef 158 return dest;
718e3744 159}
6b0655a2 160
9bcb3eef 161struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 162 safi_t safi, const struct prefix *p,
d62a17ae 163 struct prefix_rd *prd)
128ea8ab 164{
9bcb3eef
DS
165 struct bgp_dest *dest;
166 struct bgp_dest *pdest = NULL;
128ea8ab 167
d62a17ae 168 if (!table)
169 return NULL;
128ea8ab 170
d62a17ae 171 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
172 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
173 pdest = bgp_node_lookup(table, (struct prefix *)prd);
174 if (!pdest)
d62a17ae 175 return NULL;
128ea8ab 176
9bcb3eef
DS
177 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
178 bgp_dest_unlock_node(pdest);
d62a17ae 179 return NULL;
180 }
128ea8ab 181
9bcb3eef 182 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 183 }
128ea8ab 184
9bcb3eef 185 dest = bgp_node_lookup(table, p);
128ea8ab 186
9bcb3eef 187 return dest;
128ea8ab 188}
189
18ee8310
DS
190/* Allocate bgp_path_info_extra */
191static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 192{
4b7e6066
DS
193 struct bgp_path_info_extra *new;
194 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
195 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
196 new->label[0] = MPLS_INVALID_LABEL;
197 new->num_labels = 0;
3e3708cb
PG
198 new->bgp_fs_pbr = NULL;
199 new->bgp_fs_iprule = NULL;
d62a17ae 200 return new;
fb982c25
PJ
201}
202
a2e219fe 203void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 204{
4b7e6066 205 struct bgp_path_info_extra *e;
d62a17ae 206
c93a3b77
DS
207 if (!extra || !*extra)
208 return;
d62a17ae 209
c93a3b77 210 e = *extra;
d62a17ae 211
c93a3b77
DS
212 e->damp_info = NULL;
213 if (e->parent) {
40381db7 214 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 215
40381db7 216 if (bpi->net) {
0e70e6c8
DL
217 /* FIXME: since multiple e may have the same e->parent
218 * and e->parent->net is holding a refcount for each
219 * of them, we need to do some fudging here.
220 *
40381db7
DS
221 * WARNING: if bpi->net->lock drops to 0, bpi may be
222 * freed as well (because bpi->net was holding the
223 * last reference to bpi) => write after free!
0e70e6c8
DL
224 */
225 unsigned refcount;
226
40381db7 227 bpi = bgp_path_info_lock(bpi);
c10e14e9 228 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 229 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 230 if (!refcount)
40381db7
DS
231 bpi->net = NULL;
232 bgp_path_info_unlock(bpi);
0e70e6c8 233 }
18ee8310 234 bgp_path_info_unlock(e->parent);
c93a3b77 235 e->parent = NULL;
d62a17ae 236 }
c93a3b77
DS
237
238 if (e->bgp_orig)
239 bgp_unlock(e->bgp_orig);
c26edcda 240
ff3bf9a4
DS
241 if (e->aggr_suppressors)
242 list_delete(&e->aggr_suppressors);
243
26c03e43
AK
244 if (e->es_info)
245 bgp_evpn_path_es_info_free(e->es_info);
246
ce3c0614
PG
247 if ((*extra)->bgp_fs_iprule)
248 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 249 if ((*extra)->bgp_fs_pbr)
6a154c88 250 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 251 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
252}
253
18ee8310
DS
254/* Get bgp_path_info extra information for the given bgp_path_info, lazy
255 * allocated if required.
fb982c25 256 */
40381db7 257struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 258{
40381db7
DS
259 if (!pi->extra)
260 pi->extra = bgp_path_info_extra_new();
261 return pi->extra;
fb982c25
PJ
262}
263
718e3744 264/* Free bgp route information. */
9b6d8fcf 265static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 266{
05864da7 267 bgp_attr_unintern(&path->attr);
fb018d25 268
9b6d8fcf
DS
269 bgp_unlink_nexthop(path);
270 bgp_path_info_extra_free(&path->extra);
271 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
272 if (path->net)
273 bgp_addpath_free_info_data(&path->tx_addpath,
274 &path->net->tx_addpath);
718e3744 275
9b6d8fcf 276 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 277
9b6d8fcf 278 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 279}
280
9b6d8fcf 281struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 282{
9b6d8fcf
DS
283 path->lock++;
284 return path;
200df115 285}
286
9b6d8fcf 287struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 288{
9b6d8fcf
DS
289 assert(path && path->lock > 0);
290 path->lock--;
d62a17ae 291
9b6d8fcf 292 if (path->lock == 0) {
200df115 293#if 0
294 zlog_debug ("%s: unlocked and freeing", __func__);
295 zlog_backtrace (LOG_DEBUG);
296#endif
9b6d8fcf 297 bgp_path_info_free(path);
d62a17ae 298 return NULL;
299 }
200df115 300
301#if 0
9b6d8fcf 302 if (path->lock == 1)
200df115 303 {
304 zlog_debug ("%s: unlocked to 1", __func__);
305 zlog_backtrace (LOG_DEBUG);
306 }
307#endif
d62a17ae 308
9b6d8fcf 309 return path;
200df115 310}
311
f009ff26 312/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 313static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 314{
315 struct peer *peer;
316 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 317 bool set_flag = false;
f009ff26 318 struct bgp *bgp = NULL;
319 struct bgp_table *table = NULL;
320 afi_t afi = 0;
321 safi_t safi = 0;
f009ff26 322
323 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
324 * then the route selection is deferred
325 */
9bcb3eef 326 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 327 return 0;
328
9bcb3eef 329 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 330 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 331 zlog_debug(
56ca3b5b
DL
332 "Route %pBD is in workqueue and being processed, not deferred.",
333 dest);
b54892e0 334
5f9c1aa2 335 return 0;
336 }
337
9bcb3eef 338 table = bgp_dest_table(dest);
f009ff26 339 if (table) {
340 bgp = table->bgp;
341 afi = table->afi;
342 safi = table->safi;
343 }
344
9bcb3eef 345 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 346 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
347 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
348 continue;
349
350 /* Route selection is deferred if there is a stale path which
351 * which indicates peer is in restart mode
352 */
36235319
QY
353 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
354 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 355 set_flag = true;
f009ff26 356 } else {
357 /* If the peer is graceful restart capable and peer is
358 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
359 */
360 peer = old_pi->peer;
36235319
QY
361 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
362 && BGP_PEER_RESTARTING_MODE(peer)
363 && (old_pi
364 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 365 set_flag = true;
f009ff26 366 }
367 }
368 if (set_flag)
369 break;
370 }
371
372 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
373 * is active
374 */
2ba1fe69 375 if (set_flag && table) {
f009ff26 376 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
377 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
378 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 379 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 380 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
381 zlog_debug("DEFER route %pBD, dest %p", dest,
382 dest);
f009ff26 383 return 0;
384 }
385 }
386 return -1;
387}
388
9bcb3eef 389void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 390{
4b7e6066 391 struct bgp_path_info *top;
718e3744 392
9bcb3eef 393 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 394
6f94b685 395 pi->next = top;
40381db7 396 pi->prev = NULL;
d62a17ae 397 if (top)
40381db7 398 top->prev = pi;
9bcb3eef 399 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 400
40381db7 401 bgp_path_info_lock(pi);
9bcb3eef 402 bgp_dest_lock_node(dest);
40381db7 403 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 404 bgp_dest_set_defer_flag(dest, false);
718e3744 405}
406
d62a17ae 407/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 408 completion callback *only* */
9bcb3eef 409void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 410{
40381db7
DS
411 if (pi->next)
412 pi->next->prev = pi->prev;
413 if (pi->prev)
414 pi->prev->next = pi->next;
d62a17ae 415 else
9bcb3eef 416 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 417
40381db7
DS
418 bgp_path_info_mpath_dequeue(pi);
419 bgp_path_info_unlock(pi);
9bcb3eef 420 bgp_dest_unlock_node(dest);
718e3744 421}
422
9bcb3eef 423void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 424{
9bcb3eef 425 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 426 /* set of previous already took care of pcount */
40381db7 427 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 428}
429
18ee8310 430/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
431 called when a route is deleted and then quickly re-added before the
432 deletion has been processed */
9bcb3eef 433void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 434{
9bcb3eef 435 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 436 /* unset of previous already took care of pcount */
40381db7 437 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
438}
439
d62a17ae 440/* Adjust pcount as required */
9bcb3eef 441static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 442{
d62a17ae 443 struct bgp_table *table;
67174041 444
9bcb3eef 445 assert(dest && bgp_dest_table(dest));
40381db7 446 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 447
9bcb3eef 448 table = bgp_dest_table(dest);
67174041 449
40381db7 450 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 451 return;
452
40381db7
DS
453 if (!BGP_PATH_COUNTABLE(pi)
454 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 455
40381db7 456 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 457
458 /* slight hack, but more robust against errors. */
40381db7
DS
459 if (pi->peer->pcount[table->afi][table->safi])
460 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 461 else
450971aa 462 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 463 "Asked to decrement 0 prefix count for peer");
40381db7
DS
464 } else if (BGP_PATH_COUNTABLE(pi)
465 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
466 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
467 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 468 }
1a392d46
PJ
469}
470
40381db7
DS
471static int bgp_label_index_differs(struct bgp_path_info *pi1,
472 struct bgp_path_info *pi2)
28d58fd7 473{
40381db7 474 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 475}
1a392d46 476
18ee8310 477/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
478 * This is here primarily to keep prefix-count in check.
479 */
9bcb3eef 480void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 481 uint32_t flag)
1a392d46 482{
40381db7 483 SET_FLAG(pi->flags, flag);
d62a17ae 484
485 /* early bath if we know it's not a flag that changes countability state
486 */
487 if (!CHECK_FLAG(flag,
1defdda8 488 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 489 return;
490
9bcb3eef 491 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
492}
493
9bcb3eef 494void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 495 uint32_t flag)
1a392d46 496{
40381db7 497 UNSET_FLAG(pi->flags, flag);
d62a17ae 498
499 /* early bath if we know it's not a flag that changes countability state
500 */
501 if (!CHECK_FLAG(flag,
1defdda8 502 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 503 return;
504
9bcb3eef 505 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
506}
507
718e3744 508/* Get MED value. If MED value is missing and "bgp bestpath
509 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 510static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 511{
512 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
513 return attr->med;
514 else {
892fedb6 515 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 516 return BGP_MED_MAX;
517 else
518 return 0;
519 }
718e3744 520}
521
40381db7 522void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 523{
40381db7
DS
524 if (pi->addpath_rx_id)
525 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
526 pi->addpath_rx_id);
d62a17ae 527 else
40381db7 528 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 529}
9fbdd100 530
d62a17ae 531/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
532 */
18ee8310
DS
533static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
534 struct bgp_path_info *exist, int *paths_eq,
535 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
536 char *pfx_buf, afi_t afi, safi_t safi,
537 enum bgp_path_selection_reason *reason)
d62a17ae 538{
539 struct attr *newattr, *existattr;
540 bgp_peer_sort_t new_sort;
541 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
542 uint32_t new_pref;
543 uint32_t exist_pref;
544 uint32_t new_med;
545 uint32_t exist_med;
546 uint32_t new_weight;
547 uint32_t exist_weight;
d62a17ae 548 uint32_t newm, existm;
549 struct in_addr new_id;
550 struct in_addr exist_id;
551 int new_cluster;
552 int exist_cluster;
553 int internal_as_route;
554 int confed_as_route;
04d14c8b 555 int ret = 0;
d62a17ae 556 char new_buf[PATH_ADDPATH_STR_BUFFER];
557 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
558 uint32_t new_mm_seq;
559 uint32_t exist_mm_seq;
6d8c603a 560 int nh_cmp;
d071f237
AK
561 esi_t *exist_esi;
562 esi_t *new_esi;
563 bool same_esi;
564 bool old_proxy;
565 bool new_proxy;
33c6e933 566 bool new_origin, exist_origin;
d62a17ae 567
568 *paths_eq = 0;
569
570 /* 0. Null check. */
571 if (new == NULL) {
fdf81fa0 572 *reason = bgp_path_selection_none;
d62a17ae 573 if (debug)
574 zlog_debug("%s: new is NULL", pfx_buf);
575 return 0;
576 }
2ec1e66f 577
d62a17ae 578 if (debug)
18ee8310 579 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 580
d62a17ae 581 if (exist == NULL) {
fdf81fa0 582 *reason = bgp_path_selection_first;
d62a17ae 583 if (debug)
584 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
585 new_buf);
586 return 1;
587 }
2ec1e66f 588
d62a17ae 589 if (debug) {
18ee8310 590 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 591 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
592 pfx_buf, new_buf, new->flags, exist_buf,
593 exist->flags);
594 }
8ff56318 595
d62a17ae 596 newattr = new->attr;
597 existattr = exist->attr;
598
599 /* For EVPN routes, we cannot just go by local vs remote, we have to
600 * look at the MAC mobility sequence number, if present.
601 */
602 if (safi == SAFI_EVPN) {
603 /* This is an error condition described in RFC 7432 Section
604 * 15.2. The RFC
605 * states that in this scenario "the PE MUST alert the operator"
606 * but it
607 * does not state what other action to take. In order to provide
608 * some
609 * consistency in this scenario we are going to prefer the path
610 * with the
611 * sticky flag.
612 */
613 if (newattr->sticky != existattr->sticky) {
614 if (!debug) {
9bcb3eef
DS
615 prefix2str(
616 bgp_dest_get_prefix(new->net), pfx_buf,
617 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
618 bgp_path_info_path_with_addpath_rx_str(new,
619 new_buf);
620 bgp_path_info_path_with_addpath_rx_str(
621 exist, exist_buf);
d62a17ae 622 }
623
624 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 625 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
626 if (debug)
627 zlog_debug(
628 "%s: %s wins over %s due to sticky MAC flag",
629 pfx_buf, new_buf, exist_buf);
d62a17ae 630 return 1;
631 }
632
633 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 634 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
635 if (debug)
636 zlog_debug(
637 "%s: %s loses to %s due to sticky MAC flag",
638 pfx_buf, new_buf, exist_buf);
d62a17ae 639 return 0;
640 }
641 }
128ea8ab 642
d071f237
AK
643 new_esi = bgp_evpn_attr_get_esi(newattr);
644 exist_esi = bgp_evpn_attr_get_esi(existattr);
645 if (bgp_evpn_is_esi_valid(new_esi) &&
646 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
647 same_esi = true;
648 } else {
649 same_esi = false;
650 }
651
652 /* If both paths have the same non-zero ES and
653 * one path is local it wins.
654 * PS: Note the local path wins even if the remote
655 * has the higher MM seq. The local path's
656 * MM seq will be fixed up to match the highest
657 * rem seq, subsequently.
658 */
659 if (same_esi) {
660 char esi_buf[ESI_STR_LEN];
661
662 if (bgp_evpn_is_path_local(bgp, new)) {
663 *reason = bgp_path_selection_evpn_local_path;
664 if (debug)
665 zlog_debug(
666 "%s: %s wins over %s as ES %s is same and local",
667 pfx_buf, new_buf, exist_buf,
668 esi_to_str(new_esi, esi_buf,
669 sizeof(esi_buf)));
670 return 1;
671 }
672 if (bgp_evpn_is_path_local(bgp, exist)) {
673 *reason = bgp_path_selection_evpn_local_path;
674 if (debug)
675 zlog_debug(
676 "%s: %s loses to %s as ES %s is same and local",
677 pfx_buf, new_buf, exist_buf,
678 esi_to_str(new_esi, esi_buf,
679 sizeof(esi_buf)));
680 return 0;
681 }
682 }
683
d62a17ae 684 new_mm_seq = mac_mobility_seqnum(newattr);
685 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 686
d62a17ae 687 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 688 *reason = bgp_path_selection_evpn_seq;
d62a17ae 689 if (debug)
690 zlog_debug(
691 "%s: %s wins over %s due to MM seq %u > %u",
692 pfx_buf, new_buf, exist_buf, new_mm_seq,
693 exist_mm_seq);
694 return 1;
695 }
8ff56318 696
d62a17ae 697 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 698 *reason = bgp_path_selection_evpn_seq;
d62a17ae 699 if (debug)
700 zlog_debug(
701 "%s: %s loses to %s due to MM seq %u < %u",
702 pfx_buf, new_buf, exist_buf, new_mm_seq,
703 exist_mm_seq);
704 return 0;
705 }
6d8c603a 706
d071f237
AK
707 /* if the sequence numbers and ESI are the same and one path
708 * is non-proxy it wins (over proxy)
709 */
710 new_proxy = bgp_evpn_attr_is_proxy(newattr);
711 old_proxy = bgp_evpn_attr_is_proxy(existattr);
712 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
713 old_proxy != new_proxy) {
714 if (!new_proxy) {
715 *reason = bgp_path_selection_evpn_non_proxy;
716 if (debug)
717 zlog_debug(
718 "%s: %s wins over %s, same seq/es and non-proxy",
719 pfx_buf, new_buf, exist_buf);
720 return 1;
721 }
722
723 *reason = bgp_path_selection_evpn_non_proxy;
724 if (debug)
725 zlog_debug(
726 "%s: %s loses to %s, same seq/es and non-proxy",
727 pfx_buf, new_buf, exist_buf);
728 return 0;
729 }
730
6d8c603a
AK
731 /*
732 * if sequence numbers are the same path with the lowest IP
733 * wins
734 */
735 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
736 if (nh_cmp < 0) {
fdf81fa0 737 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
738 if (debug)
739 zlog_debug(
23d0a753 740 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 741 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 742 &new->attr->nexthop);
6d8c603a
AK
743 return 1;
744 }
745 if (nh_cmp > 0) {
fdf81fa0 746 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
747 if (debug)
748 zlog_debug(
23d0a753 749 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 750 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 751 &new->attr->nexthop);
6d8c603a
AK
752 return 0;
753 }
d62a17ae 754 }
9fbdd100 755
d62a17ae 756 /* 1. Weight check. */
d62a17ae 757 new_weight = newattr->weight;
758 exist_weight = existattr->weight;
8ff56318 759
d62a17ae 760 if (new_weight > exist_weight) {
fdf81fa0 761 *reason = bgp_path_selection_weight;
d62a17ae 762 if (debug)
763 zlog_debug("%s: %s wins over %s due to weight %d > %d",
764 pfx_buf, new_buf, exist_buf, new_weight,
765 exist_weight);
766 return 1;
767 }
718e3744 768
d62a17ae 769 if (new_weight < exist_weight) {
fdf81fa0 770 *reason = bgp_path_selection_weight;
d62a17ae 771 if (debug)
772 zlog_debug("%s: %s loses to %s due to weight %d < %d",
773 pfx_buf, new_buf, exist_buf, new_weight,
774 exist_weight);
775 return 0;
776 }
9fbdd100 777
d62a17ae 778 /* 2. Local preference check. */
779 new_pref = exist_pref = bgp->default_local_pref;
780
781 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
782 new_pref = newattr->local_pref;
783 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
784 exist_pref = existattr->local_pref;
785
786 if (new_pref > exist_pref) {
fdf81fa0 787 *reason = bgp_path_selection_local_pref;
d62a17ae 788 if (debug)
789 zlog_debug(
790 "%s: %s wins over %s due to localpref %d > %d",
791 pfx_buf, new_buf, exist_buf, new_pref,
792 exist_pref);
793 return 1;
794 }
718e3744 795
d62a17ae 796 if (new_pref < exist_pref) {
fdf81fa0 797 *reason = bgp_path_selection_local_pref;
d62a17ae 798 if (debug)
799 zlog_debug(
800 "%s: %s loses to %s due to localpref %d < %d",
801 pfx_buf, new_buf, exist_buf, new_pref,
802 exist_pref);
803 return 0;
804 }
9fbdd100 805
d62a17ae 806 /* 3. Local route check. We prefer:
807 * - BGP_ROUTE_STATIC
808 * - BGP_ROUTE_AGGREGATE
809 * - BGP_ROUTE_REDISTRIBUTE
810 */
33c6e933
DS
811 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
812 new->sub_type == BGP_ROUTE_IMPORTED);
813 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
814 exist->sub_type == BGP_ROUTE_IMPORTED);
815
816 if (new_origin && !exist_origin) {
fdf81fa0 817 *reason = bgp_path_selection_local_route;
d62a17ae 818 if (debug)
819 zlog_debug(
820 "%s: %s wins over %s due to preferred BGP_ROUTE type",
821 pfx_buf, new_buf, exist_buf);
822 return 1;
823 }
718e3744 824
33c6e933 825 if (!new_origin && exist_origin) {
fdf81fa0 826 *reason = bgp_path_selection_local_route;
d62a17ae 827 if (debug)
828 zlog_debug(
829 "%s: %s loses to %s due to preferred BGP_ROUTE type",
830 pfx_buf, new_buf, exist_buf);
831 return 0;
6811845b 832 }
718e3744 833
d62a17ae 834 /* 4. AS path length check. */
892fedb6 835 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 836 int exist_hops = aspath_count_hops(existattr->aspath);
837 int exist_confeds = aspath_count_confeds(existattr->aspath);
838
892fedb6 839 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 840 int aspath_hops;
841
842 aspath_hops = aspath_count_hops(newattr->aspath);
843 aspath_hops += aspath_count_confeds(newattr->aspath);
844
845 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 846 *reason = bgp_path_selection_confed_as_path;
d62a17ae 847 if (debug)
848 zlog_debug(
849 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
850 pfx_buf, new_buf, exist_buf,
851 aspath_hops,
852 (exist_hops + exist_confeds));
853 return 1;
854 }
855
856 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 857 *reason = bgp_path_selection_confed_as_path;
d62a17ae 858 if (debug)
859 zlog_debug(
860 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
861 pfx_buf, new_buf, exist_buf,
862 aspath_hops,
863 (exist_hops + exist_confeds));
864 return 0;
865 }
866 } else {
867 int newhops = aspath_count_hops(newattr->aspath);
868
869 if (newhops < exist_hops) {
fdf81fa0 870 *reason = bgp_path_selection_as_path;
d62a17ae 871 if (debug)
872 zlog_debug(
873 "%s: %s wins over %s due to aspath hopcount %d < %d",
874 pfx_buf, new_buf, exist_buf,
875 newhops, exist_hops);
876 return 1;
877 }
878
879 if (newhops > exist_hops) {
fdf81fa0 880 *reason = bgp_path_selection_as_path;
d62a17ae 881 if (debug)
882 zlog_debug(
883 "%s: %s loses to %s due to aspath hopcount %d > %d",
884 pfx_buf, new_buf, exist_buf,
885 newhops, exist_hops);
886 return 0;
887 }
888 }
889 }
9fbdd100 890
d62a17ae 891 /* 5. Origin check. */
892 if (newattr->origin < existattr->origin) {
fdf81fa0 893 *reason = bgp_path_selection_origin;
d62a17ae 894 if (debug)
895 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
896 pfx_buf, new_buf, exist_buf,
897 bgp_origin_long_str[newattr->origin],
898 bgp_origin_long_str[existattr->origin]);
899 return 1;
900 }
718e3744 901
d62a17ae 902 if (newattr->origin > existattr->origin) {
fdf81fa0 903 *reason = bgp_path_selection_origin;
d62a17ae 904 if (debug)
905 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
906 pfx_buf, new_buf, exist_buf,
907 bgp_origin_long_str[newattr->origin],
908 bgp_origin_long_str[existattr->origin]);
909 return 0;
910 }
718e3744 911
d62a17ae 912 /* 6. MED check. */
913 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
914 && aspath_count_hops(existattr->aspath) == 0);
915 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
916 && aspath_count_confeds(existattr->aspath) > 0
917 && aspath_count_hops(newattr->aspath) == 0
918 && aspath_count_hops(existattr->aspath) == 0);
919
892fedb6
DA
920 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
921 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 922 || aspath_cmp_left(newattr->aspath, existattr->aspath)
923 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
924 || internal_as_route) {
925 new_med = bgp_med_value(new->attr, bgp);
926 exist_med = bgp_med_value(exist->attr, bgp);
927
928 if (new_med < exist_med) {
fdf81fa0 929 *reason = bgp_path_selection_med;
d62a17ae 930 if (debug)
931 zlog_debug(
932 "%s: %s wins over %s due to MED %d < %d",
933 pfx_buf, new_buf, exist_buf, new_med,
934 exist_med);
935 return 1;
936 }
8ff56318 937
d62a17ae 938 if (new_med > exist_med) {
fdf81fa0 939 *reason = bgp_path_selection_med;
d62a17ae 940 if (debug)
941 zlog_debug(
942 "%s: %s loses to %s due to MED %d > %d",
943 pfx_buf, new_buf, exist_buf, new_med,
944 exist_med);
945 return 0;
946 }
947 }
9fbdd100 948
d62a17ae 949 /* 7. Peer type check. */
950 new_sort = new->peer->sort;
951 exist_sort = exist->peer->sort;
952
953 if (new_sort == BGP_PEER_EBGP
954 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 955 *reason = bgp_path_selection_peer;
d62a17ae 956 if (debug)
957 zlog_debug(
958 "%s: %s wins over %s due to eBGP peer > iBGP peer",
959 pfx_buf, new_buf, exist_buf);
960 return 1;
961 }
718e3744 962
d62a17ae 963 if (exist_sort == BGP_PEER_EBGP
964 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 965 *reason = bgp_path_selection_peer;
d62a17ae 966 if (debug)
967 zlog_debug(
968 "%s: %s loses to %s due to iBGP peer < eBGP peer",
969 pfx_buf, new_buf, exist_buf);
970 return 0;
971 }
8ff56318 972
d62a17ae 973 /* 8. IGP metric check. */
974 newm = existm = 0;
8ff56318 975
d62a17ae 976 if (new->extra)
977 newm = new->extra->igpmetric;
978 if (exist->extra)
979 existm = exist->extra->igpmetric;
9fbdd100 980
d62a17ae 981 if (newm < existm) {
982 if (debug)
983 zlog_debug(
984 "%s: %s wins over %s due to IGP metric %d < %d",
985 pfx_buf, new_buf, exist_buf, newm, existm);
986 ret = 1;
987 }
718e3744 988
d62a17ae 989 if (newm > existm) {
990 if (debug)
991 zlog_debug(
992 "%s: %s loses to %s due to IGP metric %d > %d",
993 pfx_buf, new_buf, exist_buf, newm, existm);
994 ret = 0;
5e242b0d 995 }
5e242b0d 996
d62a17ae 997 /* 9. Same IGP metric. Compare the cluster list length as
998 representative of IGP hops metric. Rewrite the metric value
999 pair (newm, existm) with the cluster list length. Prefer the
1000 path with smaller cluster list length. */
1001 if (newm == existm) {
bf0d28dc
DS
1002 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1003 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1004 && (mpath_cfg == NULL
1005 || CHECK_FLAG(
1006 mpath_cfg->ibgp_flags,
1007 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1008 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1009 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1010
1011 if (newm < existm) {
1012 if (debug)
1013 zlog_debug(
1014 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1015 pfx_buf, new_buf, exist_buf,
1016 newm, existm);
1017 ret = 1;
1018 }
1019
1020 if (newm > existm) {
1021 if (debug)
1022 zlog_debug(
1023 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1024 pfx_buf, new_buf, exist_buf,
1025 newm, existm);
1026 ret = 0;
1027 }
1028 }
1029 }
31a4638f 1030
d62a17ae 1031 /* 10. confed-external vs. confed-internal */
1032 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1033 if (new_sort == BGP_PEER_CONFED
1034 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1035 *reason = bgp_path_selection_confed;
d62a17ae 1036 if (debug)
1037 zlog_debug(
1038 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1039 pfx_buf, new_buf, exist_buf);
1040 return 1;
1041 }
718e3744 1042
d62a17ae 1043 if (exist_sort == BGP_PEER_CONFED
1044 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1045 *reason = bgp_path_selection_confed;
d62a17ae 1046 if (debug)
1047 zlog_debug(
1048 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1049 pfx_buf, new_buf, exist_buf);
1050 return 0;
1051 }
1052 }
718e3744 1053
d62a17ae 1054 /* 11. Maximum path check. */
1055 if (newm == existm) {
1056 /* If one path has a label but the other does not, do not treat
1057 * them as equals for multipath
1058 */
a4d82a8a 1059 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1060 != (exist->extra
b57ba6d2 1061 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1062 if (debug)
1063 zlog_debug(
1064 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1065 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1066 } else if (CHECK_FLAG(bgp->flags,
1067 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1068
1069 /*
1070 * For the two paths, all comparison steps till IGP
1071 * metric
1072 * have succeeded - including AS_PATH hop count. Since
1073 * 'bgp
1074 * bestpath as-path multipath-relax' knob is on, we
1075 * don't need
1076 * an exact match of AS_PATH. Thus, mark the paths are
1077 * equal.
1078 * That will trigger both these paths to get into the
1079 * multipath
1080 * array.
1081 */
1082 *paths_eq = 1;
1083
1084 if (debug)
1085 zlog_debug(
1086 "%s: %s and %s are equal via multipath-relax",
1087 pfx_buf, new_buf, exist_buf);
1088 } else if (new->peer->sort == BGP_PEER_IBGP) {
1089 if (aspath_cmp(new->attr->aspath,
1090 exist->attr->aspath)) {
1091 *paths_eq = 1;
1092
1093 if (debug)
1094 zlog_debug(
1095 "%s: %s and %s are equal via matching aspaths",
1096 pfx_buf, new_buf, exist_buf);
1097 }
1098 } else if (new->peer->as == exist->peer->as) {
1099 *paths_eq = 1;
1100
1101 if (debug)
1102 zlog_debug(
1103 "%s: %s and %s are equal via same remote-as",
1104 pfx_buf, new_buf, exist_buf);
1105 }
1106 } else {
1107 /*
1108 * TODO: If unequal cost ibgp multipath is enabled we can
1109 * mark the paths as equal here instead of returning
1110 */
1111 if (debug) {
1112 if (ret == 1)
1113 zlog_debug(
1114 "%s: %s wins over %s after IGP metric comparison",
1115 pfx_buf, new_buf, exist_buf);
1116 else
1117 zlog_debug(
1118 "%s: %s loses to %s after IGP metric comparison",
1119 pfx_buf, new_buf, exist_buf);
1120 }
fdf81fa0 1121 *reason = bgp_path_selection_igp_metric;
d62a17ae 1122 return ret;
1123 }
718e3744 1124
d62a17ae 1125 /* 12. If both paths are external, prefer the path that was received
1126 first (the oldest one). This step minimizes route-flap, since a
1127 newer path won't displace an older one, even if it was the
1128 preferred route based on the additional decision criteria below. */
892fedb6 1129 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1130 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1131 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1132 *reason = bgp_path_selection_older;
d62a17ae 1133 if (debug)
1134 zlog_debug(
1135 "%s: %s wins over %s due to oldest external",
1136 pfx_buf, new_buf, exist_buf);
1137 return 1;
1138 }
9fbdd100 1139
1defdda8 1140 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1141 *reason = bgp_path_selection_older;
d62a17ae 1142 if (debug)
1143 zlog_debug(
1144 "%s: %s loses to %s due to oldest external",
1145 pfx_buf, new_buf, exist_buf);
1146 return 0;
1147 }
1148 }
718e3744 1149
d62a17ae 1150 /* 13. Router-ID comparision. */
1151 /* If one of the paths is "stale", the corresponding peer router-id will
1152 * be 0 and would always win over the other path. If originator id is
1153 * used for the comparision, it will decide which path is better.
1154 */
1155 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1156 new_id.s_addr = newattr->originator_id.s_addr;
1157 else
1158 new_id.s_addr = new->peer->remote_id.s_addr;
1159 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1160 exist_id.s_addr = existattr->originator_id.s_addr;
1161 else
1162 exist_id.s_addr = exist->peer->remote_id.s_addr;
1163
1164 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1165 *reason = bgp_path_selection_router_id;
d62a17ae 1166 if (debug)
1167 zlog_debug(
1168 "%s: %s wins over %s due to Router-ID comparison",
1169 pfx_buf, new_buf, exist_buf);
1170 return 1;
1171 }
718e3744 1172
d62a17ae 1173 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1174 *reason = bgp_path_selection_router_id;
d62a17ae 1175 if (debug)
1176 zlog_debug(
1177 "%s: %s loses to %s due to Router-ID comparison",
1178 pfx_buf, new_buf, exist_buf);
1179 return 0;
1180 }
9fbdd100 1181
d62a17ae 1182 /* 14. Cluster length comparision. */
1183 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1184 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1185
1186 if (new_cluster < exist_cluster) {
fdf81fa0 1187 *reason = bgp_path_selection_cluster_length;
d62a17ae 1188 if (debug)
1189 zlog_debug(
1190 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1191 pfx_buf, new_buf, exist_buf, new_cluster,
1192 exist_cluster);
1193 return 1;
1194 }
718e3744 1195
d62a17ae 1196 if (new_cluster > exist_cluster) {
fdf81fa0 1197 *reason = bgp_path_selection_cluster_length;
d62a17ae 1198 if (debug)
1199 zlog_debug(
1200 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1201 pfx_buf, new_buf, exist_buf, new_cluster,
1202 exist_cluster);
1203 return 0;
1204 }
9fbdd100 1205
d62a17ae 1206 /* 15. Neighbor address comparision. */
1207 /* Do this only if neither path is "stale" as stale paths do not have
1208 * valid peer information (as the connection may or may not be up).
1209 */
1defdda8 1210 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1211 *reason = bgp_path_selection_stale;
d62a17ae 1212 if (debug)
1213 zlog_debug(
1214 "%s: %s wins over %s due to latter path being STALE",
1215 pfx_buf, new_buf, exist_buf);
1216 return 1;
1217 }
0de5153c 1218
1defdda8 1219 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1220 *reason = bgp_path_selection_stale;
d62a17ae 1221 if (debug)
1222 zlog_debug(
1223 "%s: %s loses to %s due to former path being STALE",
1224 pfx_buf, new_buf, exist_buf);
1225 return 0;
1226 }
718e3744 1227
d62a17ae 1228 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1229 if (new->peer->su_remote == NULL) {
1230 *reason = bgp_path_selection_local_configured;
d62a17ae 1231 return 0;
fdf81fa0
DS
1232 }
1233 if (exist->peer->su_remote == NULL) {
1234 *reason = bgp_path_selection_local_configured;
d62a17ae 1235 return 1;
fdf81fa0 1236 }
9fbdd100 1237
d62a17ae 1238 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1239
1240 if (ret == 1) {
fdf81fa0 1241 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1242 if (debug)
1243 zlog_debug(
1244 "%s: %s loses to %s due to Neighor IP comparison",
1245 pfx_buf, new_buf, exist_buf);
1246 return 0;
1247 }
1248
1249 if (ret == -1) {
fdf81fa0 1250 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1251 if (debug)
1252 zlog_debug(
1253 "%s: %s wins over %s due to Neighor IP comparison",
1254 pfx_buf, new_buf, exist_buf);
1255 return 1;
1256 }
9fbdd100 1257
fdf81fa0 1258 *reason = bgp_path_selection_default;
d62a17ae 1259 if (debug)
1260 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1261 pfx_buf, new_buf, exist_buf);
718e3744 1262
d62a17ae 1263 return 1;
718e3744 1264}
1265
d071f237
AK
1266
1267int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1268 struct bgp_path_info *exist, int *paths_eq)
1269{
1270 enum bgp_path_selection_reason reason;
1271 char pfx_buf[PREFIX2STR_BUFFER];
1272
1273 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1274 AFI_L2VPN, SAFI_EVPN, &reason);
1275}
1276
65efcfce
LB
1277/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1278 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1279 * multipath is enabled
65efcfce 1280 * This version is compatible with */
18ee8310
DS
1281int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1282 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1283 afi_t afi, safi_t safi,
1284 enum bgp_path_selection_reason *reason)
d62a17ae 1285{
1286 int paths_eq;
1287 int ret;
18ee8310 1288 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1289 afi, safi, reason);
d62a17ae 1290
1291 if (paths_eq)
1292 ret = 0;
1293 else {
1294 if (ret == 1)
1295 ret = -1;
1296 else
1297 ret = 1;
1298 }
1299 return ret;
65efcfce
LB
1300}
1301
5a1ae2c2
DS
1302static enum filter_type bgp_input_filter(struct peer *peer,
1303 const struct prefix *p,
d62a17ae 1304 struct attr *attr, afi_t afi,
1305 safi_t safi)
718e3744 1306{
d62a17ae 1307 struct bgp_filter *filter;
6401252f 1308 enum filter_type ret = FILTER_PERMIT;
718e3744 1309
d62a17ae 1310 filter = &peer->filter[afi][safi];
718e3744 1311
d62a17ae 1312#define FILTER_EXIST_WARN(F, f, filter) \
1313 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1314 zlog_debug("%s: Could not find configured input %s-list %s!", \
1315 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1316
1317 if (DISTRIBUTE_IN_NAME(filter)) {
1318 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1319
6401252f
QY
1320 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1321 == FILTER_DENY) {
1322 ret = FILTER_DENY;
1323 goto done;
1324 }
d62a17ae 1325 }
1326
1327 if (PREFIX_LIST_IN_NAME(filter)) {
1328 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1329
6401252f
QY
1330 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1331 == PREFIX_DENY) {
1332 ret = FILTER_DENY;
1333 goto done;
1334 }
d62a17ae 1335 }
1336
1337 if (FILTER_LIST_IN_NAME(filter)) {
1338 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1339
1340 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1341 == AS_FILTER_DENY) {
1342 ret = FILTER_DENY;
1343 goto done;
1344 }
d62a17ae 1345 }
1346
6401252f 1347done:
c7bb4f00 1348 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1349 char pfxprint[PREFIX2STR_BUFFER];
1350
1351 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1352 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1353 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1354 }
1355
1356 return ret;
650f76c2 1357#undef FILTER_EXIST_WARN
718e3744 1358}
1359
b8685f9b
DS
1360static enum filter_type bgp_output_filter(struct peer *peer,
1361 const struct prefix *p,
d62a17ae 1362 struct attr *attr, afi_t afi,
1363 safi_t safi)
718e3744 1364{
d62a17ae 1365 struct bgp_filter *filter;
6401252f 1366 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1367
1368 filter = &peer->filter[afi][safi];
1369
1370#define FILTER_EXIST_WARN(F, f, filter) \
1371 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1372 zlog_debug("%s: Could not find configured output %s-list %s!", \
1373 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1374
d62a17ae 1375 if (DISTRIBUTE_OUT_NAME(filter)) {
1376 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1377
6401252f
QY
1378 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1379 == FILTER_DENY) {
1380 ret = FILTER_DENY;
1381 goto done;
1382 }
d62a17ae 1383 }
1384
1385 if (PREFIX_LIST_OUT_NAME(filter)) {
1386 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1387
d62a17ae 1388 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1389 == PREFIX_DENY) {
1390 ret = FILTER_DENY;
1391 goto done;
1392 }
d62a17ae 1393 }
718e3744 1394
d62a17ae 1395 if (FILTER_LIST_OUT_NAME(filter)) {
1396 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1397
d62a17ae 1398 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1399 == AS_FILTER_DENY) {
1400 ret = FILTER_DENY;
1401 goto done;
1402 }
1403 }
1404
c7bb4f00 1405 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1406 char pfxprint[PREFIX2STR_BUFFER];
1407
1408 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1409 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1410 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1411 }
718e3744 1412
6401252f
QY
1413done:
1414 return ret;
650f76c2 1415#undef FILTER_EXIST_WARN
718e3744 1416}
1417
1418/* If community attribute includes no_export then return 1. */
3dc339cd 1419static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1420{
1421 if (attr->community) {
1422 /* NO_ADVERTISE check. */
1423 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1424 return true;
d62a17ae 1425
1426 /* NO_EXPORT check. */
1427 if (peer->sort == BGP_PEER_EBGP
1428 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1429 return true;
d62a17ae 1430
1431 /* NO_EXPORT_SUBCONFED check. */
1432 if (peer->sort == BGP_PEER_EBGP
1433 || peer->sort == BGP_PEER_CONFED)
1434 if (community_include(attr->community,
1435 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1436 return true;
d62a17ae 1437 }
3dc339cd 1438 return false;
718e3744 1439}
1440
1441/* Route reflection loop check. */
3dc339cd 1442static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1443{
d62a17ae 1444 struct in_addr cluster_id;
779fee93 1445 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1446
779fee93 1447 if (cluster) {
d62a17ae 1448 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1449 cluster_id = peer->bgp->cluster_id;
1450 else
1451 cluster_id = peer->bgp->router_id;
1452
779fee93 1453 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1454 return true;
d62a17ae 1455 }
3dc339cd 1456 return false;
718e3744 1457}
6b0655a2 1458
5a1ae2c2 1459static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1460 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1461 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1462 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1463{
d62a17ae 1464 struct bgp_filter *filter;
82b692c0
LK
1465 struct bgp_path_info rmap_path = { 0 };
1466 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1467 route_map_result_t ret;
1468 struct route_map *rmap = NULL;
718e3744 1469
d62a17ae 1470 filter = &peer->filter[afi][safi];
718e3744 1471
d62a17ae 1472 /* Apply default weight value. */
1473 if (peer->weight[afi][safi])
1474 attr->weight = peer->weight[afi][safi];
718e3744 1475
d62a17ae 1476 if (rmap_name) {
1477 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1478
d62a17ae 1479 if (rmap == NULL)
1480 return RMAP_DENY;
1481 } else {
1482 if (ROUTE_MAP_IN_NAME(filter)) {
1483 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1484
d62a17ae 1485 if (rmap == NULL)
1486 return RMAP_DENY;
1487 }
1488 }
0b16f239 1489
d62a17ae 1490 /* Route map apply. */
1491 if (rmap) {
40381db7 1492 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1493 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1494 rmap_path.peer = peer;
1495 rmap_path.attr = attr;
82b692c0 1496 rmap_path.extra = &extra;
9bcb3eef 1497 rmap_path.net = dest;
196c6b09 1498
82b692c0
LK
1499 extra.num_labels = num_labels;
1500 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1501 memcpy(extra.label, label,
1502 num_labels * sizeof(mpls_label_t));
718e3744 1503
d62a17ae 1504 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1505
d62a17ae 1506 /* Apply BGP route map to the attribute. */
1782514f 1507 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1508
d62a17ae 1509 peer->rmap_type = 0;
0b16f239 1510
1f2263be 1511 if (ret == RMAP_DENYMATCH)
d62a17ae 1512 return RMAP_DENY;
0b16f239 1513 }
d62a17ae 1514 return RMAP_PERMIT;
0b16f239
DS
1515}
1516
5f040085 1517static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1518 struct attr *attr, afi_t afi, safi_t safi,
1519 const char *rmap_name)
0b16f239 1520{
40381db7 1521 struct bgp_path_info rmap_path;
d62a17ae 1522 route_map_result_t ret;
1523 struct route_map *rmap = NULL;
d7c0a89a 1524 uint8_t rmap_type;
0b16f239 1525
b787157a
DS
1526 /*
1527 * So if we get to this point and have no rmap_name
1528 * we want to just show the output as it currently
1529 * exists.
1530 */
1531 if (!rmap_name)
1532 return RMAP_PERMIT;
0b16f239 1533
d62a17ae 1534 /* Apply default weight value. */
1535 if (peer->weight[afi][safi])
1536 attr->weight = peer->weight[afi][safi];
0b16f239 1537
b787157a 1538 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1539
b787157a
DS
1540 /*
1541 * If we have a route map name and we do not find
1542 * the routemap that means we have an implicit
1543 * deny.
1544 */
1545 if (rmap == NULL)
1546 return RMAP_DENY;
0b16f239 1547
40381db7 1548 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1549 /* Route map apply. */
b787157a 1550 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1551 rmap_path.peer = peer;
1552 rmap_path.attr = attr;
0b16f239 1553
0f672529 1554 rmap_type = peer->rmap_type;
b787157a 1555 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1556
b787157a 1557 /* Apply BGP route map to the attribute. */
1782514f 1558 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1559
0f672529 1560 peer->rmap_type = rmap_type;
b787157a
DS
1561
1562 if (ret == RMAP_DENYMATCH)
1563 /*
1564 * caller has multiple error paths with bgp_attr_flush()
1565 */
1566 return RMAP_DENY;
ac41b2a2 1567
d62a17ae 1568 return RMAP_PERMIT;
718e3744 1569}
6b0655a2 1570
5000f21c 1571/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1572static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1573 struct peer *peer, struct attr *attr)
1574{
1575 if (peer->sort == BGP_PEER_EBGP
1576 && (peer_af_flag_check(peer, afi, safi,
1577 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1578 || peer_af_flag_check(peer, afi, safi,
1579 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1580 || peer_af_flag_check(peer, afi, safi,
1581 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1582 || peer_af_flag_check(peer, afi, safi,
1583 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1584 // Take action on the entire aspath
1585 if (peer_af_flag_check(peer, afi, safi,
1586 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1587 || peer_af_flag_check(peer, afi, safi,
1588 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1589 if (peer_af_flag_check(
1590 peer, afi, safi,
1591 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1592 attr->aspath = aspath_replace_private_asns(
bf26b80e 1593 attr->aspath, bgp->as, peer->as);
d62a17ae 1594
1595 // The entire aspath consists of private ASNs so create
1596 // an empty aspath
1597 else if (aspath_private_as_check(attr->aspath))
1598 attr->aspath = aspath_empty_get();
1599
1600 // There are some public and some private ASNs, remove
1601 // the private ASNs
1602 else
1603 attr->aspath = aspath_remove_private_asns(
bf26b80e 1604 attr->aspath, peer->as);
d62a17ae 1605 }
1606
1607 // 'all' was not specified so the entire aspath must be private
1608 // ASNs
1609 // for us to do anything
1610 else if (aspath_private_as_check(attr->aspath)) {
1611 if (peer_af_flag_check(
1612 peer, afi, safi,
1613 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1614 attr->aspath = aspath_replace_private_asns(
bf26b80e 1615 attr->aspath, bgp->as, peer->as);
d62a17ae 1616 else
1617 attr->aspath = aspath_empty_get();
1618 }
1619 }
5000f21c
DS
1620}
1621
c7122e14 1622/* If this is an EBGP peer with as-override */
d62a17ae 1623static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1624 struct peer *peer, struct attr *attr)
1625{
1626 if (peer->sort == BGP_PEER_EBGP
1627 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1628 if (aspath_single_asn_check(attr->aspath, peer->as))
1629 attr->aspath = aspath_replace_specific_asn(
1630 attr->aspath, peer->as, bgp->as);
1631 }
1632}
1633
7f323236
DW
1634void bgp_attr_add_gshut_community(struct attr *attr)
1635{
1636 struct community *old;
1637 struct community *new;
1638 struct community *merge;
1639 struct community *gshut;
1640
1641 old = attr->community;
1642 gshut = community_str2com("graceful-shutdown");
1643
990f4f91 1644 assert(gshut);
1645
7f323236
DW
1646 if (old) {
1647 merge = community_merge(community_dup(old), gshut);
1648
a4d82a8a 1649 if (old->refcnt == 0)
3c1f53de 1650 community_free(&old);
7f323236
DW
1651
1652 new = community_uniq_sort(merge);
3c1f53de 1653 community_free(&merge);
7f323236
DW
1654 } else {
1655 new = community_dup(gshut);
1656 }
1657
3c1f53de 1658 community_free(&gshut);
7f323236
DW
1659 attr->community = new;
1660 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1661
1662 /* When we add the graceful-shutdown community we must also
1663 * lower the local-preference */
1664 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1665 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1666}
1667
1668
e73c112e
MK
1669/* Notify BGP Conditional advertisement scanner process. */
1670void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1671{
1672 struct peer *temp_peer;
1673 struct peer *peer = SUBGRP_PEER(subgrp);
1674 struct listnode *temp_node, *temp_nnode = NULL;
1675 afi_t afi = SUBGRP_AFI(subgrp);
1676 safi_t safi = SUBGRP_SAFI(subgrp);
1677 struct bgp *bgp = SUBGRP_INST(subgrp);
1678 struct bgp_filter *filter = &peer->filter[afi][safi];
1679
1680 if (!ADVERTISE_MAP_NAME(filter))
1681 return;
1682
1683 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1684 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1685 continue;
1686
1687 if (peer != temp_peer)
1688 continue;
1689
1690 temp_peer->advmap_table_change = true;
1691 break;
1692 }
1693}
1694
1695
f2ee6d5c 1696void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1697{
960035b2 1698 if (family == AF_INET) {
975a328e
DA
1699 attr->nexthop.s_addr = INADDR_ANY;
1700 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1701 }
d62a17ae 1702 if (family == AF_INET6)
1703 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1704 if (family == AF_EVPN)
1705 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1706}
1707
9bcb3eef 1708bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1709 struct update_subgroup *subgrp,
7f7940e6
MK
1710 const struct prefix *p, struct attr *attr,
1711 bool skip_rmap_check)
d62a17ae 1712{
1713 struct bgp_filter *filter;
1714 struct peer *from;
1715 struct peer *peer;
1716 struct peer *onlypeer;
1717 struct bgp *bgp;
40381db7 1718 struct attr *piattr;
b68885f9 1719 route_map_result_t ret;
d62a17ae 1720 int transparent;
1721 int reflect;
1722 afi_t afi;
1723 safi_t safi;
1724 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1725 bool nh_reset = false;
1726 uint64_t cum_bw;
d62a17ae 1727
1728 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1729 return false;
d62a17ae 1730
1731 afi = SUBGRP_AFI(subgrp);
1732 safi = SUBGRP_SAFI(subgrp);
1733 peer = SUBGRP_PEER(subgrp);
1734 onlypeer = NULL;
1735 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1736 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1737
40381db7 1738 from = pi->peer;
d62a17ae 1739 filter = &peer->filter[afi][safi];
1740 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1741 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1742 : pi->attr;
3f9c7369 1743
49e5a4a0 1744#ifdef ENABLE_BGP_VNC
d62a17ae 1745 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1746 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1747 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1748
1749 /*
1750 * direct and direct_ext type routes originate internally even
1751 * though they can have peer pointers that reference other
1752 * systems
1753 */
8228a9a7
DS
1754 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1755 __func__, p);
d62a17ae 1756 samepeer_safe = 1;
1757 }
65efcfce
LB
1758#endif
1759
ddb5b488
PZ
1760 if (((afi == AFI_IP) || (afi == AFI_IP6))
1761 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1762 && (pi->type == ZEBRA_ROUTE_BGP)
1763 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1764
1765 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1766
1767 samepeer_safe = 1;
1768 }
1769
d62a17ae 1770 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1771 * pi is valid */
1772 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1773 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1774 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1775 return false;
d62a17ae 1776 }
adbac85e 1777
d62a17ae 1778 /* If this is not the bestpath then check to see if there is an enabled
1779 * addpath
1780 * feature that requires us to advertise it */
40381db7 1781 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1782 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1783 return false;
d62a17ae 1784 }
1785 }
06370dac 1786
d62a17ae 1787 /* Aggregate-address suppress check. */
4056a5f6
RZ
1788 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1789 return false;
3f9c7369 1790
13b7e7f0
DS
1791 /*
1792 * If we are doing VRF 2 VRF leaking via the import
1793 * statement, we want to prevent the route going
1794 * off box as that the RT and RD created are localy
1795 * significant and globaly useless.
1796 */
40381db7
DS
1797 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1798 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1799 return false;
13b7e7f0 1800
d62a17ae 1801 /* If it's labeled safi, make sure the route has a valid label. */
1802 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1803 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1804 if (!bgp_is_valid_label(&label)) {
1805 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1806 zlog_debug("u%" PRIu64 ":s%" PRIu64
1807 " %pFX is filtered - no label (%p)",
d62a17ae 1808 subgrp->update_group->id, subgrp->id,
8228a9a7 1809 p, &label);
3dc339cd 1810 return false;
d62a17ae 1811 }
1812 }
cd1964ff 1813
d62a17ae 1814 /* Do not send back route to sender. */
1815 if (onlypeer && from == onlypeer) {
3dc339cd 1816 return false;
d62a17ae 1817 }
3f9c7369 1818
d62a17ae 1819 /* Do not send the default route in the BGP table if the neighbor is
1820 * configured for default-originate */
1821 if (CHECK_FLAG(peer->af_flags[afi][safi],
1822 PEER_FLAG_DEFAULT_ORIGINATE)) {
1823 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1824 return false;
d62a17ae 1825 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1826 return false;
d62a17ae 1827 }
4125bb67 1828
d62a17ae 1829 /* Transparency check. */
1830 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1831 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1832 transparent = 1;
1833 else
1834 transparent = 0;
1835
1836 /* If community is not disabled check the no-export and local. */
40381db7 1837 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1838 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1839 zlog_debug("%s: community filter check fail for %pFX",
1840 __func__, p);
3dc339cd 1841 return false;
d62a17ae 1842 }
3f9c7369 1843
d62a17ae 1844 /* If the attribute has originator-id and it is same as remote
1845 peer's id. */
40381db7
DS
1846 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1847 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1848 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1849 zlog_debug(
8228a9a7
DS
1850 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1851 onlypeer->host, p);
3dc339cd 1852 return false;
d62a17ae 1853 }
3f9c7369 1854
d62a17ae 1855 /* ORF prefix-list filter check */
1856 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1857 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1858 || CHECK_FLAG(peer->af_cap[afi][safi],
1859 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1860 if (peer->orf_plist[afi][safi]) {
1861 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1862 == PREFIX_DENY) {
1863 if (bgp_debug_update(NULL, p,
1864 subgrp->update_group, 0))
1865 zlog_debug(
8228a9a7
DS
1866 "%s [Update:SEND] %pFX is filtered via ORF",
1867 peer->host, p);
3dc339cd 1868 return false;
d62a17ae 1869 }
1870 }
1871
1872 /* Output filter check. */
40381db7 1873 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1874 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1875 zlog_debug("%s [Update:SEND] %pFX is filtered",
1876 peer->host, p);
3dc339cd 1877 return false;
d62a17ae 1878 }
3f9c7369 1879
d62a17ae 1880 /* AS path loop check. */
2b31007c
RZ
1881 if (onlypeer && onlypeer->as_path_loop_detection
1882 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1883 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1884 zlog_debug(
3efd0893 1885 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1886 onlypeer->host, onlypeer->as);
3dc339cd 1887 return false;
d62a17ae 1888 }
3f9c7369 1889
d62a17ae 1890 /* If we're a CONFED we need to loop check the CONFED ID too */
1891 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1892 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1893 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1894 zlog_debug(
3efd0893 1895 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1896 peer->host, bgp->confed_id);
3dc339cd 1897 return false;
d62a17ae 1898 }
3f9c7369 1899 }
3f9c7369 1900
d62a17ae 1901 /* Route-Reflect check. */
1902 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1903 reflect = 1;
1904 else
1905 reflect = 0;
1906
1907 /* IBGP reflection check. */
1908 if (reflect && !samepeer_safe) {
1909 /* A route from a Client peer. */
1910 if (CHECK_FLAG(from->af_flags[afi][safi],
1911 PEER_FLAG_REFLECTOR_CLIENT)) {
1912 /* Reflect to all the Non-Client peers and also to the
1913 Client peers other than the originator. Originator
1914 check
1915 is already done. So there is noting to do. */
1916 /* no bgp client-to-client reflection check. */
892fedb6
DA
1917 if (CHECK_FLAG(bgp->flags,
1918 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1919 if (CHECK_FLAG(peer->af_flags[afi][safi],
1920 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1921 return false;
d62a17ae 1922 } else {
1923 /* A route from a Non-client peer. Reflect to all other
1924 clients. */
1925 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1926 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1927 return false;
d62a17ae 1928 }
1929 }
3f9c7369 1930
d62a17ae 1931 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1932 *attr = *piattr;
d62a17ae 1933
1934 /* If local-preference is not set. */
1935 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1936 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1937 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1938 attr->local_pref = bgp->default_local_pref;
3f9c7369 1939 }
3f9c7369 1940
d62a17ae 1941 /* If originator-id is not set and the route is to be reflected,
1942 set the originator id */
1943 if (reflect
1944 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1945 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1946 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1947 }
3f9c7369 1948
d62a17ae 1949 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1950 */
1951 if (peer->sort == BGP_PEER_EBGP
1952 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1953 if (from != bgp->peer_self && !transparent
1954 && !CHECK_FLAG(peer->af_flags[afi][safi],
1955 PEER_FLAG_MED_UNCHANGED))
1956 attr->flag &=
1957 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1958 }
3f9c7369 1959
d62a17ae 1960 /* Since the nexthop attribute can vary per peer, it is not explicitly
1961 * set
1962 * in announce check, only certain flags and length (or number of
1963 * nexthops
1964 * -- for IPv6/MP_REACH) are set here in order to guide the update
1965 * formation
1966 * code in setting the nexthop(s) on a per peer basis in
1967 * reformat_peer().
1968 * Typically, the source nexthop in the attribute is preserved but in
1969 * the
1970 * scenarios where we know it will always be overwritten, we reset the
1971 * nexthop to "0" in an attempt to achieve better Update packing. An
1972 * example of this is when a prefix from each of 2 IBGP peers needs to
1973 * be
1974 * announced to an EBGP peer (and they have the same attributes barring
1975 * their nexthop).
1976 */
1977 if (reflect)
1978 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1979
1980#define NEXTHOP_IS_V6 \
1981 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1982 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1983 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1984 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1985
1986 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1987 * if
1988 * the peer (group) is configured to receive link-local nexthop
1989 * unchanged
c728d027
DA
1990 * and it is available in the prefix OR we're not reflecting the route,
1991 * link-local nexthop address is valid and
d62a17ae 1992 * the peer (group) to whom we're going to announce is on a shared
1993 * network
1994 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1995 * By checking if nexthop LL address is valid we are sure that
1996 * we do not announce LL address as `::`.
d62a17ae 1997 */
1998 if (NEXTHOP_IS_V6) {
1999 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2000 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2001 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2002 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2003 || (!reflect
2004 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2005 && peer->shared_network
d62a17ae 2006 && (from == bgp->peer_self
2007 || peer->sort == BGP_PEER_EBGP))) {
2008 attr->mp_nexthop_len =
2009 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2010 }
3f9c7369 2011
d62a17ae 2012 /* Clear off link-local nexthop in source, whenever it is not
2013 * needed to
2014 * ensure more prefixes share the same attribute for
2015 * announcement.
2016 */
2017 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2018 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2019 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2020 }
3f9c7369 2021
d62a17ae 2022 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2023 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2024
2025 /* Route map & unsuppress-map apply. */
7f7940e6 2026 if (!skip_rmap_check
e73c112e 2027 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2028 struct bgp_path_info rmap_path = {0};
2029 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2030 struct attr dummy_attr = {0};
d62a17ae 2031
e34291b8 2032 /* Fill temp path_info */
9bcb3eef
DS
2033 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2034 pi, peer, attr);
16f7ce2b 2035
d62a17ae 2036 /* don't confuse inbound and outbound setting */
2037 RESET_FLAG(attr->rmap_change_flags);
2038
2039 /*
2040 * The route reflector is not allowed to modify the attributes
2041 * of the reflected IBGP routes unless explicitly allowed.
2042 */
2043 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2044 && !CHECK_FLAG(bgp->flags,
2045 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2046 dummy_attr = *attr;
40381db7 2047 rmap_path.attr = &dummy_attr;
d62a17ae 2048 }
3f9c7369 2049
d62a17ae 2050 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2051
4056a5f6 2052 if (bgp_path_suppressed(pi))
d62a17ae 2053 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2054 &rmap_path);
d62a17ae 2055 else
2056 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2057 &rmap_path);
d62a17ae 2058
2059 peer->rmap_type = 0;
2060
2061 if (ret == RMAP_DENYMATCH) {
778048bf 2062 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2063 zlog_debug(
2064 "%s [Update:SEND] %pFX is filtered by route-map",
2065 peer->host, p);
778048bf 2066
d62a17ae 2067 bgp_attr_flush(attr);
3dc339cd 2068 return false;
d62a17ae 2069 }
3f9c7369 2070 }
3f9c7369 2071
9dac9fc8
DA
2072 /* RFC 8212 to prevent route leaks.
2073 * This specification intends to improve this situation by requiring the
2074 * explicit configuration of both BGP Import and Export Policies for any
2075 * External BGP (EBGP) session such as customers, peers, or
2076 * confederation boundaries for all enabled address families. Through
2077 * codification of the aforementioned requirement, operators will
2078 * benefit from consistent behavior across different BGP
2079 * implementations.
2080 */
1d3fdccf 2081 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2082 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2083 return false;
9dac9fc8 2084
fb29348a
DA
2085 /* draft-ietf-idr-deprecate-as-set-confed-set
2086 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2087 * Eventually, This document (if approved) updates RFC 4271
2088 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2089 * and obsoletes RFC 6472.
2090 */
7f972cd8 2091 if (peer->bgp->reject_as_sets)
fb29348a 2092 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2093 return false;
fb29348a 2094
33d022bc
DA
2095 /* Codification of AS 0 Processing */
2096 if (aspath_check_as_zero(attr->aspath))
e2369003 2097 return false;
33d022bc 2098
637e5ba4 2099 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2100 if (peer->sort == BGP_PEER_IBGP
2101 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2102 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2103 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2104 } else {
2105 bgp_attr_add_gshut_community(attr);
2106 }
2107 }
2108
d62a17ae 2109 /* After route-map has been applied, we check to see if the nexthop to
2110 * be carried in the attribute (that is used for the announcement) can
2111 * be cleared off or not. We do this in all cases where we would be
2112 * setting the nexthop to "ourselves". For IPv6, we only need to
2113 * consider
2114 * the global nexthop here; the link-local nexthop would have been
2115 * cleared
2116 * already, and if not, it is required by the update formation code.
2117 * Also see earlier comments in this function.
2118 */
2119 /*
2120 * If route-map has performed some operation on the nexthop or the peer
2121 * configuration says to pass it unchanged, we cannot reset the nexthop
2122 * here, so only attempt to do it if these aren't true. Note that the
2123 * route-map handler itself might have cleared the nexthop, if for
2124 * example,
2125 * it is configured as 'peer-address'.
2126 */
2127 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2128 piattr->rmap_change_flags)
d62a17ae 2129 && !transparent
2130 && !CHECK_FLAG(peer->af_flags[afi][safi],
2131 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2132 /* We can reset the nexthop, if setting (or forcing) it to
2133 * 'self' */
2134 if (CHECK_FLAG(peer->af_flags[afi][safi],
2135 PEER_FLAG_NEXTHOP_SELF)
2136 || CHECK_FLAG(peer->af_flags[afi][safi],
2137 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2138 if (!reflect
2139 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2140 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2141 subgroup_announce_reset_nhop(
2142 (peer_cap_enhe(peer, afi, safi)
2143 ? AF_INET6
2144 : p->family),
2145 attr);
7b651a32 2146 nh_reset = true;
2147 }
d62a17ae 2148 } else if (peer->sort == BGP_PEER_EBGP) {
2149 /* Can also reset the nexthop if announcing to EBGP, but
2150 * only if
2151 * no peer in the subgroup is on a shared subnet.
2152 * Note: 3rd party nexthop currently implemented for
2153 * IPv4 only.
2154 */
737af885
BS
2155 if ((p->family == AF_INET) &&
2156 (!bgp_subgrp_multiaccess_check_v4(
2157 piattr->nexthop,
7b651a32 2158 subgrp, from))) {
d62a17ae 2159 subgroup_announce_reset_nhop(
2160 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2161 ? AF_INET6
2162 : p->family),
737af885 2163 attr);
7b651a32 2164 nh_reset = true;
2165 }
737af885
BS
2166
2167 if ((p->family == AF_INET6) &&
2168 (!bgp_subgrp_multiaccess_check_v6(
2169 piattr->mp_nexthop_global,
7b651a32 2170 subgrp, from))) {
737af885
BS
2171 subgroup_announce_reset_nhop(
2172 (peer_cap_enhe(peer, afi, safi)
2173 ? AF_INET6
2174 : p->family),
2175 attr);
7b651a32 2176 nh_reset = true;
2177 }
737af885
BS
2178
2179
2180
40381db7 2181 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2182 /*
2183 * This flag is used for leaked vpn-vrf routes
2184 */
2185 int family = p->family;
2186
2187 if (peer_cap_enhe(peer, afi, safi))
2188 family = AF_INET6;
2189
2190 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2191 zlog_debug(
1defdda8 2192 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2193 __func__, family2str(family));
2194 subgroup_announce_reset_nhop(family, attr);
7b651a32 2195 nh_reset = true;
d62a17ae 2196 }
63696f1d 2197 }
960035b2 2198
63696f1d 2199 /* If IPv6/MP and nexthop does not have any override and happens
2200 * to
2201 * be a link-local address, reset it so that we don't pass along
2202 * the
2203 * source's link-local IPv6 address to recipients who may not be
2204 * on
2205 * the same interface.
2206 */
2207 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2208 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2209 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2210 nh_reset = true;
2211 }
d62a17ae 2212 }
3f9c7369 2213
7b651a32 2214 /*
2215 * When the next hop is set to ourselves, if all multipaths have
2216 * link-bandwidth announce the cumulative bandwidth as that makes
2217 * the most sense. However, don't modify if the link-bandwidth has
2218 * been explicitly set by user policy.
2219 */
2220 if (nh_reset &&
f7e1c681 2221 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2222 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2223 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2224 attr->ecommunity = ecommunity_replace_linkbw(
2225 bgp->as, attr->ecommunity, cum_bw);
2226
3dc339cd 2227 return true;
3f9c7369
DS
2228}
2229
f009ff26 2230static int bgp_route_select_timer_expire(struct thread *thread)
2231{
2232 struct afi_safi_info *info;
2233 afi_t afi;
2234 safi_t safi;
2235 struct bgp *bgp;
2236
2237 info = THREAD_ARG(thread);
2238 afi = info->afi;
2239 safi = info->safi;
2240 bgp = info->bgp;
2241
2242 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2243 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2244 safi);
f009ff26 2245
2246 bgp->gr_info[afi][safi].t_route_select = NULL;
2247
2248 XFREE(MTYPE_TMP, info);
2249
2250 /* Best path selection */
2251 return bgp_best_path_select_defer(bgp, afi, safi);
2252}
2253
9bcb3eef 2254void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2255 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2256 struct bgp_path_info_pair *result, afi_t afi,
2257 safi_t safi)
2258{
2259 struct bgp_path_info *new_select;
2260 struct bgp_path_info *old_select;
40381db7
DS
2261 struct bgp_path_info *pi;
2262 struct bgp_path_info *pi1;
2263 struct bgp_path_info *pi2;
2264 struct bgp_path_info *nextpi = NULL;
d62a17ae 2265 int paths_eq, do_mpath, debug;
2266 struct list mp_list;
2267 char pfx_buf[PREFIX2STR_BUFFER];
2268 char path_buf[PATH_ADDPATH_STR_BUFFER];
2269
2270 bgp_mp_list_init(&mp_list);
2271 do_mpath =
2272 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2273
9bcb3eef 2274 debug = bgp_debug_bestpath(dest);
d62a17ae 2275
2276 if (debug)
9bcb3eef 2277 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2278
9bcb3eef 2279 dest->reason = bgp_path_selection_none;
d62a17ae 2280 /* bgp deterministic-med */
2281 new_select = NULL;
892fedb6 2282 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2283
1defdda8 2284 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2285 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2286 pi1 = pi1->next)
9bcb3eef 2287 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2288 BGP_PATH_DMED_SELECTED);
d62a17ae 2289
9bcb3eef 2290 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2291 pi1 = pi1->next) {
40381db7 2292 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2293 continue;
40381db7 2294 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2295 continue;
ea8b2282 2296 if (pi1->peer != bgp->peer_self)
40381db7 2297 if (pi1->peer->status != Established)
d62a17ae 2298 continue;
2299
40381db7
DS
2300 new_select = pi1;
2301 if (pi1->next) {
2302 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2303 if (CHECK_FLAG(pi2->flags,
1defdda8 2304 BGP_PATH_DMED_CHECK))
d62a17ae 2305 continue;
40381db7 2306 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2307 continue;
ea8b2282 2308 if (pi2->peer != bgp->peer_self
d62a17ae 2309 && !CHECK_FLAG(
ea8b2282
DS
2310 pi2->peer->sflags,
2311 PEER_STATUS_NSF_WAIT))
40381db7 2312 if (pi2->peer->status
d62a17ae 2313 != Established)
2314 continue;
2315
121e245d
DS
2316 if (!aspath_cmp_left(pi1->attr->aspath,
2317 pi2->attr->aspath)
2318 && !aspath_cmp_left_confed(
40381db7 2319 pi1->attr->aspath,
121e245d
DS
2320 pi2->attr->aspath))
2321 continue;
d62a17ae 2322
121e245d
DS
2323 if (bgp_path_info_cmp(
2324 bgp, pi2, new_select,
2325 &paths_eq, mpath_cfg, debug,
fdf81fa0 2326 pfx_buf, afi, safi,
9bcb3eef 2327 &dest->reason)) {
121e245d 2328 bgp_path_info_unset_flag(
9bcb3eef 2329 dest, new_select,
121e245d
DS
2330 BGP_PATH_DMED_SELECTED);
2331 new_select = pi2;
d62a17ae 2332 }
121e245d
DS
2333
2334 bgp_path_info_set_flag(
9bcb3eef 2335 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2336 }
2337 }
9bcb3eef 2338 bgp_path_info_set_flag(dest, new_select,
18ee8310 2339 BGP_PATH_DMED_CHECK);
9bcb3eef 2340 bgp_path_info_set_flag(dest, new_select,
18ee8310 2341 BGP_PATH_DMED_SELECTED);
d62a17ae 2342
2343 if (debug) {
18ee8310
DS
2344 bgp_path_info_path_with_addpath_rx_str(
2345 new_select, path_buf);
8228a9a7
DS
2346 zlog_debug(
2347 "%pBD: %s is the bestpath from AS %u",
2348 dest, path_buf,
2349 aspath_get_first_as(
2350 new_select->attr->aspath));
d62a17ae 2351 }
2352 }
2353 }
96450faf 2354
d62a17ae 2355 /* Check old selected route and new selected route. */
2356 old_select = NULL;
2357 new_select = NULL;
9bcb3eef 2358 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2359 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2360 enum bgp_path_selection_reason reason;
2361
40381db7
DS
2362 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2363 old_select = pi;
d62a17ae 2364
40381db7 2365 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2366 /* reap REMOVED routes, if needs be
2367 * selected route must stay for a while longer though
2368 */
40381db7
DS
2369 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2370 && (pi != old_select))
9bcb3eef 2371 bgp_path_info_reap(dest, pi);
d62a17ae 2372
ddb5b488 2373 if (debug)
40381db7
DS
2374 zlog_debug("%s: pi %p in holddown", __func__,
2375 pi);
ddb5b488 2376
d62a17ae 2377 continue;
2378 }
96450faf 2379
40381db7
DS
2380 if (pi->peer && pi->peer != bgp->peer_self
2381 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2382 if (pi->peer->status != Established) {
ddb5b488
PZ
2383
2384 if (debug)
2385 zlog_debug(
40381db7
DS
2386 "%s: pi %p non self peer %s not estab state",
2387 __func__, pi, pi->peer->host);
ddb5b488 2388
d62a17ae 2389 continue;
ddb5b488 2390 }
9fbdd100 2391
892fedb6 2392 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2393 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2394 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2395 if (debug)
40381db7 2396 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2397 continue;
2398 }
9fbdd100 2399
9bcb3eef 2400 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2401
9bcb3eef 2402 reason = dest->reason;
40381db7 2403 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2404 debug, pfx_buf, afi, safi,
2405 &dest->reason)) {
19ea4cec
DS
2406 if (new_select == NULL &&
2407 reason != bgp_path_selection_none)
9bcb3eef 2408 dest->reason = reason;
40381db7 2409 new_select = pi;
d62a17ae 2410 }
2411 }
718e3744 2412
d62a17ae 2413 /* Now that we know which path is the bestpath see if any of the other
2414 * paths
2415 * qualify as multipaths
2416 */
2417 if (debug) {
2418 if (new_select)
18ee8310
DS
2419 bgp_path_info_path_with_addpath_rx_str(new_select,
2420 path_buf);
d62a17ae 2421 else
772270f3 2422 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2423 zlog_debug(
8228a9a7
DS
2424 "%pBD: After path selection, newbest is %s oldbest was %s",
2425 dest, path_buf,
d62a17ae 2426 old_select ? old_select->peer->host : "NONE");
96450faf 2427 }
9fbdd100 2428
d62a17ae 2429 if (do_mpath && new_select) {
9bcb3eef 2430 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2431 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2432
2433 if (debug)
18ee8310 2434 bgp_path_info_path_with_addpath_rx_str(
40381db7 2435 pi, path_buf);
d62a17ae 2436
40381db7 2437 if (pi == new_select) {
d62a17ae 2438 if (debug)
2439 zlog_debug(
8228a9a7
DS
2440 "%pBD: %s is the bestpath, add to the multipath list",
2441 dest, path_buf);
40381db7 2442 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2443 continue;
2444 }
2445
40381db7 2446 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2447 continue;
2448
40381db7
DS
2449 if (pi->peer && pi->peer != bgp->peer_self
2450 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2451 PEER_STATUS_NSF_WAIT))
40381db7 2452 if (pi->peer->status != Established)
d62a17ae 2453 continue;
2454
40381db7 2455 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2456 if (debug)
2457 zlog_debug(
8228a9a7
DS
2458 "%pBD: %s has the same nexthop as the bestpath, skip it",
2459 dest, path_buf);
d62a17ae 2460 continue;
2461 }
2462
40381db7 2463 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2464 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2465 &dest->reason);
d62a17ae 2466
2467 if (paths_eq) {
2468 if (debug)
2469 zlog_debug(
8228a9a7
DS
2470 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2471 dest, path_buf);
40381db7 2472 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2473 }
2474 }
2475 }
fee0f4c6 2476
9bcb3eef 2477 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2478 mpath_cfg);
2479 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2480 bgp_mp_list_clear(&mp_list);
96450faf 2481
9bcb3eef 2482 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2483
d62a17ae 2484 result->old = old_select;
2485 result->new = new_select;
96450faf 2486
d62a17ae 2487 return;
fee0f4c6 2488}
2489
3f9c7369
DS
2490/*
2491 * A new route/change in bestpath of an existing route. Evaluate the path
2492 * for advertisement to the subgroup.
2493 */
3dc339cd
DA
2494void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2495 struct bgp_path_info *selected,
9bcb3eef 2496 struct bgp_dest *dest,
3dc339cd 2497 uint32_t addpath_tx_id)
d62a17ae 2498{
b54892e0 2499 const struct prefix *p;
d62a17ae 2500 struct peer *onlypeer;
2501 struct attr attr;
2502 afi_t afi;
2503 safi_t safi;
a77e2f4b
S
2504 struct bgp *bgp;
2505 bool advertise;
adbac85e 2506
9bcb3eef 2507 p = bgp_dest_get_prefix(dest);
d62a17ae 2508 afi = SUBGRP_AFI(subgrp);
2509 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2510 bgp = SUBGRP_INST(subgrp);
d62a17ae 2511 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2512 : NULL);
2513
2dbe669b
DA
2514 if (BGP_DEBUG(update, UPDATE_OUT))
2515 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2516
d62a17ae 2517 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2518 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2519 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2520 return;
d62a17ae 2521
2522 memset(&attr, 0, sizeof(struct attr));
2523 /* It's initialized in bgp_announce_check() */
2524
a77e2f4b
S
2525 /* Announcement to the subgroup. If the route is filtered withdraw it.
2526 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2527 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2528 * route
d62a17ae 2529 */
a77e2f4b
S
2530 advertise = bgp_check_advertise(bgp, dest);
2531
d62a17ae 2532 if (selected) {
7f7940e6 2533 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2534 false)) {
2535 /* Route is selected, if the route is already installed
2536 * in FIB, then it is advertised
2537 */
2538 if (advertise)
2539 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2540 selected);
2541 } else
9bcb3eef 2542 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2543 addpath_tx_id);
d62a17ae 2544 }
2545
2546 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2547 else {
9bcb3eef 2548 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2549 }
200df115 2550}
fee0f4c6 2551
3064bf43 2552/*
e1072051 2553 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2554 * This is called at the end of route processing.
3064bf43 2555 */
9bcb3eef 2556void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2557{
40381db7 2558 struct bgp_path_info *pi;
3064bf43 2559
9bcb3eef 2560 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2561 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2562 continue;
40381db7
DS
2563 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2564 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2565 }
3064bf43 2566}
2567
2568/*
2569 * Has the route changed from the RIB's perspective? This is invoked only
2570 * if the route selection returns the same best route as earlier - to
2571 * determine if we need to update zebra or not.
2572 */
9bcb3eef 2573bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2574{
4b7e6066 2575 struct bgp_path_info *mpinfo;
d62a17ae 2576
2bb9eff4
DS
2577 /* If this is multipath, check all selected paths for any nexthop
2578 * change or attribute change. Some attribute changes (e.g., community)
2579 * aren't of relevance to the RIB, but we'll update zebra to ensure
2580 * we handle the case of BGP nexthop change. This is the behavior
2581 * when the best path has an attribute change anyway.
d62a17ae 2582 */
1defdda8 2583 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2584 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2585 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2586 return true;
d62a17ae 2587
2bb9eff4
DS
2588 /*
2589 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2590 */
18ee8310
DS
2591 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2592 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2593 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2594 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2595 return true;
d62a17ae 2596 }
3064bf43 2597
d62a17ae 2598 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2599 return false;
3064bf43 2600}
2601
d62a17ae 2602struct bgp_process_queue {
2603 struct bgp *bgp;
9bcb3eef 2604 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2605#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2606 unsigned int flags;
2607 unsigned int queued;
200df115 2608};
2609
3b0c17e1 2610static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2611 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2612 struct bgp_path_info *new_select,
2613 struct bgp_path_info *old_select)
2614{
9bcb3eef 2615 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2616
2617 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2618 return;
2619
2620 if (advertise_type5_routes(bgp, afi) && new_select
2621 && is_route_injectable_into_evpn(new_select)) {
2622
2623 /* apply the route-map */
2624 if (bgp->adv_cmd_rmap[afi][safi].map) {
2625 route_map_result_t ret;
2626 struct bgp_path_info rmap_path;
2627 struct bgp_path_info_extra rmap_path_extra;
2628 struct attr dummy_attr;
2629
2630 dummy_attr = *new_select->attr;
2631
2632 /* Fill temp path_info */
9bcb3eef 2633 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2634 new_select, new_select->peer,
2635 &dummy_attr);
2636
2637 RESET_FLAG(dummy_attr.rmap_change_flags);
2638
2639 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2640 p, &rmap_path);
3b0c17e1 2641
2642 if (ret == RMAP_DENYMATCH) {
2643 bgp_attr_flush(&dummy_attr);
2644 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2645 safi);
2646 } else
2647 bgp_evpn_advertise_type5_route(
2648 bgp, p, &dummy_attr, afi, safi);
2649 } else {
2650 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2651 afi, safi);
2652 }
2653 } else if (advertise_type5_routes(bgp, afi) && old_select
2654 && is_route_injectable_into_evpn(old_select))
2655 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2656}
2657
3103e8d2
DS
2658/*
2659 * old_select = The old best path
2660 * new_select = the new best path
2661 *
2662 * if (!old_select && new_select)
2663 * We are sending new information on.
2664 *
2665 * if (old_select && new_select) {
2666 * if (new_select != old_select)
2667 * We have a new best path send a change
2668 * else
2669 * We've received a update with new attributes that needs
2670 * to be passed on.
2671 * }
2672 *
2673 * if (old_select && !new_select)
2674 * We have no eligible route that we can announce or the rn
2675 * is being removed.
2676 */
9bcb3eef 2677static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2678 afi_t afi, safi_t safi)
d62a17ae 2679{
4b7e6066
DS
2680 struct bgp_path_info *new_select;
2681 struct bgp_path_info *old_select;
2682 struct bgp_path_info_pair old_and_new;
ddb5b488 2683 int debug = 0;
d62a17ae 2684
892fedb6 2685 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2686 if (dest)
2687 debug = bgp_debug_bestpath(dest);
b54892e0 2688 if (debug)
f4c713ae 2689 zlog_debug(
56ca3b5b 2690 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2691 __func__, dest);
f4c713ae
LB
2692 return;
2693 }
d62a17ae 2694 /* Is it end of initial update? (after startup) */
9bcb3eef 2695 if (!dest) {
d62a17ae 2696 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2697 sizeof(bgp->update_delay_zebra_resume_time));
2698
2699 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2700 FOREACH_AFI_SAFI (afi, safi) {
2701 if (bgp_fibupd_safi(safi))
2702 bgp_zebra_announce_table(bgp, afi, safi);
2703 }
d62a17ae 2704 bgp->main_peers_update_hold = 0;
2705
2706 bgp_start_routeadv(bgp);
aac24838 2707 return;
d62a17ae 2708 }
cb1faec9 2709
9bcb3eef 2710 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2711
9bcb3eef 2712 debug = bgp_debug_bestpath(dest);
b54892e0 2713 if (debug)
56ca3b5b 2714 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2715 afi2str(afi), safi2str(safi));
ddb5b488 2716
f009ff26 2717 /* The best path calculation for the route is deferred if
2718 * BGP_NODE_SELECT_DEFER is set
2719 */
9bcb3eef 2720 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2721 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2722 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2723 return;
2724 }
2725
d62a17ae 2726 /* Best path selection. */
9bcb3eef 2727 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2728 afi, safi);
2729 old_select = old_and_new.old;
2730 new_select = old_and_new.new;
2731
2732 /* Do we need to allocate or free labels?
2733 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2734 * necessary to do this upon changes to best path. Exceptions:
2735 * - label index has changed -> recalculate resulting label
2736 * - path_info sub_type changed -> switch to/from implicit-null
2737 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2738 */
318cac96 2739 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2740 if (new_select) {
2741 if (!old_select
2742 || bgp_label_index_differs(new_select, old_select)
57592a53 2743 || new_select->sub_type != old_select->sub_type
9bcb3eef 2744 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2745 /* Enforced penultimate hop popping:
2746 * implicit-null for local routes, aggregate
2747 * and redistributed routes
2748 */
d62a17ae 2749 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2750 || new_select->sub_type
2751 == BGP_ROUTE_AGGREGATE
2752 || new_select->sub_type
2753 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2754 if (CHECK_FLAG(
9bcb3eef 2755 dest->flags,
992dd67e
PR
2756 BGP_NODE_REGISTERED_FOR_LABEL)
2757 || CHECK_FLAG(
2758 dest->flags,
2759 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2760 bgp_unregister_for_label(dest);
70e98a7f 2761 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2762 &dest->local_label);
2763 bgp_set_valid_label(&dest->local_label);
d62a17ae 2764 } else
9bcb3eef
DS
2765 bgp_register_for_label(dest,
2766 new_select);
d62a17ae 2767 }
9bcb3eef 2768 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2769 BGP_NODE_REGISTERED_FOR_LABEL)
2770 || CHECK_FLAG(dest->flags,
2771 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2772 bgp_unregister_for_label(dest);
318cac96 2773 }
992dd67e
PR
2774 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2775 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2776 bgp_unregister_for_label(dest);
d62a17ae 2777 }
cd1964ff 2778
b54892e0 2779 if (debug)
ddb5b488 2780 zlog_debug(
56ca3b5b 2781 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2782 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2783 old_select, new_select);
ddb5b488 2784
d62a17ae 2785 /* If best route remains the same and this is not due to user-initiated
2786 * clear, see exactly what needs to be done.
2787 */
d62a17ae 2788 if (old_select && old_select == new_select
9bcb3eef 2789 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2790 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2791 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2792 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2793#ifdef ENABLE_BGP_VNC
d62a17ae 2794 vnc_import_bgp_add_route(bgp, p, old_select);
2795 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2796#endif
bb744275 2797 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2798 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2799
2800 if (new_select->type == ZEBRA_ROUTE_BGP
2801 && (new_select->sub_type == BGP_ROUTE_NORMAL
2802 || new_select->sub_type
2803 == BGP_ROUTE_IMPORTED))
2804
9bcb3eef 2805 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2806 bgp, afi, safi);
2807 }
d62a17ae 2808 }
d62a17ae 2809
2810 /* If there is a change of interest to peers, reannounce the
2811 * route. */
1defdda8 2812 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2813 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2814 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2815 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2816
2817 /* unicast routes must also be annouced to
2818 * labeled-unicast update-groups */
2819 if (safi == SAFI_UNICAST)
2820 group_announce_route(bgp, afi,
9bcb3eef 2821 SAFI_LABELED_UNICAST, dest,
d62a17ae 2822 new_select);
2823
1defdda8 2824 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2825 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2826 }
fee0f4c6 2827
3b0c17e1 2828 /* advertise/withdraw type-5 routes */
2829 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2830 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2831 bgp_process_evpn_route_injection(
9bcb3eef 2832 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2833
b1875e65 2834 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2835 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2836 bgp_zebra_clear_route_change_flags(dest);
2837 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2838 return;
d62a17ae 2839 }
8ad7271d 2840
d62a17ae 2841 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2842 */
9bcb3eef 2843 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2844
2845 /* bestpath has changed; bump version */
2846 if (old_select || new_select) {
9bcb3eef 2847 bgp_bump_version(dest);
d62a17ae 2848
2849 if (!bgp->t_rmap_def_originate_eval) {
2850 bgp_lock(bgp);
2851 thread_add_timer(
2852 bm->master,
2853 update_group_refresh_default_originate_route_map,
2854 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2855 &bgp->t_rmap_def_originate_eval);
2856 }
2857 }
3f9c7369 2858
d62a17ae 2859 if (old_select)
9bcb3eef 2860 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2861 if (new_select) {
ddb5b488
PZ
2862 if (debug)
2863 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2864 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2865 bgp_path_info_unset_flag(dest, new_select,
2866 BGP_PATH_ATTR_CHANGED);
1defdda8 2867 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2868 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2869 }
338b3424 2870
49e5a4a0 2871#ifdef ENABLE_BGP_VNC
d62a17ae 2872 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2873 if (old_select != new_select) {
2874 if (old_select) {
2875 vnc_import_bgp_exterior_del_route(bgp, p,
2876 old_select);
2877 vnc_import_bgp_del_route(bgp, p, old_select);
2878 }
2879 if (new_select) {
2880 vnc_import_bgp_exterior_add_route(bgp, p,
2881 new_select);
2882 vnc_import_bgp_add_route(bgp, p, new_select);
2883 }
2884 }
2885 }
65efcfce
LB
2886#endif
2887
9bcb3eef 2888 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2889
2890 /* unicast routes must also be annouced to labeled-unicast update-groups
2891 */
2892 if (safi == SAFI_UNICAST)
9bcb3eef 2893 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2894 new_select);
2895
2896 /* FIB update. */
2897 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2898 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2899 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2900 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2901 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2902 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2903
2904 /* if this is an evpn imported type-5 prefix,
2905 * we need to withdraw the route first to clear
2906 * the nh neigh and the RMAC entry.
2907 */
2908 if (old_select &&
2909 is_route_parent_evpn(old_select))
2910 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2911
9bcb3eef 2912 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2913 } else {
d62a17ae 2914 /* Withdraw the route from the kernel. */
2915 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2916 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2917 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2918 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2919
568e10ca 2920 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2921 }
718e3744 2922 }
3064bf43 2923
9bcb3eef 2924 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2925 old_select);
5424b7ba 2926
d62a17ae 2927 /* Clear any route change flags. */
9bcb3eef 2928 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2929
18ee8310 2930 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2931 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2932 bgp_path_info_reap(dest, old_select);
d62a17ae 2933
9bcb3eef 2934 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2935 return;
718e3744 2936}
2937
f009ff26 2938/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2939int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2940{
9bcb3eef 2941 struct bgp_dest *dest;
f009ff26 2942 int cnt = 0;
2943 struct afi_safi_info *thread_info;
f009ff26 2944
56c226e7
DS
2945 if (bgp->gr_info[afi][safi].t_route_select) {
2946 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2947
2948 thread_info = THREAD_ARG(t);
2949 XFREE(MTYPE_TMP, thread_info);
f009ff26 2950 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2951 }
f009ff26 2952
2953 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2954 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2955 get_afi_safi_str(afi, safi, false),
26742171 2956 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2957 }
2958
2959 /* Process the route list */
6338d242
DS
2960 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2961 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2962 dest = bgp_route_next(dest)) {
2963 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2964 continue;
2965
2966 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2967 bgp->gr_info[afi][safi].gr_deferred--;
2968 bgp_process_main_one(bgp, dest, afi, safi);
2969 cnt++;
2970 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2971 bgp_dest_unlock_node(dest);
2972 break;
f009ff26 2973 }
f009ff26 2974 }
2975
9e3b51a7 2976 /* Send EOR message when all routes are processed */
6338d242 2977 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2978 bgp_send_delayed_eor(bgp);
8c48b3b6 2979 /* Send route processing complete message to RIB */
2980 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2981 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2982 return 0;
9e3b51a7 2983 }
f009ff26 2984
2985 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2986
2987 thread_info->afi = afi;
2988 thread_info->safi = safi;
2989 thread_info->bgp = bgp;
2990
2991 /* If there are more routes to be processed, start the
2992 * selection timer
2993 */
2994 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2995 BGP_ROUTE_SELECT_DELAY,
2996 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2997 return 0;
2998}
2999
aac24838 3000static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3001{
aac24838
JB
3002 struct bgp_process_queue *pqnode = data;
3003 struct bgp *bgp = pqnode->bgp;
d62a17ae 3004 struct bgp_table *table;
9bcb3eef 3005 struct bgp_dest *dest;
aac24838
JB
3006
3007 /* eoiu marker */
3008 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3009 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3010 /* should always have dedicated wq call */
3011 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3012 return WQ_SUCCESS;
3013 }
3014
ac021f40 3015 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3016 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3017 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3018 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3019 table = bgp_dest_table(dest);
3020 /* note, new DESTs may be added as part of processing */
3021 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3022
9bcb3eef 3023 bgp_dest_unlock_node(dest);
d62a17ae 3024 bgp_table_unlock(table);
3025 }
aac24838
JB
3026
3027 return WQ_SUCCESS;
3028}
3029
3030static void bgp_processq_del(struct work_queue *wq, void *data)
3031{
3032 struct bgp_process_queue *pqnode = data;
3033
3034 bgp_unlock(pqnode->bgp);
3035
3036 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3037}
3038
b6c386bb 3039void bgp_process_queue_init(struct bgp *bgp)
200df115 3040{
b6c386bb
DS
3041 if (!bgp->process_queue) {
3042 char name[BUFSIZ];
3043
3044 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3045 bgp->process_queue = work_queue_new(bm->master, name);
3046 }
3047
3048 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3049 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3050 bgp->process_queue->spec.max_retries = 0;
3051 bgp->process_queue->spec.hold = 50;
d62a17ae 3052 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3053 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3054}
3055
cfe8d15a 3056static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3057{
3058 struct bgp_process_queue *pqnode;
3059
a4d82a8a
PZ
3060 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3061 sizeof(struct bgp_process_queue));
aac24838
JB
3062
3063 /* unlocked in bgp_processq_del */
3064 pqnode->bgp = bgp_lock(bgp);
3065 STAILQ_INIT(&pqnode->pqueue);
3066
aac24838
JB
3067 return pqnode;
3068}
3069
9bcb3eef 3070void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3071{
aac24838 3072#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3073 struct work_queue *wq = bgp->process_queue;
d62a17ae 3074 struct bgp_process_queue *pqnode;
cfe8d15a 3075 int pqnode_reuse = 0;
495f0b13 3076
d62a17ae 3077 /* already scheduled for processing? */
9bcb3eef 3078 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3079 return;
2e02b9b2 3080
f009ff26 3081 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3082 * the workqueue
3083 */
9bcb3eef 3084 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3085 if (BGP_DEBUG(update, UPDATE_OUT))
3086 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3087 dest);
f009ff26 3088 return;
3089 }
3090
aac24838 3091 if (wq == NULL)
d62a17ae 3092 return;
3093
aac24838 3094 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3095 limit only if is from the same BGP view and it's not an EOIU marker
3096 */
aac24838
JB
3097 if (work_queue_item_count(wq)) {
3098 struct work_queue_item *item = work_queue_last_item(wq);
3099 pqnode = item->data;
228da428 3100
a4d82a8a
PZ
3101 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3102 || pqnode->bgp != bgp
3103 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3104 pqnode = bgp_processq_alloc(bgp);
3105 else
3106 pqnode_reuse = 1;
aac24838 3107 } else
cfe8d15a 3108 pqnode = bgp_processq_alloc(bgp);
aac24838 3109 /* all unlocked in bgp_process_wq */
9bcb3eef 3110 bgp_table_lock(bgp_dest_table(dest));
aac24838 3111
9bcb3eef
DS
3112 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3113 bgp_dest_lock_node(dest);
aac24838 3114
60466a63 3115 /* can't be enqueued twice */
9bcb3eef
DS
3116 assert(STAILQ_NEXT(dest, pq) == NULL);
3117 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3118 pqnode->queued++;
3119
cfe8d15a
LB
3120 if (!pqnode_reuse)
3121 work_queue_add(wq, pqnode);
3122
d62a17ae 3123 return;
fee0f4c6 3124}
0a486e5f 3125
d62a17ae 3126void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3127{
d62a17ae 3128 struct bgp_process_queue *pqnode;
cb1faec9 3129
b6c386bb 3130 if (bgp->process_queue == NULL)
d62a17ae 3131 return;
2e02b9b2 3132
cfe8d15a 3133 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3134
aac24838 3135 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3136 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3137}
3138
d62a17ae 3139static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3140{
d62a17ae 3141 struct peer *peer;
0a486e5f 3142
d62a17ae 3143 peer = THREAD_ARG(thread);
3144 peer->t_pmax_restart = NULL;
0a486e5f 3145
d62a17ae 3146 if (bgp_debug_neighbor_events(peer))
3147 zlog_debug(
3148 "%s Maximum-prefix restart timer expired, restore peering",
3149 peer->host);
0a486e5f 3150
a9bafa95 3151 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3152 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3153
d62a17ae 3154 return 0;
0a486e5f 3155}
3156
9cbd06e0
DA
3157static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3158 safi_t safi)
3159{
3160 uint32_t count = 0;
f41b0459 3161 bool filtered = false;
9cbd06e0
DA
3162 struct bgp_dest *dest;
3163 struct bgp_adj_in *ain;
40bb2ccf 3164 struct attr attr = {};
9cbd06e0
DA
3165 struct bgp_table *table = peer->bgp->rib[afi][safi];
3166
3167 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3168 for (ain = dest->adj_in; ain; ain = ain->next) {
3169 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3170
3171 attr = *ain->attr;
9cbd06e0
DA
3172
3173 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3174 == FILTER_DENY)
f41b0459
DA
3175 filtered = true;
3176
3177 if (bgp_input_modifier(
3178 peer, rn_p, &attr, afi, safi,
3179 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3180 NULL, 0, NULL)
3181 == RMAP_DENY)
3182 filtered = true;
3183
3184 if (filtered)
9cbd06e0 3185 count++;
f41b0459
DA
3186
3187 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3188 }
3189 }
3190
3191 return count;
3192}
3193
3dc339cd
DA
3194bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3195 int always)
718e3744 3196{
d62a17ae 3197 iana_afi_t pkt_afi;
5c525538 3198 iana_safi_t pkt_safi;
9cbd06e0
DA
3199 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3200 PEER_FLAG_MAX_PREFIX_FORCE))
3201 ? bgp_filtered_routes_count(peer, afi, safi)
3202 + peer->pcount[afi][safi]
3203 : peer->pcount[afi][safi];
9cabb64b 3204
d62a17ae 3205 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3206 return false;
e0701b79 3207
9cbd06e0 3208 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3209 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3210 PEER_STATUS_PREFIX_LIMIT)
3211 && !always)
3dc339cd 3212 return false;
e0701b79 3213
d62a17ae 3214 zlog_info(
6cde4b45 3215 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3216 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3217 peer->pmax[afi][safi]);
d62a17ae 3218 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3219
3220 if (CHECK_FLAG(peer->af_flags[afi][safi],
3221 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3222 return false;
d62a17ae 3223
3224 /* Convert AFI, SAFI to values for packet. */
3225 pkt_afi = afi_int2iana(afi);
3226 pkt_safi = safi_int2iana(safi);
3227 {
d7c0a89a 3228 uint8_t ndata[7];
d62a17ae 3229
3230 ndata[0] = (pkt_afi >> 8);
3231 ndata[1] = pkt_afi;
3232 ndata[2] = pkt_safi;
3233 ndata[3] = (peer->pmax[afi][safi] >> 24);
3234 ndata[4] = (peer->pmax[afi][safi] >> 16);
3235 ndata[5] = (peer->pmax[afi][safi] >> 8);
3236 ndata[6] = (peer->pmax[afi][safi]);
3237
3238 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3239 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3240 BGP_NOTIFY_CEASE_MAX_PREFIX,
3241 ndata, 7);
3242 }
3243
3244 /* Dynamic peers will just close their connection. */
3245 if (peer_dynamic_neighbor(peer))
3dc339cd 3246 return true;
d62a17ae 3247
3248 /* restart timer start */
3249 if (peer->pmax_restart[afi][safi]) {
3250 peer->v_pmax_restart =
3251 peer->pmax_restart[afi][safi] * 60;
3252
3253 if (bgp_debug_neighbor_events(peer))
3254 zlog_debug(
3255 "%s Maximum-prefix restart timer started for %d secs",
3256 peer->host, peer->v_pmax_restart);
3257
3258 BGP_TIMER_ON(peer->t_pmax_restart,
3259 bgp_maximum_prefix_restart_timer,
3260 peer->v_pmax_restart);
3261 }
3262
3dc339cd 3263 return true;
d62a17ae 3264 } else
3265 UNSET_FLAG(peer->af_sflags[afi][safi],
3266 PEER_STATUS_PREFIX_LIMIT);
3267
b1823b69
DS
3268 if (pcount
3269 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3270 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3271 PEER_STATUS_PREFIX_THRESHOLD)
3272 && !always)
3dc339cd 3273 return false;
d62a17ae 3274
3275 zlog_info(
6cde4b45 3276 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3277 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3278 peer->pmax[afi][safi]);
d62a17ae 3279 SET_FLAG(peer->af_sflags[afi][safi],
3280 PEER_STATUS_PREFIX_THRESHOLD);
3281 } else
3282 UNSET_FLAG(peer->af_sflags[afi][safi],
3283 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3284 return false;
718e3744 3285}
3286
b40d939b 3287/* Unconditionally remove the route from the RIB, without taking
3288 * damping into consideration (eg, because the session went down)
3289 */
9bcb3eef 3290void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3291 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3292{
f009ff26 3293
3294 struct bgp *bgp = NULL;
3295 bool delete_route = false;
3296
9bcb3eef
DS
3297 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3298 safi);
d62a17ae 3299
f009ff26 3300 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3301 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3302
f009ff26 3303 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3304 * flag
3305 */
3306 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3307 delete_route = true;
9bcb3eef 3308 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3309 delete_route = true;
f009ff26 3310 if (delete_route) {
9bcb3eef
DS
3311 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3312 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3313 bgp = pi->peer->bgp;
26742171 3314 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3315 }
3316 }
3317 }
4a11bf2c 3318
9bcb3eef
DS
3319 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3320 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3321}
3322
9bcb3eef 3323static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3324 struct peer *peer, afi_t afi, safi_t safi,
3325 struct prefix_rd *prd)
3326{
9bcb3eef 3327 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3328
d62a17ae 3329 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3330 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3331 */
40ec3340
DS
3332 if (peer->sort == BGP_PEER_EBGP) {
3333 if (get_active_bdc_from_pi(pi, afi, safi)) {
3334 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3335 == BGP_DAMP_SUPPRESSED) {
3336 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3337 safi);
3338 return;
3339 }
d62a17ae 3340 }
40ec3340 3341 }
d62a17ae 3342
49e5a4a0 3343#ifdef ENABLE_BGP_VNC
d62a17ae 3344 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3345 struct bgp_dest *pdest = NULL;
d62a17ae 3346 struct bgp_table *table = NULL;
3347
9bcb3eef
DS
3348 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3349 (struct prefix *)prd);
3350 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3351 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3352
3353 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3354 peer->bgp, prd, table, p, pi);
d62a17ae 3355 }
9bcb3eef 3356 bgp_dest_unlock_node(pdest);
d62a17ae 3357 }
3358 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3359 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3360
b54892e0
DS
3361 vnc_import_bgp_del_route(peer->bgp, p, pi);
3362 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3363 }
65efcfce 3364 }
d62a17ae 3365#endif
128ea8ab 3366
d62a17ae 3367 /* If this is an EVPN route, process for un-import. */
3368 if (safi == SAFI_EVPN)
b54892e0 3369 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3370
9bcb3eef 3371 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3372}
3373
4b7e6066
DS
3374struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3375 struct peer *peer, struct attr *attr,
9bcb3eef 3376 struct bgp_dest *dest)
fb018d25 3377{
4b7e6066 3378 struct bgp_path_info *new;
fb018d25 3379
d62a17ae 3380 /* Make new BGP info. */
4b7e6066 3381 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3382 new->type = type;
3383 new->instance = instance;
3384 new->sub_type = sub_type;
3385 new->peer = peer;
3386 new->attr = attr;
3387 new->uptime = bgp_clock();
9bcb3eef 3388 new->net = dest;
d62a17ae 3389 return new;
fb018d25
DS
3390}
3391
d62a17ae 3392static void overlay_index_update(struct attr *attr,
d62a17ae 3393 union gw_addr *gw_ip)
684a7227 3394{
d62a17ae 3395 if (!attr)
3396 return;
d62a17ae 3397 if (gw_ip == NULL) {
6c924775
DS
3398 struct bgp_route_evpn eo;
3399
3400 memset(&eo, 0, sizeof(eo));
3401 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3402 } else {
6c924775
DS
3403 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3404
3405 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3406 }
684a7227
PG
3407}
3408
40381db7 3409static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3410 union gw_addr *gw_ip)
3411{
6c924775
DS
3412 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3413 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3414 union {
0a50c248 3415 esi_t esi;
11ebf4ed
DS
3416 union gw_addr ip;
3417 } temp;
d62a17ae 3418
3419 if (afi != AFI_L2VPN)
3420 return true;
11ebf4ed 3421
6c924775 3422 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3423
3424 if (gw_ip == NULL) {
3425 memset(&temp, 0, sizeof(temp));
40381db7 3426 path_gw_ip_remote = &temp.ip;
11ebf4ed 3427 } else
40381db7 3428 path_gw_ip_remote = gw_ip;
11ebf4ed 3429
6c924775 3430 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3431}
3432
c265ee22 3433/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3434bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3435 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3436 struct bgp_dest *dest)
d62a17ae 3437{
2dbe3fa9 3438 bool ret = false;
b099a5c8
DA
3439 bool is_bgp_static_route =
3440 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3441 : false;
d62a17ae 3442
e8442016
DS
3443 /*
3444 * Only validated for unicast and multicast currently.
3445 * Also valid for EVPN where the nexthop is an IP address.
3446 * If we are a bgp static route being checked then there is
3447 * no need to check to see if the nexthop is martian as
3448 * that it should be ok.
3449 */
3450 if (is_bgp_static_route ||
3451 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3452 return false;
d62a17ae 3453
3454 /* If NEXT_HOP is present, validate it. */
3455 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3456 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3457 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3458 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3459 return true;
d62a17ae 3460 }
c265ee22 3461
d62a17ae 3462 /* If MP_NEXTHOP is present, validate it. */
3463 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3464 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3465 * it is not an IPv6 link-local address.
0355b41d
DA
3466 *
3467 * If we receive an UPDATE with nexthop length set to 32 bytes
3468 * we shouldn't discard an UPDATE if it's set to (::).
3469 * The link-local (2st) is validated along the code path later.
d62a17ae 3470 */
3471 if (attr->mp_nexthop_len) {
3472 switch (attr->mp_nexthop_len) {
3473 case BGP_ATTR_NHLEN_IPV4:
3474 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3475 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3476 || IPV4_CLASS_DE(
3477 ntohl(attr->mp_nexthop_global_in.s_addr))
3478 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3479 dest));
d62a17ae 3480 break;
3481
3482 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3483 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3484 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3485 &attr->mp_nexthop_global)
d62a17ae 3486 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3487 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3488 &attr->mp_nexthop_global)
3489 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3490 dest));
d62a17ae 3491 break;
0355b41d
DA
3492 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3493 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3494 || IN6_IS_ADDR_MULTICAST(
3495 &attr->mp_nexthop_global)
3496 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3497 dest));
0355b41d 3498 break;
d62a17ae 3499
3500 default:
3dc339cd 3501 ret = true;
d62a17ae 3502 break;
3503 }
3504 }
c265ee22 3505
d62a17ae 3506 return ret;
3507}
3508
aade37d7 3509static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3510{
3511 struct community *old;
3512 struct community *new;
3513 struct community *merge;
aade37d7 3514 struct community *no_export;
2721dd61
DA
3515
3516 old = attr->community;
aade37d7 3517 no_export = community_str2com("no-export");
2721dd61
DA
3518
3519 if (old) {
aade37d7 3520 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3521
3522 if (!old->refcnt)
3523 community_free(&old);
3524
3525 new = community_uniq_sort(merge);
3526 community_free(&merge);
3527 } else {
aade37d7 3528 new = community_dup(no_export);
2721dd61
DA
3529 }
3530
aade37d7 3531 community_free(&no_export);
2721dd61
DA
3532
3533 attr->community = new;
3534 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3535}
3536
5a1ae2c2 3537int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3538 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3539 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3540 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3541 struct bgp_route_evpn *evpn)
d62a17ae 3542{
3543 int ret;
3544 int aspath_loop_count = 0;
9bcb3eef 3545 struct bgp_dest *dest;
d62a17ae 3546 struct bgp *bgp;
3547 struct attr new_attr;
3548 struct attr *attr_new;
40381db7 3549 struct bgp_path_info *pi;
4b7e6066
DS
3550 struct bgp_path_info *new;
3551 struct bgp_path_info_extra *extra;
d62a17ae 3552 const char *reason;
3553 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3554 int connected = 0;
3555 int do_loop_check = 1;
3556 int has_valid_label = 0;
7c312383 3557 afi_t nh_afi;
949b0f24 3558 uint8_t pi_type = 0;
3559 uint8_t pi_sub_type = 0;
3560
c7bb4f00 3561 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3562 char pfxprint[PREFIX2STR_BUFFER];
3563
3564 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3565 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3566 afi, safi, attr);
6401252f
QY
3567 }
3568
49e5a4a0 3569#ifdef ENABLE_BGP_VNC
d62a17ae 3570 int vnc_implicit_withdraw = 0;
65efcfce 3571#endif
d62a17ae 3572 int same_attr = 0;
718e3744 3573
d62a17ae 3574 memset(&new_attr, 0, sizeof(struct attr));
3575 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3576 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3577
d62a17ae 3578 bgp = peer->bgp;
9bcb3eef 3579 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3580 /* TODO: Check to see if we can get rid of "is_valid_label" */
3581 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3582 has_valid_label = (num_labels > 0) ? 1 : 0;
3583 else
3584 has_valid_label = bgp_is_valid_label(label);
718e3744 3585
28f66de2
MS
3586 if (has_valid_label)
3587 assert(label != NULL);
3588
a77e2f4b
S
3589 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3590 * condition :
3591 * Suppress fib is enabled
3592 * BGP_OPT_NO_FIB is not enabled
3593 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3594 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3595 */
3596 if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
3597 (sub_type == BGP_ROUTE_NORMAL) &&
3598 (!bgp_option_check(BGP_OPT_NO_FIB)) &&
3599 (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3600 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3601
d62a17ae 3602 /* When peer's soft reconfiguration enabled. Record input packet in
3603 Adj-RIBs-In. */
3604 if (!soft_reconfig
3605 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3606 && peer != bgp->peer_self)
9bcb3eef 3607 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3608
3609 /* Check previously received route. */
9bcb3eef 3610 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3611 if (pi->peer == peer && pi->type == type
3612 && pi->sub_type == sub_type
3613 && pi->addpath_rx_id == addpath_id)
d62a17ae 3614 break;
3615
3616 /* AS path local-as loop check. */
3617 if (peer->change_local_as) {
c4368918
DW
3618 if (peer->allowas_in[afi][safi])
3619 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3620 else if (!CHECK_FLAG(peer->flags,
3621 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3622 aspath_loop_count = 1;
3623
3624 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3625 > aspath_loop_count) {
b4d46cc9 3626 peer->stat_pfx_aspath_loop++;
9bcb3eef 3627 reason = "as-path contains our own AS A;";
d62a17ae 3628 goto filtered;
3629 }
718e3744 3630 }
718e3744 3631
d62a17ae 3632 /* If the peer is configured for "allowas-in origin" and the last ASN in
3633 * the
3634 * as-path is our ASN then we do not need to call aspath_loop_check
3635 */
3636 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3637 if (aspath_get_last_as(attr->aspath) == bgp->as)
3638 do_loop_check = 0;
3639
3640 /* AS path loop check. */
3641 if (do_loop_check) {
3642 if (aspath_loop_check(attr->aspath, bgp->as)
3643 > peer->allowas_in[afi][safi]
3644 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3645 && aspath_loop_check(attr->aspath, bgp->confed_id)
3646 > peer->allowas_in[afi][safi])) {
b4d46cc9 3647 peer->stat_pfx_aspath_loop++;
d62a17ae 3648 reason = "as-path contains our own AS;";
3649 goto filtered;
3650 }
3651 }
aac9ef6c 3652
d62a17ae 3653 /* Route reflector originator ID check. */
3654 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3655 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3656 peer->stat_pfx_originator_loop++;
d62a17ae 3657 reason = "originator is us;";
3658 goto filtered;
3659 }
718e3744 3660
d62a17ae 3661 /* Route reflector cluster ID check. */
3662 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3663 peer->stat_pfx_cluster_loop++;
d62a17ae 3664 reason = "reflected from the same cluster;";
3665 goto filtered;
3666 }
718e3744 3667
d62a17ae 3668 /* Apply incoming filter. */
3669 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3670 peer->stat_pfx_filter++;
d62a17ae 3671 reason = "filter;";
3672 goto filtered;
3673 }
718e3744 3674
a8b72dc6
DA
3675 /* RFC 8212 to prevent route leaks.
3676 * This specification intends to improve this situation by requiring the
3677 * explicit configuration of both BGP Import and Export Policies for any
3678 * External BGP (EBGP) session such as customers, peers, or
3679 * confederation boundaries for all enabled address families. Through
3680 * codification of the aforementioned requirement, operators will
3681 * benefit from consistent behavior across different BGP
3682 * implementations.
3683 */
1d3fdccf 3684 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3685 if (!bgp_inbound_policy_exists(peer,
3686 &peer->filter[afi][safi])) {
3687 reason = "inbound policy missing";
3688 goto filtered;
3689 }
3690
fb29348a
DA
3691 /* draft-ietf-idr-deprecate-as-set-confed-set
3692 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3693 * Eventually, This document (if approved) updates RFC 4271
3694 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3695 * and obsoletes RFC 6472.
3696 */
7f972cd8 3697 if (peer->bgp->reject_as_sets)
fb29348a
DA
3698 if (aspath_check_as_sets(attr->aspath)) {
3699 reason =
3700 "as-path contains AS_SET or AS_CONFED_SET type;";
3701 goto filtered;
3702 }
3703
6f4f49b2 3704 new_attr = *attr;
d62a17ae 3705
3706 /* Apply incoming route-map.
3707 * NB: new_attr may now contain newly allocated values from route-map
3708 * "set"
3709 * commands, so we need bgp_attr_flush in the error paths, until we
3710 * intern
3711 * the attr (which takes over the memory references) */
9bcb3eef
DS
3712 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3713 num_labels, dest)
3714 == RMAP_DENY) {
b4d46cc9 3715 peer->stat_pfx_filter++;
d62a17ae 3716 reason = "route-map;";
3717 bgp_attr_flush(&new_attr);
3718 goto filtered;
3719 }
718e3744 3720
05864da7 3721 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3722 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3723 /* remove from RIB previous entry */
3724 bgp_zebra_withdraw(p, pi, bgp, safi);
3725 }
3726
7f323236
DW
3727 if (peer->sort == BGP_PEER_EBGP) {
3728
2721dd61
DA
3729 /* rfc7999:
3730 * A BGP speaker receiving an announcement tagged with the
3731 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3732 * NO_EXPORT community as defined in RFC1997, or a
3733 * similar community, to prevent propagation of the
3734 * prefix outside the local AS. The community to prevent
3735 * propagation SHOULD be chosen according to the operator's
3736 * routing policy.
3737 */
3738 if (new_attr.community
3739 && community_include(new_attr.community,
3740 COMMUNITY_BLACKHOLE))
aade37d7 3741 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3742
a4d82a8a
PZ
3743 /* If we receive the graceful-shutdown community from an eBGP
3744 * peer we must lower local-preference */
3745 if (new_attr.community
3746 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3747 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3748 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3749
a4d82a8a
PZ
3750 /* If graceful-shutdown is configured then add the GSHUT
3751 * community to all paths received from eBGP peers */
637e5ba4 3752 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3753 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3754 }
3755
949b0f24 3756 if (pi) {
3757 pi_type = pi->type;
3758 pi_sub_type = pi->sub_type;
3759 }
3760
d62a17ae 3761 /* next hop check. */
a4d82a8a 3762 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3763 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3764 &new_attr, dest)) {
b4d46cc9 3765 peer->stat_pfx_nh_invalid++;
d62a17ae 3766 reason = "martian or self next-hop;";
3767 bgp_attr_flush(&new_attr);
3768 goto filtered;
3769 }
718e3744 3770
5c14a191 3771 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3772 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3773 reason = "self mac;";
3774 goto filtered;
3775 }
3776
1e9be514
QY
3777 /* Update Overlay Index */
3778 if (afi == AFI_L2VPN) {
3779 overlay_index_update(&new_attr,
3780 evpn == NULL ? NULL : &evpn->gw_ip);
3781 }
3782
d62a17ae 3783 attr_new = bgp_attr_intern(&new_attr);
3784
9cbd06e0
DA
3785 /* If maximum prefix count is configured and current prefix
3786 * count exeed it.
3787 */
3788 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3789 return -1;
3790
d62a17ae 3791 /* If the update is implicit withdraw. */
40381db7
DS
3792 if (pi) {
3793 pi->uptime = bgp_clock();
3794 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3795
9bcb3eef 3796 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3797
d62a17ae 3798 /* Same attribute comes in. */
40381db7
DS
3799 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3800 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3801 && (!has_valid_label
40381db7 3802 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3803 num_labels * sizeof(mpls_label_t))
d62a17ae 3804 == 0)
3805 && (overlay_index_equal(
0a50c248 3806 afi, pi,
d62a17ae 3807 evpn == NULL ? NULL : &evpn->gw_ip))) {
40ec3340 3808 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3809 && peer->sort == BGP_PEER_EBGP
40381db7 3810 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3811 if (bgp_debug_update(peer, p, NULL, 1)) {
3812 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3813 afi, safi, prd, p, label,
3814 num_labels, addpath_id ? 1 : 0,
3815 addpath_id, pfx_buf,
3816 sizeof(pfx_buf));
d62a17ae 3817 zlog_debug("%s rcvd %s", peer->host,
3818 pfx_buf);
3819 }
3820
9bcb3eef 3821 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3822 != BGP_DAMP_SUPPRESSED) {
40381db7 3823 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3824 safi);
9bcb3eef 3825 bgp_process(bgp, dest, afi, safi);
d62a17ae 3826 }
3827 } else /* Duplicate - odd */
3828 {
3829 if (bgp_debug_update(peer, p, NULL, 1)) {
3830 if (!peer->rcvd_attr_printed) {
3831 zlog_debug(
3832 "%s rcvd UPDATE w/ attr: %s",
3833 peer->host,
3834 peer->rcvd_attr_str);
3835 peer->rcvd_attr_printed = 1;
3836 }
3837
3838 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3839 afi, safi, prd, p, label,
3840 num_labels, addpath_id ? 1 : 0,
3841 addpath_id, pfx_buf,
3842 sizeof(pfx_buf));
d62a17ae 3843 zlog_debug(
3844 "%s rcvd %s...duplicate ignored",
3845 peer->host, pfx_buf);
3846 }
3847
3848 /* graceful restart STALE flag unset. */
40381db7 3849 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3850 bgp_path_info_unset_flag(
9bcb3eef
DS
3851 dest, pi, BGP_PATH_STALE);
3852 bgp_dest_set_defer_flag(dest, false);
3853 bgp_process(bgp, dest, afi, safi);
d62a17ae 3854 }
3855 }
3856
9bcb3eef 3857 bgp_dest_unlock_node(dest);
d62a17ae 3858 bgp_attr_unintern(&attr_new);
3859
3860 return 0;
3861 }
718e3744 3862
d62a17ae 3863 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3864 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3865 if (bgp_debug_update(peer, p, NULL, 1)) {
3866 bgp_debug_rdpfxpath2str(
a4d82a8a 3867 afi, safi, prd, p, label, num_labels,
d62a17ae 3868 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3869 sizeof(pfx_buf));
3870 zlog_debug(
3871 "%s rcvd %s, flapped quicker than processing",
3872 peer->host, pfx_buf);
3873 }
3874
9bcb3eef 3875 bgp_path_info_restore(dest, pi);
d62a17ae 3876 }
718e3744 3877
d62a17ae 3878 /* Received Logging. */
3879 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3880 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3881 num_labels, addpath_id ? 1 : 0,
3882 addpath_id, pfx_buf,
3883 sizeof(pfx_buf));
d62a17ae 3884 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3885 }
718e3744 3886
d62a17ae 3887 /* graceful restart STALE flag unset. */
f009ff26 3888 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3889 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3890 bgp_dest_set_defer_flag(dest, false);
f009ff26 3891 }
d62a17ae 3892
3893 /* The attribute is changed. */
9bcb3eef 3894 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3895
3896 /* implicit withdraw, decrement aggregate and pcount here.
3897 * only if update is accepted, they'll increment below.
3898 */
40381db7 3899 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3900
3901 /* Update bgp route dampening information. */
40ec3340 3902 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3903 && peer->sort == BGP_PEER_EBGP) {
3904 /* This is implicit withdraw so we should update
40ec3340
DS
3905 * dampening information.
3906 */
40381db7 3907 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3908 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3909 }
49e5a4a0 3910#ifdef ENABLE_BGP_VNC
d62a17ae 3911 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3912 struct bgp_dest *pdest = NULL;
d62a17ae 3913 struct bgp_table *table = NULL;
3914
9bcb3eef
DS
3915 pdest = bgp_node_get(bgp->rib[afi][safi],
3916 (struct prefix *)prd);
3917 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3918 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3919
3920 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3921 bgp, prd, table, p, pi);
d62a17ae 3922 }
9bcb3eef 3923 bgp_dest_unlock_node(pdest);
d62a17ae 3924 }
3925 if ((afi == AFI_IP || afi == AFI_IP6)
3926 && (safi == SAFI_UNICAST)) {
40381db7 3927 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3928 /*
3929 * Implicit withdraw case.
3930 */
3931 ++vnc_implicit_withdraw;
40381db7
DS
3932 vnc_import_bgp_del_route(bgp, p, pi);
3933 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3934 }
3935 }
65efcfce 3936#endif
128ea8ab 3937
d62a17ae 3938 /* Special handling for EVPN update of an existing route. If the
3939 * extended community attribute has changed, we need to
3940 * un-import
3941 * the route using its existing extended community. It will be
3942 * subsequently processed for import with the new extended
3943 * community.
3944 */
6f8c9c11
PR
3945 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3946 && !same_attr) {
40381db7 3947 if ((pi->attr->flag
d62a17ae 3948 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3949 && (attr_new->flag
3950 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3951 int cmp;
3952
40381db7 3953 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3954 attr_new->ecommunity);
3955 if (!cmp) {
3956 if (bgp_debug_update(peer, p, NULL, 1))
3957 zlog_debug(
3958 "Change in EXT-COMM, existing %s new %s",
3959 ecommunity_str(
40381db7 3960 pi->attr->ecommunity),
d62a17ae 3961 ecommunity_str(
3962 attr_new->ecommunity));
6f8c9c11
PR
3963 if (safi == SAFI_EVPN)
3964 bgp_evpn_unimport_route(
3965 bgp, afi, safi, p, pi);
3966 else /* SAFI_MPLS_VPN */
3967 vpn_leak_to_vrf_withdraw(bgp,
3968 pi);
d62a17ae 3969 }
3970 }
3971 }
718e3744 3972
d62a17ae 3973 /* Update to new attribute. */
40381db7
DS
3974 bgp_attr_unintern(&pi->attr);
3975 pi->attr = attr_new;
d62a17ae 3976
3977 /* Update MPLS label */
3978 if (has_valid_label) {
40381db7 3979 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3980 if (extra->label != label) {
3981 memcpy(&extra->label, label,
dbd587da 3982 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3983 extra->num_labels = num_labels;
3984 }
b57ba6d2
MK
3985 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3986 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3987 }
718e3744 3988
e496b420
HS
3989 /* Update SRv6 SID */
3990 if (attr->srv6_l3vpn) {
3991 extra = bgp_path_info_extra_get(pi);
3992 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3993 sid_copy(&extra->sid[0],
3994 &attr->srv6_l3vpn->sid);
3995 extra->num_sids = 1;
3996 }
3997 } else if (attr->srv6_vpn) {
3998 extra = bgp_path_info_extra_get(pi);
3999 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4000 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4001 extra->num_sids = 1;
4002 }
4003 }
4004
49e5a4a0 4005#ifdef ENABLE_BGP_VNC
d62a17ae 4006 if ((afi == AFI_IP || afi == AFI_IP6)
4007 && (safi == SAFI_UNICAST)) {
4008 if (vnc_implicit_withdraw) {
4009 /*
4010 * Add back the route with its new attributes
4011 * (e.g., nexthop).
4012 * The route is still selected, until the route
4013 * selection
4014 * queued by bgp_process actually runs. We have
4015 * to make this
4016 * update to the VNC side immediately to avoid
4017 * racing against
4018 * configuration changes (e.g., route-map
4019 * changes) which
4020 * trigger re-importation of the entire RIB.
4021 */
40381db7
DS
4022 vnc_import_bgp_add_route(bgp, p, pi);
4023 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4024 }
4025 }
65efcfce
LB
4026#endif
4027
d62a17ae 4028 /* Update bgp route dampening information. */
40ec3340 4029 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 4030 && peer->sort == BGP_PEER_EBGP) {
4031 /* Now we do normal update dampening. */
9bcb3eef 4032 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4033 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4034 bgp_dest_unlock_node(dest);
d62a17ae 4035 return 0;
4036 }
4037 }
128ea8ab 4038
d62a17ae 4039 /* Nexthop reachability check - for unicast and
4040 * labeled-unicast.. */
7c312383
AD
4041 if (((afi == AFI_IP || afi == AFI_IP6)
4042 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4043 || (safi == SAFI_EVPN &&
4044 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4045 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4046 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4047 && !CHECK_FLAG(peer->flags,
4048 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4049 && !CHECK_FLAG(bgp->flags,
4050 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4051 connected = 1;
4052 else
4053 connected = 0;
4054
960035b2
PZ
4055 struct bgp *bgp_nexthop = bgp;
4056
40381db7
DS
4057 if (pi->extra && pi->extra->bgp_orig)
4058 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4059
7c312383
AD
4060 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4061
4062 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4063 pi, NULL, connected)
a4d82a8a 4064 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4065 bgp_path_info_set_flag(dest, pi,
4066 BGP_PATH_VALID);
d62a17ae 4067 else {
4068 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4069 zlog_debug("%s(%pI4): NH unresolved",
4070 __func__,
4071 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4072 }
9bcb3eef 4073 bgp_path_info_unset_flag(dest, pi,
18ee8310 4074 BGP_PATH_VALID);
d62a17ae 4075 }
4076 } else
9bcb3eef 4077 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4078
49e5a4a0 4079#ifdef ENABLE_BGP_VNC
d62a17ae 4080 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4081 struct bgp_dest *pdest = NULL;
d62a17ae 4082 struct bgp_table *table = NULL;
4083
9bcb3eef
DS
4084 pdest = bgp_node_get(bgp->rib[afi][safi],
4085 (struct prefix *)prd);
4086 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4087 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4088
4089 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4090 bgp, prd, table, p, pi);
d62a17ae 4091 }
9bcb3eef 4092 bgp_dest_unlock_node(pdest);
d62a17ae 4093 }
4094#endif
718e3744 4095
d62a17ae 4096 /* If this is an EVPN route and some attribute has changed,
4097 * process
4098 * route for import. If the extended community has changed, we
4099 * would
4100 * have done the un-import earlier and the import would result
4101 * in the
4102 * route getting injected into appropriate L2 VNIs. If it is
4103 * just
4104 * some other attribute change, the import will result in
4105 * updating
4106 * the attributes for the route in the VNI(s).
4107 */
7c312383
AD
4108 if (safi == SAFI_EVPN && !same_attr &&
4109 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4110 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4111
4112 /* Process change. */
40381db7 4113 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4114
9bcb3eef
DS
4115 bgp_process(bgp, dest, afi, safi);
4116 bgp_dest_unlock_node(dest);
558d1fec 4117
ddb5b488
PZ
4118 if (SAFI_UNICAST == safi
4119 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4120 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4121
40381db7 4122 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4123 }
4124 if ((SAFI_MPLS_VPN == safi)
4125 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4126
40381db7 4127 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4128 }
4129
49e5a4a0 4130#ifdef ENABLE_BGP_VNC
d62a17ae 4131 if (SAFI_MPLS_VPN == safi) {
4132 mpls_label_t label_decoded = decode_label(label);
28070ee3 4133
d62a17ae 4134 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4135 type, sub_type, &label_decoded);
4136 }
4137 if (SAFI_ENCAP == safi) {
4138 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4139 type, sub_type, NULL);
4140 }
28070ee3
PZ
4141#endif
4142
d62a17ae 4143 return 0;
4144 } // End of implicit withdraw
718e3744 4145
d62a17ae 4146 /* Received Logging. */
4147 if (bgp_debug_update(peer, p, NULL, 1)) {
4148 if (!peer->rcvd_attr_printed) {
4149 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4150 peer->rcvd_attr_str);
4151 peer->rcvd_attr_printed = 1;
4152 }
718e3744 4153
a4d82a8a 4154 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4155 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4156 sizeof(pfx_buf));
4157 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4158 }
718e3744 4159
d62a17ae 4160 /* Make new BGP info. */
9bcb3eef 4161 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4162
d62a17ae 4163 /* Update MPLS label */
4164 if (has_valid_label) {
18ee8310 4165 extra = bgp_path_info_extra_get(new);
8ba71050 4166 if (extra->label != label) {
dbd587da
QY
4167 memcpy(&extra->label, label,
4168 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4169 extra->num_labels = num_labels;
4170 }
b57ba6d2
MK
4171 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4172 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4173 }
718e3744 4174
e496b420
HS
4175 /* Update SRv6 SID */
4176 if (safi == SAFI_MPLS_VPN) {
4177 extra = bgp_path_info_extra_get(new);
4178 if (attr->srv6_l3vpn) {
4179 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4180 extra->num_sids = 1;
4181 } else if (attr->srv6_vpn) {
4182 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4183 extra->num_sids = 1;
4184 }
4185 }
4186
d62a17ae 4187 /* Update Overlay Index */
4188 if (afi == AFI_L2VPN) {
4189 overlay_index_update(new->attr,
d62a17ae 4190 evpn == NULL ? NULL : &evpn->gw_ip);
4191 }
4192 /* Nexthop reachability check. */
7c312383
AD
4193 if (((afi == AFI_IP || afi == AFI_IP6)
4194 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4195 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4196 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4197 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4198 && !CHECK_FLAG(peer->flags,
4199 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4200 && !CHECK_FLAG(bgp->flags,
4201 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4202 connected = 1;
4203 else
4204 connected = 0;
4205
7c312383
AD
4206 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4207
4208 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
4209 connected)
a4d82a8a 4210 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4211 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4212 else {
4213 if (BGP_DEBUG(nht, NHT)) {
4214 char buf1[INET6_ADDRSTRLEN];
4215 inet_ntop(AF_INET,
4216 (const void *)&attr_new->nexthop,
4217 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4218 zlog_debug("%s(%s): NH unresolved", __func__,
4219 buf1);
d62a17ae 4220 }
9bcb3eef 4221 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4222 }
4223 } else
9bcb3eef 4224 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4225
d62a17ae 4226 /* Addpath ID */
4227 new->addpath_rx_id = addpath_id;
4228
4229 /* Increment prefix */
4230 bgp_aggregate_increment(bgp, p, new, afi, safi);
4231
4232 /* Register new BGP information. */
9bcb3eef 4233 bgp_path_info_add(dest, new);
d62a17ae 4234
4235 /* route_node_get lock */
9bcb3eef 4236 bgp_dest_unlock_node(dest);
558d1fec 4237
49e5a4a0 4238#ifdef ENABLE_BGP_VNC
d62a17ae 4239 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4240 struct bgp_dest *pdest = NULL;
d62a17ae 4241 struct bgp_table *table = NULL;
4242
9bcb3eef
DS
4243 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4244 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4245 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4246
4247 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4248 bgp, prd, table, p, new);
4249 }
9bcb3eef 4250 bgp_dest_unlock_node(pdest);
d62a17ae 4251 }
65efcfce
LB
4252#endif
4253
d62a17ae 4254 /* If this is an EVPN route, process for import. */
7c312383 4255 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4256 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4257
9bcb3eef 4258 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4259
d62a17ae 4260 /* Process change. */
9bcb3eef 4261 bgp_process(bgp, dest, afi, safi);
718e3744 4262
ddb5b488
PZ
4263 if (SAFI_UNICAST == safi
4264 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4265 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4266 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4267 }
4268 if ((SAFI_MPLS_VPN == safi)
4269 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4270
4271 vpn_leak_to_vrf_update(bgp, new);
4272 }
49e5a4a0 4273#ifdef ENABLE_BGP_VNC
d62a17ae 4274 if (SAFI_MPLS_VPN == safi) {
4275 mpls_label_t label_decoded = decode_label(label);
28070ee3 4276
d62a17ae 4277 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4278 sub_type, &label_decoded);
4279 }
4280 if (SAFI_ENCAP == safi) {
4281 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4282 sub_type, NULL);
4283 }
28070ee3
PZ
4284#endif
4285
d62a17ae 4286 return 0;
718e3744 4287
d62a17ae 4288/* This BGP update is filtered. Log the reason then update BGP
4289 entry. */
4290filtered:
9bcb3eef 4291 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4292
d62a17ae 4293 if (bgp_debug_update(peer, p, NULL, 1)) {
4294 if (!peer->rcvd_attr_printed) {
4295 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4296 peer->rcvd_attr_str);
4297 peer->rcvd_attr_printed = 1;
4298 }
718e3744 4299
a4d82a8a 4300 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4301 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4302 sizeof(pfx_buf));
4303 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4304 peer->host, pfx_buf, reason);
4305 }
128ea8ab 4306
40381db7 4307 if (pi) {
d62a17ae 4308 /* If this is an EVPN route, un-import it as it is now filtered.
4309 */
4310 if (safi == SAFI_EVPN)
40381db7 4311 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4312
ddb5b488
PZ
4313 if (SAFI_UNICAST == safi
4314 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4315 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4316
40381db7 4317 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4318 }
4319 if ((SAFI_MPLS_VPN == safi)
4320 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4321
40381db7 4322 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4323 }
4324
9bcb3eef 4325 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4326 }
4327
9bcb3eef 4328 bgp_dest_unlock_node(dest);
558d1fec 4329
49e5a4a0 4330#ifdef ENABLE_BGP_VNC
d62a17ae 4331 /*
4332 * Filtered update is treated as an implicit withdrawal (see
4333 * bgp_rib_remove()
4334 * a few lines above)
4335 */
4336 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4337 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4338 0);
4339 }
97736e32
PZ
4340#endif
4341
d62a17ae 4342 return 0;
718e3744 4343}
4344
26a3ffd6 4345int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4346 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4347 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4348 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4349{
d62a17ae 4350 struct bgp *bgp;
4351 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4352 struct bgp_dest *dest;
40381db7 4353 struct bgp_path_info *pi;
718e3744 4354
49e5a4a0 4355#ifdef ENABLE_BGP_VNC
d62a17ae 4356 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4357 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4358 0);
4359 }
28070ee3
PZ
4360#endif
4361
d62a17ae 4362 bgp = peer->bgp;
4363
4364 /* Lookup node. */
9bcb3eef 4365 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4366
4367 /* If peer is soft reconfiguration enabled. Record input packet for
4368 * further calculation.
4369 *
4370 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4371 * routes that are filtered. This tanks out Quagga RS pretty badly due
4372 * to
4373 * the iteration over all RS clients.
4374 * Since we need to remove the entry from adj_in anyway, do that first
4375 * and
4376 * if there was no entry, we don't need to do anything more.
4377 */
4378 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4379 && peer != bgp->peer_self)
9bcb3eef 4380 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4381 peer->stat_pfx_dup_withdraw++;
4382
d62a17ae 4383 if (bgp_debug_update(peer, p, NULL, 1)) {
4384 bgp_debug_rdpfxpath2str(
a4d82a8a 4385 afi, safi, prd, p, label, num_labels,
d62a17ae 4386 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4387 sizeof(pfx_buf));
4388 zlog_debug(
4389 "%s withdrawing route %s not in adj-in",
4390 peer->host, pfx_buf);
4391 }
9bcb3eef 4392 bgp_dest_unlock_node(dest);
d62a17ae 4393 return 0;
4394 }
cd808e74 4395
d62a17ae 4396 /* Lookup withdrawn route. */
9bcb3eef 4397 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4398 if (pi->peer == peer && pi->type == type
4399 && pi->sub_type == sub_type
4400 && pi->addpath_rx_id == addpath_id)
d62a17ae 4401 break;
4402
4403 /* Logging. */
4404 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4405 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4406 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4407 sizeof(pfx_buf));
4408 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4409 pfx_buf);
4410 }
718e3744 4411
d62a17ae 4412 /* Withdraw specified route from routing table. */
40381db7 4413 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4414 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4415 if (SAFI_UNICAST == safi
4416 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4417 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4418 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4419 }
4420 if ((SAFI_MPLS_VPN == safi)
4421 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4422
40381db7 4423 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4424 }
4425 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4426 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4427 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4428 sizeof(pfx_buf));
4429 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4430 }
718e3744 4431
d62a17ae 4432 /* Unlock bgp_node_get() lock. */
9bcb3eef 4433 bgp_dest_unlock_node(dest);
d62a17ae 4434
4435 return 0;
718e3744 4436}
6b0655a2 4437
d62a17ae 4438void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4439 int withdraw)
718e3744 4440{
d62a17ae 4441 struct update_subgroup *subgrp;
4442 subgrp = peer_subgroup(peer, afi, safi);
4443 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4444}
6182d65b 4445
718e3744 4446
3f9c7369
DS
4447/*
4448 * bgp_stop_announce_route_timer
4449 */
d62a17ae 4450void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4451{
d62a17ae 4452 if (!paf->t_announce_route)
4453 return;
4454
50478845 4455 thread_cancel(&paf->t_announce_route);
718e3744 4456}
6b0655a2 4457
3f9c7369
DS
4458/*
4459 * bgp_announce_route_timer_expired
4460 *
4461 * Callback that is invoked when the route announcement timer for a
4462 * peer_af expires.
4463 */
d62a17ae 4464static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4465{
d62a17ae 4466 struct peer_af *paf;
4467 struct peer *peer;
558d1fec 4468
d62a17ae 4469 paf = THREAD_ARG(t);
4470 peer = paf->peer;
718e3744 4471
d62a17ae 4472 if (peer->status != Established)
4473 return 0;
3f9c7369 4474
d62a17ae 4475 if (!peer->afc_nego[paf->afi][paf->safi])
4476 return 0;
3f9c7369 4477
d62a17ae 4478 peer_af_announce_route(paf, 1);
c5aec50b
MK
4479
4480 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4481 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4482
d62a17ae 4483 return 0;
718e3744 4484}
4485
3f9c7369
DS
4486/*
4487 * bgp_announce_route
4488 *
4489 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4490 */
d62a17ae 4491void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4492{
4493 struct peer_af *paf;
4494 struct update_subgroup *subgrp;
4495
4496 paf = peer_af_find(peer, afi, safi);
4497 if (!paf)
4498 return;
4499 subgrp = PAF_SUBGRP(paf);
4500
4501 /*
4502 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4503 * or a refresh has already been triggered.
4504 */
4505 if (!subgrp || paf->t_announce_route)
4506 return;
4507
4508 /*
4509 * Start a timer to stagger/delay the announce. This serves
4510 * two purposes - announcement can potentially be combined for
4511 * multiple peers and the announcement doesn't happen in the
4512 * vty context.
4513 */
4514 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4515 (subgrp->peer_count == 1)
4516 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4517 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4518 &paf->t_announce_route);
3f9c7369
DS
4519}
4520
4521/*
4522 * Announce routes from all AF tables to a peer.
4523 *
4524 * This should ONLY be called when there is a need to refresh the
4525 * routes to the peer based on a policy change for this peer alone
4526 * or a route refresh request received from the peer.
4527 * The operation will result in splitting the peer from its existing
4528 * subgroups and putting it in new subgroups.
4529 */
d62a17ae 4530void bgp_announce_route_all(struct peer *peer)
718e3744 4531{
d62a17ae 4532 afi_t afi;
4533 safi_t safi;
4534
05c7a1cc
QY
4535 FOREACH_AFI_SAFI (afi, safi)
4536 bgp_announce_route(peer, afi, safi);
718e3744 4537}
6b0655a2 4538
d62a17ae 4539static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4540 struct bgp_table *table,
4541 struct prefix_rd *prd)
718e3744 4542{
d62a17ae 4543 int ret;
9bcb3eef 4544 struct bgp_dest *dest;
d62a17ae 4545 struct bgp_adj_in *ain;
718e3744 4546
d62a17ae 4547 if (!table)
4548 table = peer->bgp->rib[afi][safi];
718e3744 4549
9bcb3eef
DS
4550 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4551 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4552 if (ain->peer != peer)
4553 continue;
8692c506 4554
d7d15889 4555 struct bgp_path_info *pi;
d7c0a89a 4556 uint32_t num_labels = 0;
b57ba6d2 4557 mpls_label_t *label_pnt = NULL;
8cb687c2 4558 struct bgp_route_evpn evpn;
b57ba6d2 4559
9bcb3eef 4560 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4561 pi = pi->next)
4562 if (pi->peer == peer)
4563 break;
4564
40381db7
DS
4565 if (pi && pi->extra)
4566 num_labels = pi->extra->num_labels;
b57ba6d2 4567 if (num_labels)
40381db7 4568 label_pnt = &pi->extra->label[0];
8cb687c2 4569 if (pi)
6c924775
DS
4570 memcpy(&evpn,
4571 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4572 sizeof(evpn));
4573 else
4574 memset(&evpn, 0, sizeof(evpn));
8692c506 4575
9bcb3eef
DS
4576 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4577 ain->addpath_rx_id, ain->attr, afi,
4578 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4579 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4580 num_labels, 1, &evpn);
ea47320b
DL
4581
4582 if (ret < 0) {
9bcb3eef 4583 bgp_dest_unlock_node(dest);
ea47320b 4584 return;
d62a17ae 4585 }
4586 }
718e3744 4587}
4588
d62a17ae 4589void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4590{
9bcb3eef 4591 struct bgp_dest *dest;
d62a17ae 4592 struct bgp_table *table;
718e3744 4593
d62a17ae 4594 if (peer->status != Established)
4595 return;
718e3744 4596
d62a17ae 4597 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4598 && (safi != SAFI_EVPN))
4599 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4600 else
9bcb3eef
DS
4601 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4602 dest = bgp_route_next(dest)) {
4603 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4604
b54892e0
DS
4605 if (table == NULL)
4606 continue;
8692c506 4607
9bcb3eef 4608 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4609 struct prefix_rd prd;
4610
4611 prd.family = AF_UNSPEC;
4612 prd.prefixlen = 64;
4613 memcpy(&prd.val, p->u.val, 8);
4614
4615 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4616 }
718e3744 4617}
6b0655a2 4618
228da428 4619
d62a17ae 4620struct bgp_clear_node_queue {
9bcb3eef 4621 struct bgp_dest *dest;
228da428
CC
4622};
4623
d62a17ae 4624static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4625{
d62a17ae 4626 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4627 struct bgp_dest *dest = cnq->dest;
d62a17ae 4628 struct peer *peer = wq->spec.data;
40381db7 4629 struct bgp_path_info *pi;
3103e8d2 4630 struct bgp *bgp;
9bcb3eef
DS
4631 afi_t afi = bgp_dest_table(dest)->afi;
4632 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4633
9bcb3eef 4634 assert(dest && peer);
3103e8d2 4635 bgp = peer->bgp;
d62a17ae 4636
4637 /* It is possible that we have multiple paths for a prefix from a peer
4638 * if that peer is using AddPath.
4639 */
9bcb3eef 4640 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4641 if (pi->peer != peer)
ea47320b
DL
4642 continue;
4643
4644 /* graceful restart STALE flag set. */
9af52ccf
DA
4645 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4646 && peer->nsf[afi][safi])
4647 || CHECK_FLAG(peer->af_sflags[afi][safi],
4648 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4649 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4650 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4651 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4652 else {
4653 /* If this is an EVPN route, process for
4654 * un-import. */
4655 if (safi == SAFI_EVPN)
9bcb3eef
DS
4656 bgp_evpn_unimport_route(
4657 bgp, afi, safi,
4658 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4659 /* Handle withdraw for VRF route-leaking and L3VPN */
4660 if (SAFI_UNICAST == safi
4661 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4662 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4663 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4664 bgp, pi);
960035b2 4665 }
3103e8d2 4666 if (SAFI_MPLS_VPN == safi &&
960035b2 4667 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4668 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4669 }
3103e8d2 4670
9bcb3eef 4671 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4672 }
ea47320b 4673 }
d62a17ae 4674 return WQ_SUCCESS;
200df115 4675}
4676
d62a17ae 4677static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4678{
d62a17ae 4679 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4680 struct bgp_dest *dest = cnq->dest;
4681 struct bgp_table *table = bgp_dest_table(dest);
228da428 4682
9bcb3eef 4683 bgp_dest_unlock_node(dest);
d62a17ae 4684 bgp_table_unlock(table);
4685 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4686}
4687
d62a17ae 4688static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4689{
d62a17ae 4690 struct peer *peer = wq->spec.data;
64e580a7 4691
d62a17ae 4692 /* Tickle FSM to start moving again */
4693 BGP_EVENT_ADD(peer, Clearing_Completed);
4694
4695 peer_unlock(peer); /* bgp_clear_route */
200df115 4696}
718e3744 4697
d62a17ae 4698static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4699{
d62a17ae 4700 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4701
4702 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4703#undef CLEAR_QUEUE_NAME_LEN
4704
0ce1ca80 4705 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4706 peer->clear_node_queue->spec.hold = 10;
4707 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4708 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4709 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4710 peer->clear_node_queue->spec.max_retries = 0;
4711
4712 /* we only 'lock' this peer reference when the queue is actually active
4713 */
4714 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4715}
4716
d62a17ae 4717static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4718 struct bgp_table *table)
65ca75e0 4719{
9bcb3eef 4720 struct bgp_dest *dest;
b6c386bb 4721 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4722
d62a17ae 4723 if (!table)
4724 table = peer->bgp->rib[afi][safi];
dc83d712 4725
d62a17ae 4726 /* If still no table => afi/safi isn't configured at all or smth. */
4727 if (!table)
4728 return;
dc83d712 4729
9bcb3eef 4730 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4731 struct bgp_path_info *pi, *next;
d62a17ae 4732 struct bgp_adj_in *ain;
4733 struct bgp_adj_in *ain_next;
4734
4735 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4736 * queued for every clearing peer, regardless of whether it is
4737 * relevant to the peer at hand.
4738 *
4739 * Overview: There are 3 different indices which need to be
4740 * scrubbed, potentially, when a peer is removed:
4741 *
4742 * 1 peer's routes visible via the RIB (ie accepted routes)
4743 * 2 peer's routes visible by the (optional) peer's adj-in index
4744 * 3 other routes visible by the peer's adj-out index
4745 *
4746 * 3 there is no hurry in scrubbing, once the struct peer is
4747 * removed from bgp->peer, we could just GC such deleted peer's
4748 * adj-outs at our leisure.
4749 *
4750 * 1 and 2 must be 'scrubbed' in some way, at least made
4751 * invisible via RIB index before peer session is allowed to be
4752 * brought back up. So one needs to know when such a 'search' is
4753 * complete.
4754 *
4755 * Ideally:
4756 *
4757 * - there'd be a single global queue or a single RIB walker
4758 * - rather than tracking which route_nodes still need to be
4759 * examined on a peer basis, we'd track which peers still
4760 * aren't cleared
4761 *
4762 * Given that our per-peer prefix-counts now should be reliable,
4763 * this may actually be achievable. It doesn't seem to be a huge
4764 * problem at this time,
4765 *
4766 * It is possible that we have multiple paths for a prefix from
4767 * a peer
4768 * if that peer is using AddPath.
4769 */
9bcb3eef 4770 ain = dest->adj_in;
d62a17ae 4771 while (ain) {
4772 ain_next = ain->next;
4773
4774 if (ain->peer == peer) {
9bcb3eef
DS
4775 bgp_adj_in_remove(dest, ain);
4776 bgp_dest_unlock_node(dest);
d62a17ae 4777 }
4778
4779 ain = ain_next;
4780 }
4781
9bcb3eef 4782 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4783 next = pi->next;
4784 if (pi->peer != peer)
d62a17ae 4785 continue;
4786
4787 if (force)
9bcb3eef 4788 bgp_path_info_reap(dest, pi);
d62a17ae 4789 else {
4790 struct bgp_clear_node_queue *cnq;
4791
4792 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4793 bgp_table_lock(bgp_dest_table(dest));
4794 bgp_dest_lock_node(dest);
d62a17ae 4795 cnq = XCALLOC(
4796 MTYPE_BGP_CLEAR_NODE_QUEUE,
4797 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4798 cnq->dest = dest;
d62a17ae 4799 work_queue_add(peer->clear_node_queue, cnq);
4800 break;
4801 }
4802 }
4803 }
4804 return;
4805}
4806
4807void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4808{
9bcb3eef 4809 struct bgp_dest *dest;
d62a17ae 4810 struct bgp_table *table;
4811
4812 if (peer->clear_node_queue == NULL)
4813 bgp_clear_node_queue_init(peer);
4814
4815 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4816 * Idle until it receives a Clearing_Completed event. This protects
4817 * against peers which flap faster than we can we clear, which could
4818 * lead to:
4819 *
4820 * a) race with routes from the new session being installed before
4821 * clear_route_node visits the node (to delete the route of that
4822 * peer)
4823 * b) resource exhaustion, clear_route_node likely leads to an entry
4824 * on the process_main queue. Fast-flapping could cause that queue
4825 * to grow and grow.
4826 */
4827
4828 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4829 * the unlock will happen upon work-queue completion; other wise, the
4830 * unlock happens at the end of this function.
4831 */
4832 if (!peer->clear_node_queue->thread)
4833 peer_lock(peer);
4834
4835 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4836 bgp_clear_route_table(peer, afi, safi, NULL);
4837 else
9bcb3eef
DS
4838 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4839 dest = bgp_route_next(dest)) {
4840 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4841 if (!table)
4842 continue;
4843
4844 bgp_clear_route_table(peer, afi, safi, table);
4845 }
d62a17ae 4846
4847 /* unlock if no nodes got added to the clear-node-queue. */
4848 if (!peer->clear_node_queue->thread)
4849 peer_unlock(peer);
718e3744 4850}
d62a17ae 4851
4852void bgp_clear_route_all(struct peer *peer)
718e3744 4853{
d62a17ae 4854 afi_t afi;
4855 safi_t safi;
718e3744 4856
05c7a1cc
QY
4857 FOREACH_AFI_SAFI (afi, safi)
4858 bgp_clear_route(peer, afi, safi);
65efcfce 4859
49e5a4a0 4860#ifdef ENABLE_BGP_VNC
d62a17ae 4861 rfapiProcessPeerDown(peer);
65efcfce 4862#endif
718e3744 4863}
4864
d62a17ae 4865void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4866{
d62a17ae 4867 struct bgp_table *table;
9bcb3eef 4868 struct bgp_dest *dest;
d62a17ae 4869 struct bgp_adj_in *ain;
4870 struct bgp_adj_in *ain_next;
718e3744 4871
d62a17ae 4872 table = peer->bgp->rib[afi][safi];
718e3744 4873
d62a17ae 4874 /* It is possible that we have multiple paths for a prefix from a peer
4875 * if that peer is using AddPath.
4876 */
9bcb3eef
DS
4877 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4878 ain = dest->adj_in;
43143c8f 4879
d62a17ae 4880 while (ain) {
4881 ain_next = ain->next;
43143c8f 4882
d62a17ae 4883 if (ain->peer == peer) {
9bcb3eef
DS
4884 bgp_adj_in_remove(dest, ain);
4885 bgp_dest_unlock_node(dest);
d62a17ae 4886 }
43143c8f 4887
d62a17ae 4888 ain = ain_next;
4889 }
4890 }
718e3744 4891}
93406d87 4892
d62a17ae 4893void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4894{
9bcb3eef 4895 struct bgp_dest *dest;
40381db7 4896 struct bgp_path_info *pi;
d62a17ae 4897 struct bgp_table *table;
4898
9af52ccf 4899 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
4900 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4901 dest = bgp_route_next(dest)) {
4902 struct bgp_dest *rm;
d62a17ae 4903
4904 /* look for neighbor in tables */
9bcb3eef 4905 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4906 if (!table)
ea47320b
DL
4907 continue;
4908
4909 for (rm = bgp_table_top(table); rm;
4910 rm = bgp_route_next(rm))
9bcb3eef 4911 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4912 pi = pi->next) {
40381db7 4913 if (pi->peer != peer)
ea47320b 4914 continue;
40381db7 4915 if (!CHECK_FLAG(pi->flags,
1defdda8 4916 BGP_PATH_STALE))
ea47320b
DL
4917 break;
4918
40381db7 4919 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4920 break;
4921 }
d62a17ae 4922 }
4923 } else {
9bcb3eef
DS
4924 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4925 dest = bgp_route_next(dest))
4926 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4927 pi = pi->next) {
40381db7 4928 if (pi->peer != peer)
ea47320b 4929 continue;
40381db7 4930 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4931 break;
9bcb3eef 4932 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4933 break;
4934 }
d62a17ae 4935 }
93406d87 4936}
6b0655a2 4937
9af52ccf
DA
4938void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4939{
4940 struct bgp_dest *dest, *ndest;
4941 struct bgp_path_info *pi;
4942 struct bgp_table *table;
4943
4944 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4945 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4946 dest = bgp_route_next(dest)) {
4947 table = bgp_dest_get_bgp_table_info(dest);
4948 if (!table)
4949 continue;
4950
4951 for (ndest = bgp_table_top(table); ndest;
4952 ndest = bgp_route_next(ndest)) {
4953 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
4954 pi = pi->next) {
4955 if (pi->peer != peer)
4956 continue;
4957
4958 if ((CHECK_FLAG(
4959 peer->af_sflags[afi][safi],
4960 PEER_STATUS_ENHANCED_REFRESH))
4961 && !CHECK_FLAG(pi->flags,
4962 BGP_PATH_STALE)
4963 && !CHECK_FLAG(
4964 pi->flags,
4965 BGP_PATH_UNUSEABLE)) {
4966 if (bgp_debug_neighbor_events(
4967 peer))
4968 zlog_debug(
4969 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4970 peer->host,
4971 afi2str(afi),
4972 safi2str(safi),
4973 bgp_dest_get_prefix(
4974 ndest));
4975
4976 bgp_path_info_set_flag(
4977 ndest, pi,
4978 BGP_PATH_STALE);
4979 }
4980 }
4981 }
4982 }
4983 } else {
4984 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4985 dest = bgp_route_next(dest)) {
4986 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4987 pi = pi->next) {
4988 if (pi->peer != peer)
4989 continue;
4990
4991 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
4992 PEER_STATUS_ENHANCED_REFRESH))
4993 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4994 && !CHECK_FLAG(pi->flags,
4995 BGP_PATH_UNUSEABLE)) {
4996 if (bgp_debug_neighbor_events(peer))
4997 zlog_debug(
4998 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4999 peer->host,
5000 afi2str(afi),
5001 safi2str(safi),
5002 bgp_dest_get_prefix(
5003 dest));
5004
5005 bgp_path_info_set_flag(dest, pi,
5006 BGP_PATH_STALE);
5007 }
5008 }
5009 }
5010 }
5011}
5012
3dc339cd 5013bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5014{
e0df4c04 5015 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5016 return true;
e0df4c04 5017
9dac9fc8
DA
5018 if (peer->sort == BGP_PEER_EBGP
5019 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5020 || FILTER_LIST_OUT_NAME(filter)
5021 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5022 return true;
5023 return false;
9dac9fc8
DA
5024}
5025
3dc339cd 5026bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5027{
e0df4c04 5028 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5029 return true;
e0df4c04 5030
9dac9fc8
DA
5031 if (peer->sort == BGP_PEER_EBGP
5032 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5033 || FILTER_LIST_IN_NAME(filter)
5034 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5035 return true;
5036 return false;
9dac9fc8
DA
5037}
5038
568e10ca 5039static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5040 safi_t safi)
bb86c601 5041{
9bcb3eef 5042 struct bgp_dest *dest;
40381db7 5043 struct bgp_path_info *pi;
4b7e6066 5044 struct bgp_path_info *next;
bb86c601 5045
9bcb3eef
DS
5046 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5047 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5048 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5049
40381db7 5050 next = pi->next;
1b7bb747
CS
5051
5052 /* Unimport EVPN routes from VRFs */
5053 if (safi == SAFI_EVPN)
5054 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5055 SAFI_EVPN, p, pi);
1b7bb747 5056
40381db7
DS
5057 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5058 && pi->type == ZEBRA_ROUTE_BGP
5059 && (pi->sub_type == BGP_ROUTE_NORMAL
5060 || pi->sub_type == BGP_ROUTE_AGGREGATE
5061 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5062
d62a17ae 5063 if (bgp_fibupd_safi(safi))
b54892e0 5064 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5065 }
9514b37d 5066
9bcb3eef 5067 bgp_path_info_reap(dest, pi);
d62a17ae 5068 }
bb86c601
LB
5069}
5070
718e3744 5071/* Delete all kernel routes. */
d62a17ae 5072void bgp_cleanup_routes(struct bgp *bgp)
5073{
5074 afi_t afi;
9bcb3eef 5075 struct bgp_dest *dest;
67009e22 5076 struct bgp_table *table;
d62a17ae 5077
5078 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5079 if (afi == AFI_L2VPN)
5080 continue;
568e10ca 5081 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5082 SAFI_UNICAST);
d62a17ae 5083 /*
5084 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5085 */
5086 if (afi != AFI_L2VPN) {
5087 safi_t safi;
5088 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5089 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5090 dest = bgp_route_next(dest)) {
5091 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5092 if (table != NULL) {
5093 bgp_cleanup_table(bgp, table, safi);
5094 bgp_table_finish(&table);
9bcb3eef
DS
5095 bgp_dest_set_bgp_table_info(dest, NULL);
5096 bgp_dest_unlock_node(dest);
d62a17ae 5097 }
5098 }
5099 safi = SAFI_ENCAP;
9bcb3eef
DS
5100 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5101 dest = bgp_route_next(dest)) {
5102 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5103 if (table != NULL) {
5104 bgp_cleanup_table(bgp, table, safi);
5105 bgp_table_finish(&table);
9bcb3eef
DS
5106 bgp_dest_set_bgp_table_info(dest, NULL);
5107 bgp_dest_unlock_node(dest);
d62a17ae 5108 }
5109 }
5110 }
5111 }
9bcb3eef
DS
5112 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5113 dest = bgp_route_next(dest)) {
5114 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5115 if (table != NULL) {
5116 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5117 bgp_table_finish(&table);
9bcb3eef
DS
5118 bgp_dest_set_bgp_table_info(dest, NULL);
5119 bgp_dest_unlock_node(dest);
d62a17ae 5120 }
bb86c601 5121 }
718e3744 5122}
5123
d62a17ae 5124void bgp_reset(void)
718e3744 5125{
d62a17ae 5126 vty_reset();
5127 bgp_zclient_reset();
5128 access_list_reset();
5129 prefix_list_reset();
718e3744 5130}
6b0655a2 5131
d62a17ae 5132static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5133{
d62a17ae 5134 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5135 && CHECK_FLAG(peer->af_cap[afi][safi],
5136 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5137}
5138
718e3744 5139/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5140 value. */
d62a17ae 5141int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5142 struct bgp_nlri *packet)
5143{
d7c0a89a
QY
5144 uint8_t *pnt;
5145 uint8_t *lim;
d62a17ae 5146 struct prefix p;
5147 int psize;
5148 int ret;
5149 afi_t afi;
5150 safi_t safi;
5151 int addpath_encoded;
d7c0a89a 5152 uint32_t addpath_id;
d62a17ae 5153
d62a17ae 5154 pnt = packet->nlri;
5155 lim = pnt + packet->length;
5156 afi = packet->afi;
5157 safi = packet->safi;
5158 addpath_id = 0;
5159 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5160
5161 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5162 syntactic validity. If the field is syntactically incorrect,
5163 then the Error Subcode is set to Invalid Network Field. */
5164 for (; pnt < lim; pnt += psize) {
5165 /* Clear prefix structure. */
5166 memset(&p, 0, sizeof(struct prefix));
5167
5168 if (addpath_encoded) {
5169
5170 /* When packet overflow occurs return immediately. */
761ed665 5171 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5172 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5173
a3a850a1 5174 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5175 addpath_id = ntohl(addpath_id);
d62a17ae 5176 pnt += BGP_ADDPATH_ID_LEN;
5177 }
718e3744 5178
d62a17ae 5179 /* Fetch prefix length. */
5180 p.prefixlen = *pnt++;
5181 /* afi/safi validity already verified by caller,
5182 * bgp_update_receive */
5183 p.family = afi2family(afi);
5184
5185 /* Prefix length check. */
5186 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5187 flog_err(
e50f7cfd 5188 EC_BGP_UPDATE_RCV,
14454c9f 5189 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5190 peer->host, p.prefixlen, packet->afi);
513386b5 5191 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5192 }
6b0655a2 5193
d62a17ae 5194 /* Packet size overflow check. */
5195 psize = PSIZE(p.prefixlen);
5196
5197 /* When packet overflow occur return immediately. */
5198 if (pnt + psize > lim) {
af4c2728 5199 flog_err(
e50f7cfd 5200 EC_BGP_UPDATE_RCV,
d62a17ae 5201 "%s [Error] Update packet error (prefix length %d overflows packet)",
5202 peer->host, p.prefixlen);
513386b5 5203 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5204 }
5205
5206 /* Defensive coding, double-check the psize fits in a struct
5207 * prefix */
5208 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5209 flog_err(
e50f7cfd 5210 EC_BGP_UPDATE_RCV,
d62a17ae 5211 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5212 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5213 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5214 }
5215
5216 /* Fetch prefix from NLRI packet. */
a85297a7 5217 memcpy(p.u.val, pnt, psize);
d62a17ae 5218
5219 /* Check address. */
5220 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5221 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5222 /* From RFC4271 Section 6.3:
5223 *
5224 * If a prefix in the NLRI field is semantically
5225 * incorrect
5226 * (e.g., an unexpected multicast IP address),
5227 * an error SHOULD
5228 * be logged locally, and the prefix SHOULD be
5229 * ignored.
a4d82a8a 5230 */
af4c2728 5231 flog_err(
e50f7cfd 5232 EC_BGP_UPDATE_RCV,
23d0a753
DA
5233 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5234 peer->host, &p.u.prefix4);
d62a17ae 5235 continue;
5236 }
5237 }
5238
5239 /* Check address. */
5240 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5241 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5242 char buf[BUFSIZ];
5243
af4c2728 5244 flog_err(
e50f7cfd 5245 EC_BGP_UPDATE_RCV,
d62a17ae 5246 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5247 peer->host,
5248 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5249 BUFSIZ));
5250
5251 continue;
5252 }
5253 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5254 char buf[BUFSIZ];
5255
af4c2728 5256 flog_err(
e50f7cfd 5257 EC_BGP_UPDATE_RCV,
d62a17ae 5258 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5259 peer->host,
5260 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5261 BUFSIZ));
5262
5263 continue;
5264 }
5265 }
5266
5267 /* Normal process. */
5268 if (attr)
5269 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5270 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5271 NULL, NULL, 0, 0, NULL);
d62a17ae 5272 else
5273 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5274 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5275 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5276 NULL);
d62a17ae 5277
513386b5
DA
5278 /* Do not send BGP notification twice when maximum-prefix count
5279 * overflow. */
5280 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5281 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5282
5283 /* Address family configuration mismatch. */
d62a17ae 5284 if (ret < 0)
513386b5 5285 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5286 }
5287
5288 /* Packet length consistency check. */
5289 if (pnt != lim) {
af4c2728 5290 flog_err(
e50f7cfd 5291 EC_BGP_UPDATE_RCV,
d62a17ae 5292 "%s [Error] Update packet error (prefix length mismatch with total length)",
5293 peer->host);
513386b5 5294 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5295 }
6b0655a2 5296
513386b5 5297 return BGP_NLRI_PARSE_OK;
718e3744 5298}
5299
d62a17ae 5300static struct bgp_static *bgp_static_new(void)
718e3744 5301{
d62a17ae 5302 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5303}
5304
d62a17ae 5305static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5306{
0a22ddfb 5307 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5308 route_map_counter_decrement(bgp_static->rmap.map);
5309
0a22ddfb 5310 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5311 XFREE(MTYPE_BGP_STATIC, bgp_static);
5312}
5313
5f040085 5314void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5315 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5316{
9bcb3eef 5317 struct bgp_dest *dest;
40381db7 5318 struct bgp_path_info *pi;
4b7e6066 5319 struct bgp_path_info *new;
40381db7 5320 struct bgp_path_info rmap_path;
d62a17ae 5321 struct attr attr;
5322 struct attr *attr_new;
b68885f9 5323 route_map_result_t ret;
49e5a4a0 5324#ifdef ENABLE_BGP_VNC
d62a17ae 5325 int vnc_implicit_withdraw = 0;
65efcfce 5326#endif
fee0f4c6 5327
d62a17ae 5328 assert(bgp_static);
dd8103a9 5329
9bcb3eef 5330 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5331
d62a17ae 5332 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5333
d62a17ae 5334 attr.nexthop = bgp_static->igpnexthop;
5335 attr.med = bgp_static->igpmetric;
5336 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5337
d62a17ae 5338 if (bgp_static->atomic)
5339 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5340
d62a17ae 5341 /* Store label index, if required. */
5342 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5343 attr.label_index = bgp_static->label_index;
5344 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5345 }
718e3744 5346
d62a17ae 5347 /* Apply route-map. */
5348 if (bgp_static->rmap.name) {
5349 struct attr attr_tmp = attr;
80ced710 5350
40381db7
DS
5351 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5352 rmap_path.peer = bgp->peer_self;
5353 rmap_path.attr = &attr_tmp;
fee0f4c6 5354
d62a17ae 5355 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5356
1782514f 5357 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5358
d62a17ae 5359 bgp->peer_self->rmap_type = 0;
718e3744 5360
d62a17ae 5361 if (ret == RMAP_DENYMATCH) {
5362 /* Free uninterned attribute. */
5363 bgp_attr_flush(&attr_tmp);
718e3744 5364
d62a17ae 5365 /* Unintern original. */
5366 aspath_unintern(&attr.aspath);
5367 bgp_static_withdraw(bgp, p, afi, safi);
5368 return;
5369 }
7f323236 5370
637e5ba4 5371 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5372 bgp_attr_add_gshut_community(&attr_tmp);
5373
d62a17ae 5374 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5375 } else {
5376
637e5ba4 5377 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5378 bgp_attr_add_gshut_community(&attr);
5379
d62a17ae 5380 attr_new = bgp_attr_intern(&attr);
7f323236 5381 }
718e3744 5382
9bcb3eef 5383 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5384 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5385 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5386 break;
5387
40381db7
DS
5388 if (pi) {
5389 if (attrhash_cmp(pi->attr, attr_new)
5390 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5391 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5392 bgp_dest_unlock_node(dest);
d62a17ae 5393 bgp_attr_unintern(&attr_new);
5394 aspath_unintern(&attr.aspath);
5395 return;
5396 } else {
5397 /* The attribute is changed. */
9bcb3eef 5398 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5399
5400 /* Rewrite BGP route information. */
40381db7 5401 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5402 bgp_path_info_restore(dest, pi);
d62a17ae 5403 else
40381db7 5404 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5405#ifdef ENABLE_BGP_VNC
d62a17ae 5406 if ((afi == AFI_IP || afi == AFI_IP6)
5407 && (safi == SAFI_UNICAST)) {
40381db7 5408 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5409 /*
5410 * Implicit withdraw case.
40381db7 5411 * We have to do this before pi is
d62a17ae 5412 * changed
5413 */
5414 ++vnc_implicit_withdraw;
40381db7 5415 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5416 vnc_import_bgp_exterior_del_route(
40381db7 5417 bgp, p, pi);
d62a17ae 5418 }
5419 }
65efcfce 5420#endif
40381db7
DS
5421 bgp_attr_unintern(&pi->attr);
5422 pi->attr = attr_new;
5423 pi->uptime = bgp_clock();
49e5a4a0 5424#ifdef ENABLE_BGP_VNC
d62a17ae 5425 if ((afi == AFI_IP || afi == AFI_IP6)
5426 && (safi == SAFI_UNICAST)) {
5427 if (vnc_implicit_withdraw) {
40381db7 5428 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5429 vnc_import_bgp_exterior_add_route(
40381db7 5430 bgp, p, pi);
d62a17ae 5431 }
5432 }
65efcfce 5433#endif
718e3744 5434
d62a17ae 5435 /* Nexthop reachability check. */
892fedb6 5436 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5437 && (safi == SAFI_UNICAST
5438 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5439
5440 struct bgp *bgp_nexthop = bgp;
5441
40381db7
DS
5442 if (pi->extra && pi->extra->bgp_orig)
5443 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5444
5445 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5446 afi, pi, NULL, 0))
9bcb3eef 5447 bgp_path_info_set_flag(dest, pi,
18ee8310 5448 BGP_PATH_VALID);
d62a17ae 5449 else {
5450 if (BGP_DEBUG(nht, NHT)) {
5451 char buf1[INET6_ADDRSTRLEN];
5452 inet_ntop(p->family,
5453 &p->u.prefix, buf1,
5454 INET6_ADDRSTRLEN);
5455 zlog_debug(
5456 "%s(%s): Route not in table, not advertising",
15569c58 5457 __func__, buf1);
d62a17ae 5458 }
18ee8310 5459 bgp_path_info_unset_flag(
9bcb3eef 5460 dest, pi, BGP_PATH_VALID);
d62a17ae 5461 }
5462 } else {
5463 /* Delete the NHT structure if any, if we're
5464 * toggling between
5465 * enabling/disabling import check. We
5466 * deregister the route
5467 * from NHT to avoid overloading NHT and the
5468 * process interaction
5469 */
40381db7 5470 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5471 bgp_path_info_set_flag(dest, pi,
5472 BGP_PATH_VALID);
d62a17ae 5473 }
5474 /* Process change. */
40381db7 5475 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5476 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5477
5478 if (SAFI_UNICAST == safi
5479 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5480 || bgp->inst_type
5481 == BGP_INSTANCE_TYPE_DEFAULT)) {
5482 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5483 pi);
ddb5b488
PZ
5484 }
5485
9bcb3eef 5486 bgp_dest_unlock_node(dest);
d62a17ae 5487 aspath_unintern(&attr.aspath);
5488 return;
5489 }
718e3744 5490 }
718e3744 5491
d62a17ae 5492 /* Make new BGP info. */
5493 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5494 attr_new, dest);
d62a17ae 5495 /* Nexthop reachability check. */
892fedb6 5496 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5497 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5498 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5499 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5500 else {
5501 if (BGP_DEBUG(nht, NHT)) {
5502 char buf1[INET6_ADDRSTRLEN];
5503 inet_ntop(p->family, &p->u.prefix, buf1,
5504 INET6_ADDRSTRLEN);
5505 zlog_debug(
5506 "%s(%s): Route not in table, not advertising",
15569c58 5507 __func__, buf1);
d62a17ae 5508 }
9bcb3eef 5509 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5510 }
5511 } else {
5512 /* Delete the NHT structure if any, if we're toggling between
5513 * enabling/disabling import check. We deregister the route
5514 * from NHT to avoid overloading NHT and the process interaction
5515 */
5516 bgp_unlink_nexthop(new);
5517
9bcb3eef 5518 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5519 }
078430f6 5520
d62a17ae 5521 /* Aggregate address increment. */
5522 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5523
d62a17ae 5524 /* Register new BGP information. */
9bcb3eef 5525 bgp_path_info_add(dest, new);
718e3744 5526
d62a17ae 5527 /* route_node_get lock */
9bcb3eef 5528 bgp_dest_unlock_node(dest);
d62a17ae 5529
5530 /* Process change. */
9bcb3eef 5531 bgp_process(bgp, dest, afi, safi);
d62a17ae 5532
ddb5b488
PZ
5533 if (SAFI_UNICAST == safi
5534 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5535 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5536 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5537 }
5538
d62a17ae 5539 /* Unintern original. */
5540 aspath_unintern(&attr.aspath);
718e3744 5541}
5542
5f040085 5543void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5544 safi_t safi)
718e3744 5545{
9bcb3eef 5546 struct bgp_dest *dest;
40381db7 5547 struct bgp_path_info *pi;
718e3744 5548
9bcb3eef 5549 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5550
d62a17ae 5551 /* Check selected route and self inserted route. */
9bcb3eef 5552 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5553 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5554 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5555 break;
5556
5557 /* Withdraw static BGP route from routing table. */
40381db7 5558 if (pi) {
ddb5b488
PZ
5559 if (SAFI_UNICAST == safi
5560 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5561 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5562 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5563 }
40381db7
DS
5564 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5565 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5566 bgp_path_info_delete(dest, pi);
5567 bgp_process(bgp, dest, afi, safi);
d62a17ae 5568 }
718e3744 5569
d62a17ae 5570 /* Unlock bgp_node_lookup. */
9bcb3eef 5571 bgp_dest_unlock_node(dest);
718e3744 5572}
5573
137446f9
LB
5574/*
5575 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5576 */
5f040085 5577static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5578 afi_t afi, safi_t safi,
5579 struct prefix_rd *prd)
718e3744 5580{
9bcb3eef 5581 struct bgp_dest *dest;
40381db7 5582 struct bgp_path_info *pi;
718e3744 5583
9bcb3eef 5584 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5585
d62a17ae 5586 /* Check selected route and self inserted route. */
9bcb3eef 5587 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5588 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5589 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5590 break;
718e3744 5591
d62a17ae 5592 /* Withdraw static BGP route from routing table. */
40381db7 5593 if (pi) {
49e5a4a0 5594#ifdef ENABLE_BGP_VNC
d62a17ae 5595 rfapiProcessWithdraw(
40381db7 5596 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5597 1); /* Kill, since it is an administrative change */
65efcfce 5598#endif
ddb5b488
PZ
5599 if (SAFI_MPLS_VPN == safi
5600 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5601 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5602 }
40381db7 5603 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5604 bgp_path_info_delete(dest, pi);
5605 bgp_process(bgp, dest, afi, safi);
d62a17ae 5606 }
718e3744 5607
d62a17ae 5608 /* Unlock bgp_node_lookup. */
9bcb3eef 5609 bgp_dest_unlock_node(dest);
718e3744 5610}
5611
5f040085 5612static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5613 struct bgp_static *bgp_static, afi_t afi,
5614 safi_t safi)
137446f9 5615{
9bcb3eef 5616 struct bgp_dest *dest;
4b7e6066 5617 struct bgp_path_info *new;
d62a17ae 5618 struct attr *attr_new;
5619 struct attr attr = {0};
40381db7 5620 struct bgp_path_info *pi;
49e5a4a0 5621#ifdef ENABLE_BGP_VNC
d62a17ae 5622 mpls_label_t label = 0;
65efcfce 5623#endif
d7c0a89a 5624 uint32_t num_labels = 0;
d62a17ae 5625 union gw_addr add;
137446f9 5626
d62a17ae 5627 assert(bgp_static);
137446f9 5628
b57ba6d2
MK
5629 if (bgp_static->label != MPLS_INVALID_LABEL)
5630 num_labels = 1;
9bcb3eef
DS
5631 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5632 &bgp_static->prd);
137446f9 5633
d62a17ae 5634 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5635
d62a17ae 5636 attr.nexthop = bgp_static->igpnexthop;
5637 attr.med = bgp_static->igpmetric;
5638 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5639
d62a17ae 5640 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5641 || (safi == SAFI_ENCAP)) {
5642 if (afi == AFI_IP) {
5643 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5644 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5645 }
5646 }
5647 if (afi == AFI_L2VPN) {
5648 if (bgp_static->gatewayIp.family == AF_INET)
5649 add.ipv4.s_addr =
5650 bgp_static->gatewayIp.u.prefix4.s_addr;
5651 else if (bgp_static->gatewayIp.family == AF_INET6)
5652 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5653 sizeof(struct in6_addr));
0a50c248 5654 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5655 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5656 struct bgp_encap_type_vxlan bet;
5657 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5658 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5659 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5660 }
5661 if (bgp_static->router_mac) {
5662 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5663 }
5664 }
5665 /* Apply route-map. */
5666 if (bgp_static->rmap.name) {
5667 struct attr attr_tmp = attr;
40381db7 5668 struct bgp_path_info rmap_path;
b68885f9 5669 route_map_result_t ret;
137446f9 5670
40381db7
DS
5671 rmap_path.peer = bgp->peer_self;
5672 rmap_path.attr = &attr_tmp;
137446f9 5673
d62a17ae 5674 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5675
1782514f 5676 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5677
d62a17ae 5678 bgp->peer_self->rmap_type = 0;
137446f9 5679
d62a17ae 5680 if (ret == RMAP_DENYMATCH) {
5681 /* Free uninterned attribute. */
5682 bgp_attr_flush(&attr_tmp);
137446f9 5683
d62a17ae 5684 /* Unintern original. */
5685 aspath_unintern(&attr.aspath);
5686 bgp_static_withdraw_safi(bgp, p, afi, safi,
5687 &bgp_static->prd);
5688 return;
5689 }
137446f9 5690
d62a17ae 5691 attr_new = bgp_attr_intern(&attr_tmp);
5692 } else {
5693 attr_new = bgp_attr_intern(&attr);
5694 }
137446f9 5695
9bcb3eef 5696 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5697 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5698 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5699 break;
5700
40381db7 5701 if (pi) {
d62a17ae 5702 memset(&add, 0, sizeof(union gw_addr));
40381db7 5703 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5704 && overlay_index_equal(afi, pi, &add)
40381db7 5705 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5706 bgp_dest_unlock_node(dest);
d62a17ae 5707 bgp_attr_unintern(&attr_new);
5708 aspath_unintern(&attr.aspath);
5709 return;
5710 } else {
5711 /* The attribute is changed. */
9bcb3eef 5712 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5713
5714 /* Rewrite BGP route information. */
40381db7 5715 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5716 bgp_path_info_restore(dest, pi);
d62a17ae 5717 else
40381db7
DS
5718 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5719 bgp_attr_unintern(&pi->attr);
5720 pi->attr = attr_new;
5721 pi->uptime = bgp_clock();
49e5a4a0 5722#ifdef ENABLE_BGP_VNC
40381db7
DS
5723 if (pi->extra)
5724 label = decode_label(&pi->extra->label[0]);
65efcfce 5725#endif
137446f9 5726
d62a17ae 5727 /* Process change. */
40381db7 5728 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5729 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5730
5731 if (SAFI_MPLS_VPN == safi
5732 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5733 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5734 }
49e5a4a0 5735#ifdef ENABLE_BGP_VNC
40381db7
DS
5736 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5737 pi->attr, afi, safi, pi->type,
5738 pi->sub_type, &label);
65efcfce 5739#endif
9bcb3eef 5740 bgp_dest_unlock_node(dest);
d62a17ae 5741 aspath_unintern(&attr.aspath);
5742 return;
5743 }
5744 }
137446f9
LB
5745
5746
d62a17ae 5747 /* Make new BGP info. */
5748 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5749 attr_new, dest);
1defdda8 5750 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5751 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5752 if (num_labels) {
5753 new->extra->label[0] = bgp_static->label;
5754 new->extra->num_labels = num_labels;
5755 }
49e5a4a0 5756#ifdef ENABLE_BGP_VNC
d62a17ae 5757 label = decode_label(&bgp_static->label);
65efcfce 5758#endif
137446f9 5759
d62a17ae 5760 /* Aggregate address increment. */
5761 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5762
d62a17ae 5763 /* Register new BGP information. */
9bcb3eef 5764 bgp_path_info_add(dest, new);
d62a17ae 5765 /* route_node_get lock */
9bcb3eef 5766 bgp_dest_unlock_node(dest);
137446f9 5767
d62a17ae 5768 /* Process change. */
9bcb3eef 5769 bgp_process(bgp, dest, afi, safi);
137446f9 5770
ddb5b488
PZ
5771 if (SAFI_MPLS_VPN == safi
5772 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5773 vpn_leak_to_vrf_update(bgp, new);
5774 }
49e5a4a0 5775#ifdef ENABLE_BGP_VNC
d62a17ae 5776 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5777 safi, new->type, new->sub_type, &label);
65efcfce
LB
5778#endif
5779
d62a17ae 5780 /* Unintern original. */
5781 aspath_unintern(&attr.aspath);
137446f9
LB
5782}
5783
718e3744 5784/* Configure static BGP network. When user don't run zebra, static
5785 route should be installed as valid. */
37a87b8f
CS
5786int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5787 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5788 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5789{
d62a17ae 5790 struct prefix p;
5791 struct bgp_static *bgp_static;
9bcb3eef 5792 struct bgp_dest *dest;
d7c0a89a 5793 uint8_t need_update = 0;
d62a17ae 5794
37a87b8f 5795 prefix_copy(&p, pfx);
d62a17ae 5796 apply_mask(&p);
718e3744 5797
e2a86ad9 5798 if (negate) {
718e3744 5799
e2a86ad9 5800 /* Set BGP static route configuration. */
9bcb3eef 5801 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5802
9bcb3eef 5803 if (!dest) {
37a87b8f
CS
5804 snprintf(errmsg, errmsg_len,
5805 "Can't find static route specified\n");
5806 return -1;
d62a17ae 5807 }
5808
9bcb3eef 5809 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5810
e2a86ad9
DS
5811 if ((label_index != BGP_INVALID_LABEL_INDEX)
5812 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5813 snprintf(errmsg, errmsg_len,
5814 "label-index doesn't match static route\n");
5815 return -1;
d62a17ae 5816 }
d62a17ae 5817
e2a86ad9
DS
5818 if ((rmap && bgp_static->rmap.name)
5819 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5820 snprintf(errmsg, errmsg_len,
5821 "route-map name doesn't match static route\n");
5822 return -1;
d62a17ae 5823 }
718e3744 5824
e2a86ad9
DS
5825 /* Update BGP RIB. */
5826 if (!bgp_static->backdoor)
5827 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5828
e2a86ad9
DS
5829 /* Clear configuration. */
5830 bgp_static_free(bgp_static);
9bcb3eef
DS
5831 bgp_dest_set_bgp_static_info(dest, NULL);
5832 bgp_dest_unlock_node(dest);
5833 bgp_dest_unlock_node(dest);
e2a86ad9 5834 } else {
718e3744 5835
e2a86ad9 5836 /* Set BGP static route configuration. */
9bcb3eef
DS
5837 dest = bgp_node_get(bgp->route[afi][safi], &p);
5838 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5839 if (bgp_static) {
e2a86ad9 5840 /* Configuration change. */
e2a86ad9
DS
5841 /* Label index cannot be changed. */
5842 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5843 snprintf(errmsg, errmsg_len,
5844 "cannot change label-index\n");
5845 return -1;
e2a86ad9 5846 }
d62a17ae 5847
e2a86ad9 5848 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5849 if (bgp_static->valid
5850 && bgp_static->backdoor != backdoor)
e2a86ad9 5851 need_update = 1;
718e3744 5852
e2a86ad9 5853 bgp_static->backdoor = backdoor;
718e3744 5854
e2a86ad9 5855 if (rmap) {
0a22ddfb
QY
5856 XFREE(MTYPE_ROUTE_MAP_NAME,
5857 bgp_static->rmap.name);
b4897fa5 5858 route_map_counter_decrement(
5859 bgp_static->rmap.map);
e2a86ad9
DS
5860 bgp_static->rmap.name =
5861 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5862 bgp_static->rmap.map =
5863 route_map_lookup_by_name(rmap);
b4897fa5 5864 route_map_counter_increment(
5865 bgp_static->rmap.map);
e2a86ad9 5866 } else {
0a22ddfb
QY
5867 XFREE(MTYPE_ROUTE_MAP_NAME,
5868 bgp_static->rmap.name);
b4897fa5 5869 route_map_counter_decrement(
5870 bgp_static->rmap.map);
e2a86ad9
DS
5871 bgp_static->rmap.map = NULL;
5872 bgp_static->valid = 0;
5873 }
9bcb3eef 5874 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5875 } else {
5876 /* New configuration. */
5877 bgp_static = bgp_static_new();
5878 bgp_static->backdoor = backdoor;
5879 bgp_static->valid = 0;
5880 bgp_static->igpmetric = 0;
975a328e 5881 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5882 bgp_static->label_index = label_index;
718e3744 5883
e2a86ad9 5884 if (rmap) {
0a22ddfb
QY
5885 XFREE(MTYPE_ROUTE_MAP_NAME,
5886 bgp_static->rmap.name);
b4897fa5 5887 route_map_counter_decrement(
5888 bgp_static->rmap.map);
e2a86ad9
DS
5889 bgp_static->rmap.name =
5890 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5891 bgp_static->rmap.map =
5892 route_map_lookup_by_name(rmap);
b4897fa5 5893 route_map_counter_increment(
5894 bgp_static->rmap.map);
e2a86ad9 5895 }
9bcb3eef 5896 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5897 }
d62a17ae 5898
e2a86ad9
DS
5899 bgp_static->valid = 1;
5900 if (need_update)
5901 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5902
e2a86ad9
DS
5903 if (!bgp_static->backdoor)
5904 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5905 }
d62a17ae 5906
37a87b8f 5907 return 0;
d62a17ae 5908}
5909
5910void bgp_static_add(struct bgp *bgp)
5911{
5912 afi_t afi;
5913 safi_t safi;
9bcb3eef
DS
5914 struct bgp_dest *dest;
5915 struct bgp_dest *rm;
d62a17ae 5916 struct bgp_table *table;
5917 struct bgp_static *bgp_static;
5918
05c7a1cc 5919 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5920 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5921 dest = bgp_route_next(dest)) {
5922 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5923 continue;
ea47320b 5924
05c7a1cc
QY
5925 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5926 || (safi == SAFI_EVPN)) {
9bcb3eef 5927 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5928
5929 for (rm = bgp_table_top(table); rm;
5930 rm = bgp_route_next(rm)) {
a78beeb5 5931 bgp_static =
9bcb3eef 5932 bgp_dest_get_bgp_static_info(
5a8ba9fc 5933 rm);
9bcb3eef
DS
5934 bgp_static_update_safi(
5935 bgp, bgp_dest_get_prefix(rm),
5936 bgp_static, afi, safi);
d62a17ae 5937 }
05c7a1cc 5938 } else {
5a8ba9fc 5939 bgp_static_update(
9bcb3eef
DS
5940 bgp, bgp_dest_get_prefix(dest),
5941 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5942 safi);
ea47320b 5943 }
05c7a1cc 5944 }
6aeb9e78
DS
5945}
5946
718e3744 5947/* Called from bgp_delete(). Delete all static routes from the BGP
5948 instance. */
d62a17ae 5949void bgp_static_delete(struct bgp *bgp)
5950{
5951 afi_t afi;
5952 safi_t safi;
9bcb3eef
DS
5953 struct bgp_dest *dest;
5954 struct bgp_dest *rm;
d62a17ae 5955 struct bgp_table *table;
5956 struct bgp_static *bgp_static;
5957
05c7a1cc 5958 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5959 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5960 dest = bgp_route_next(dest)) {
5961 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5962 continue;
ea47320b 5963
05c7a1cc
QY
5964 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5965 || (safi == SAFI_EVPN)) {
9bcb3eef 5966 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5967
5968 for (rm = bgp_table_top(table); rm;
5969 rm = bgp_route_next(rm)) {
a78beeb5 5970 bgp_static =
9bcb3eef 5971 bgp_dest_get_bgp_static_info(
5a8ba9fc 5972 rm);
c7d14ba6
PG
5973 if (!bgp_static)
5974 continue;
5975
05c7a1cc 5976 bgp_static_withdraw_safi(
9bcb3eef 5977 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5978 AFI_IP, safi,
5979 (struct prefix_rd *)
9bcb3eef
DS
5980 bgp_dest_get_prefix(
5981 dest));
ea47320b 5982 bgp_static_free(bgp_static);
811c6797 5983 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5984 NULL);
811c6797 5985 bgp_dest_unlock_node(rm);
d62a17ae 5986 }
05c7a1cc 5987 } else {
9bcb3eef 5988 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5989 bgp_static_withdraw(bgp,
9bcb3eef 5990 bgp_dest_get_prefix(dest),
b54892e0 5991 afi, safi);
05c7a1cc 5992 bgp_static_free(bgp_static);
9bcb3eef
DS
5993 bgp_dest_set_bgp_static_info(dest, NULL);
5994 bgp_dest_unlock_node(dest);
ea47320b 5995 }
05c7a1cc 5996 }
d62a17ae 5997}
5998
5999void bgp_static_redo_import_check(struct bgp *bgp)
6000{
6001 afi_t afi;
6002 safi_t safi;
9bcb3eef
DS
6003 struct bgp_dest *dest;
6004 struct bgp_dest *rm;
d62a17ae 6005 struct bgp_table *table;
6006 struct bgp_static *bgp_static;
6007
6008 /* Use this flag to force reprocessing of the route */
892fedb6 6009 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6010 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6011 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6012 dest = bgp_route_next(dest)) {
6013 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6014 continue;
ea47320b 6015
05c7a1cc
QY
6016 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6017 || (safi == SAFI_EVPN)) {
9bcb3eef 6018 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6019
6020 for (rm = bgp_table_top(table); rm;
6021 rm = bgp_route_next(rm)) {
a78beeb5 6022 bgp_static =
9bcb3eef 6023 bgp_dest_get_bgp_static_info(
5a8ba9fc 6024 rm);
9bcb3eef
DS
6025 bgp_static_update_safi(
6026 bgp, bgp_dest_get_prefix(rm),
6027 bgp_static, afi, safi);
d62a17ae 6028 }
05c7a1cc 6029 } else {
9bcb3eef
DS
6030 bgp_static = bgp_dest_get_bgp_static_info(dest);
6031 bgp_static_update(bgp,
6032 bgp_dest_get_prefix(dest),
6033 bgp_static, afi, safi);
ea47320b 6034 }
05c7a1cc
QY
6035 }
6036 }
892fedb6 6037 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6038}
6039
6040static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6041 safi_t safi)
6042{
6043 struct bgp_table *table;
9bcb3eef 6044 struct bgp_dest *dest;
40381db7 6045 struct bgp_path_info *pi;
d62a17ae 6046
dfb6fd1d
NT
6047 /* Do not install the aggregate route if BGP is in the
6048 * process of termination.
6049 */
892fedb6
DA
6050 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6051 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6052 return;
6053
d62a17ae 6054 table = bgp->rib[afi][safi];
9bcb3eef
DS
6055 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6056 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6057 if (pi->peer == bgp->peer_self
6058 && ((pi->type == ZEBRA_ROUTE_BGP
6059 && pi->sub_type == BGP_ROUTE_STATIC)
6060 || (pi->type != ZEBRA_ROUTE_BGP
6061 && pi->sub_type
d62a17ae 6062 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6063 bgp_aggregate_decrement(
6064 bgp, bgp_dest_get_prefix(dest), pi, afi,
6065 safi);
40381db7 6066 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6067 bgp_path_info_delete(dest, pi);
6068 bgp_process(bgp, dest, afi, safi);
d62a17ae 6069 }
6070 }
6071 }
ad4cbda1 6072}
6073
6074/*
6075 * Purge all networks and redistributed routes from routing table.
6076 * Invoked upon the instance going down.
6077 */
d62a17ae 6078void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6079{
d62a17ae 6080 afi_t afi;
6081 safi_t safi;
ad4cbda1 6082
05c7a1cc
QY
6083 FOREACH_AFI_SAFI (afi, safi)
6084 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6085}
6086
137446f9
LB
6087/*
6088 * gpz 110624
6089 * Currently this is used to set static routes for VPN and ENCAP.
6090 * I think it can probably be factored with bgp_static_set.
6091 */
d62a17ae 6092int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6093 const char *ip_str, const char *rd_str,
6094 const char *label_str, const char *rmap_str,
6095 int evpn_type, const char *esi, const char *gwip,
6096 const char *ethtag, const char *routermac)
6097{
6098 VTY_DECLVAR_CONTEXT(bgp, bgp);
6099 int ret;
6100 struct prefix p;
6101 struct prefix_rd prd;
9bcb3eef
DS
6102 struct bgp_dest *pdest;
6103 struct bgp_dest *dest;
d62a17ae 6104 struct bgp_table *table;
6105 struct bgp_static *bgp_static;
6106 mpls_label_t label = MPLS_INVALID_LABEL;
6107 struct prefix gw_ip;
6108
6109 /* validate ip prefix */
6110 ret = str2prefix(ip_str, &p);
6111 if (!ret) {
6112 vty_out(vty, "%% Malformed prefix\n");
6113 return CMD_WARNING_CONFIG_FAILED;
6114 }
6115 apply_mask(&p);
6116 if ((afi == AFI_L2VPN)
6117 && (bgp_build_evpn_prefix(evpn_type,
6118 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6119 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6120 return CMD_WARNING_CONFIG_FAILED;
6121 }
718e3744 6122
d62a17ae 6123 ret = str2prefix_rd(rd_str, &prd);
6124 if (!ret) {
6125 vty_out(vty, "%% Malformed rd\n");
6126 return CMD_WARNING_CONFIG_FAILED;
6127 }
718e3744 6128
d62a17ae 6129 if (label_str) {
6130 unsigned long label_val;
6131 label_val = strtoul(label_str, NULL, 10);
6132 encode_label(label_val, &label);
6133 }
9bedbb1e 6134
d62a17ae 6135 if (safi == SAFI_EVPN) {
6136 if (esi && str2esi(esi, NULL) == 0) {
6137 vty_out(vty, "%% Malformed ESI\n");
6138 return CMD_WARNING_CONFIG_FAILED;
6139 }
6140 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6141 vty_out(vty, "%% Malformed Router MAC\n");
6142 return CMD_WARNING_CONFIG_FAILED;
6143 }
6144 if (gwip) {
6145 memset(&gw_ip, 0, sizeof(struct prefix));
6146 ret = str2prefix(gwip, &gw_ip);
6147 if (!ret) {
6148 vty_out(vty, "%% Malformed GatewayIp\n");
6149 return CMD_WARNING_CONFIG_FAILED;
6150 }
6151 if ((gw_ip.family == AF_INET
3714a385 6152 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6153 (struct prefix_evpn *)&p))
6154 || (gw_ip.family == AF_INET6
3714a385 6155 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6156 (struct prefix_evpn *)&p))) {
6157 vty_out(vty,
6158 "%% GatewayIp family differs with IP prefix\n");
6159 return CMD_WARNING_CONFIG_FAILED;
6160 }
6161 }
6162 }
9bcb3eef
DS
6163 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6164 if (!bgp_dest_has_bgp_path_info_data(pdest))
6165 bgp_dest_set_bgp_table_info(pdest,
67009e22 6166 bgp_table_init(bgp, afi, safi));
9bcb3eef 6167 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6168
9bcb3eef 6169 dest = bgp_node_get(table, &p);
d62a17ae 6170
9bcb3eef 6171 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6172 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6173 bgp_dest_unlock_node(dest);
d62a17ae 6174 } else {
6175 /* New configuration. */
6176 bgp_static = bgp_static_new();
6177 bgp_static->backdoor = 0;
6178 bgp_static->valid = 0;
6179 bgp_static->igpmetric = 0;
975a328e 6180 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6181 bgp_static->label = label;
6182 bgp_static->prd = prd;
6183
6184 if (rmap_str) {
0a22ddfb 6185 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6186 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6187 bgp_static->rmap.name =
6188 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6189 bgp_static->rmap.map =
6190 route_map_lookup_by_name(rmap_str);
b4897fa5 6191 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6192 }
718e3744 6193
d62a17ae 6194 if (safi == SAFI_EVPN) {
6195 if (esi) {
6196 bgp_static->eth_s_id =
6197 XCALLOC(MTYPE_ATTR,
0a50c248 6198 sizeof(esi_t));
d62a17ae 6199 str2esi(esi, bgp_static->eth_s_id);
6200 }
6201 if (routermac) {
6202 bgp_static->router_mac =
28328ea9 6203 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6204 (void)prefix_str2mac(routermac,
6205 bgp_static->router_mac);
d62a17ae 6206 }
6207 if (gwip)
6208 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6209 }
9bcb3eef 6210 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6211
d62a17ae 6212 bgp_static->valid = 1;
6213 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6214 }
718e3744 6215
d62a17ae 6216 return CMD_SUCCESS;
718e3744 6217}
6218
6219/* Configure static BGP network. */
d62a17ae 6220int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6221 const char *ip_str, const char *rd_str,
6222 const char *label_str, int evpn_type, const char *esi,
6223 const char *gwip, const char *ethtag)
6224{
6225 VTY_DECLVAR_CONTEXT(bgp, bgp);
6226 int ret;
6227 struct prefix p;
6228 struct prefix_rd prd;
9bcb3eef
DS
6229 struct bgp_dest *pdest;
6230 struct bgp_dest *dest;
d62a17ae 6231 struct bgp_table *table;
6232 struct bgp_static *bgp_static;
6233 mpls_label_t label = MPLS_INVALID_LABEL;
6234
6235 /* Convert IP prefix string to struct prefix. */
6236 ret = str2prefix(ip_str, &p);
6237 if (!ret) {
6238 vty_out(vty, "%% Malformed prefix\n");
6239 return CMD_WARNING_CONFIG_FAILED;
6240 }
6241 apply_mask(&p);
6242 if ((afi == AFI_L2VPN)
6243 && (bgp_build_evpn_prefix(evpn_type,
6244 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6245 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6246 return CMD_WARNING_CONFIG_FAILED;
6247 }
6248 ret = str2prefix_rd(rd_str, &prd);
6249 if (!ret) {
6250 vty_out(vty, "%% Malformed rd\n");
6251 return CMD_WARNING_CONFIG_FAILED;
6252 }
718e3744 6253
d62a17ae 6254 if (label_str) {
6255 unsigned long label_val;
6256 label_val = strtoul(label_str, NULL, 10);
6257 encode_label(label_val, &label);
6258 }
718e3744 6259
9bcb3eef
DS
6260 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6261 if (!bgp_dest_has_bgp_path_info_data(pdest))
6262 bgp_dest_set_bgp_table_info(pdest,
67009e22 6263 bgp_table_init(bgp, afi, safi));
d62a17ae 6264 else
9bcb3eef
DS
6265 bgp_dest_unlock_node(pdest);
6266 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6267
9bcb3eef 6268 dest = bgp_node_lookup(table, &p);
6b0655a2 6269
9bcb3eef 6270 if (dest) {
d62a17ae 6271 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6272
9bcb3eef 6273 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6274 bgp_static_free(bgp_static);
9bcb3eef
DS
6275 bgp_dest_set_bgp_static_info(dest, NULL);
6276 bgp_dest_unlock_node(dest);
6277 bgp_dest_unlock_node(dest);
d62a17ae 6278 } else
6279 vty_out(vty, "%% Can't find the route\n");
6280
6281 return CMD_SUCCESS;
6282}
6283
6284static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6285 const char *rmap_name)
6286{
6287 VTY_DECLVAR_CONTEXT(bgp, bgp);
6288 struct bgp_rmap *rmap;
6289
6290 rmap = &bgp->table_map[afi][safi];
6291 if (rmap_name) {
0a22ddfb 6292 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6293 route_map_counter_decrement(rmap->map);
d62a17ae 6294 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6295 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6296 route_map_counter_increment(rmap->map);
d62a17ae 6297 } else {
0a22ddfb 6298 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6299 route_map_counter_decrement(rmap->map);
d62a17ae 6300 rmap->map = NULL;
6301 }
73ac8160 6302
d62a17ae 6303 if (bgp_fibupd_safi(safi))
6304 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6305
d62a17ae 6306 return CMD_SUCCESS;
73ac8160
DS
6307}
6308
d62a17ae 6309static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6310 const char *rmap_name)
73ac8160 6311{
d62a17ae 6312 VTY_DECLVAR_CONTEXT(bgp, bgp);
6313 struct bgp_rmap *rmap;
73ac8160 6314
d62a17ae 6315 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6316 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6317 route_map_counter_decrement(rmap->map);
d62a17ae 6318 rmap->map = NULL;
73ac8160 6319
d62a17ae 6320 if (bgp_fibupd_safi(safi))
6321 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6322
d62a17ae 6323 return CMD_SUCCESS;
73ac8160
DS
6324}
6325
2b791107 6326void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6327 safi_t safi)
73ac8160 6328{
d62a17ae 6329 if (bgp->table_map[afi][safi].name) {
d62a17ae 6330 vty_out(vty, " table-map %s\n",
6331 bgp->table_map[afi][safi].name);
6332 }
73ac8160
DS
6333}
6334
73ac8160
DS
6335DEFUN (bgp_table_map,
6336 bgp_table_map_cmd,
6337 "table-map WORD",
6338 "BGP table to RIB route download filter\n"
6339 "Name of the route map\n")
6340{
d62a17ae 6341 int idx_word = 1;
6342 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6343 argv[idx_word]->arg);
73ac8160
DS
6344}
6345DEFUN (no_bgp_table_map,
6346 no_bgp_table_map_cmd,
6347 "no table-map WORD",
3a2d747c 6348 NO_STR
73ac8160
DS
6349 "BGP table to RIB route download filter\n"
6350 "Name of the route map\n")
6351{
d62a17ae 6352 int idx_word = 2;
6353 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6354 argv[idx_word]->arg);
73ac8160
DS
6355}
6356
37a87b8f
CS
6357DEFPY_YANG (bgp_network, bgp_network_cmd,
6358 "[no] network \
6359 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6360 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6361 backdoor$backdoor}]",
6362 NO_STR
6363 "Specify a network to announce via BGP\n"
6364 "IPv4 prefix\n"
6365 "Network number\n"
6366 "Network mask\n"
6367 "Network mask\n"
6368 "Route-map to modify the attributes\n"
6369 "Name of the route map\n"
6370 "Label index to associate with the prefix\n"
6371 "Label index value\n"
6372 "Specify a BGP backdoor route\n")
6373{
6374 char addr_prefix_str[PREFIX_STRLEN];
6375 char base_xpath[XPATH_MAXLEN];
6376 afi_t afi;
6377 safi_t safi;
e2a86ad9
DS
6378
6379 if (address_str) {
6380 int ret;
718e3744 6381
e2a86ad9
DS
6382 ret = netmask_str2prefix_str(address_str, netmask_str,
6383 addr_prefix_str);
6384 if (!ret) {
6385 vty_out(vty, "%% Inconsistent address and mask\n");
6386 return CMD_WARNING_CONFIG_FAILED;
6387 }
d62a17ae 6388 }
718e3744 6389
37a87b8f
CS
6390 afi = bgp_node_afi(vty);
6391 safi = bgp_node_safi(vty);
6392
6393 if (no) {
6394 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6395 } else {
6396 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6397
6398 if (map_name)
6399 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6400 NB_OP_CREATE, map_name);
6401 else
6402 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6403 NB_OP_DESTROY, NULL);
6404
6405 if (label_index_str)
6406 nb_cli_enqueue_change(vty, "./label-index",
6407 NB_OP_MODIFY, label_index_str);
6408
6409 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6410 backdoor ? "true" : "false");
6411 }
6412
6413 snprintf(
6414 base_xpath, sizeof(base_xpath),
6415 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6416 yang_afi_safi_value2identity(afi, safi),
6417 bgp_afi_safi_get_container_str(afi, safi),
6418 address_str ? addr_prefix_str : prefix_str);
6419
6420 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6421}
6422
37a87b8f
CS
6423DEFPY_YANG (ipv6_bgp_network,
6424 ipv6_bgp_network_cmd,
6425 "[no] network X:X::X:X/M$prefix \
6426 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6427 NO_STR
6428 "Specify a network to announce via BGP\n"
6429 "IPv6 prefix\n"
6430 "Route-map to modify the attributes\n"
6431 "Name of the route map\n"
6432 "Label index to associate with the prefix\n"
6433 "Label index value\n")
6434{
6435 char base_xpath[XPATH_MAXLEN];
6436 afi_t afi;
6437 safi_t safi;
6438
6439 afi = bgp_node_afi(vty);
6440 safi = bgp_node_safi(vty);
6441
6442 if (no) {
6443 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6444 } else {
6445 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6446
6447 if (map_name)
6448 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6449 NB_OP_MODIFY, map_name);
6450 else
6451 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6452 NB_OP_DESTROY, NULL);
6453
6454 if (label_index_str)
6455 nb_cli_enqueue_change(vty, "./label-index",
6456 NB_OP_MODIFY, label_index_str);
6457 }
6458
6459 snprintf(
6460 base_xpath, sizeof(base_xpath),
6461 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6462 yang_afi_safi_value2identity(afi, safi),
6463 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6464
6465 return nb_cli_apply_changes(vty, base_xpath);
6466}
6467
6468void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6469 struct lyd_node *dnode,
6470 bool show_defaults)
718e3744 6471{
37a87b8f
CS
6472 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6473
6474 if (yang_dnode_exists(dnode, "./label-index"))
6475 vty_out(vty, " label-index %s",
6476 yang_dnode_get_string(dnode, "./label-index"));
6477
6478 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6479 vty_out(vty, " route-map %s",
6480 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6481
6482 if (yang_dnode_get_bool(dnode, "./backdoor"))
6483 vty_out(vty, " backdoor");
6484
6485 vty_out(vty, "\n");
1b6d5c7e
VV
6486}
6487
d62a17ae 6488static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6489{
d62a17ae 6490 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6491}
6492
d62a17ae 6493static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6494{
365ab2e7
RZ
6495 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6496 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6497 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6498 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6499 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6500}
718e3744 6501
365ab2e7
RZ
6502/**
6503 * Helper function to avoid repeated code: prepare variables for a
6504 * `route_map_apply` call.
6505 *
6506 * \returns `true` on route map match, otherwise `false`.
6507 */
6508static bool aggr_suppress_map_test(struct bgp *bgp,
6509 struct bgp_aggregate *aggregate,
6510 struct bgp_path_info *pi)
6511{
6512 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6513 route_map_result_t rmr = RMAP_DENYMATCH;
6514 struct bgp_path_info rmap_path = {};
6515 struct attr attr = {};
6516
6517 /* No route map entries created, just don't match. */
6518 if (aggregate->suppress_map == NULL)
6519 return false;
6520
6521 /* Call route map matching and return result. */
6522 attr.aspath = aspath_empty();
6523 rmap_path.peer = bgp->peer_self;
6524 rmap_path.attr = &attr;
6525
6526 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6527 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6528 bgp->peer_self->rmap_type = 0;
6529
6530 bgp_attr_flush(&attr);
6531
6532 return rmr == RMAP_PERMITMATCH;
6533}
6534
4056a5f6
RZ
6535/** Test whether the aggregation has suppressed this path or not. */
6536static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6537 struct bgp_path_info *pi)
6538{
6539 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6540 return false;
6541
6542 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6543}
6544
6545/**
6546 * Suppress this path and keep the reference.
6547 *
6548 * \returns `true` if needs processing otherwise `false`.
6549 */
6550static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6551 struct bgp_path_info *pi)
6552{
6553 struct bgp_path_info_extra *pie;
6554
6555 /* Path is already suppressed by this aggregation. */
6556 if (aggr_suppress_exists(aggregate, pi))
6557 return false;
6558
6559 pie = bgp_path_info_extra_get(pi);
6560
6561 /* This is the first suppression, allocate memory and list it. */
6562 if (pie->aggr_suppressors == NULL)
6563 pie->aggr_suppressors = list_new();
6564
6565 listnode_add(pie->aggr_suppressors, aggregate);
6566
6567 /* Only mark for processing if suppressed. */
6568 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6569 if (BGP_DEBUG(update, UPDATE_OUT))
6570 zlog_debug("aggregate-address suppressing: %pFX",
6571 bgp_dest_get_prefix(pi->net));
6572
4056a5f6
RZ
6573 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6574 return true;
6575 }
6576
6577 return false;
6578}
6579
6580/**
6581 * Unsuppress this path and remove the reference.
6582 *
6583 * \returns `true` if needs processing otherwise `false`.
6584 */
6585static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6586 struct bgp_path_info *pi)
6587{
6588 /* Path wasn't suppressed. */
6589 if (!aggr_suppress_exists(aggregate, pi))
6590 return false;
6591
6592 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6593
6594 /* Unsuppress and free extra memory if last item. */
6595 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6596 if (BGP_DEBUG(update, UPDATE_OUT))
6597 zlog_debug("aggregate-address unsuppressing: %pFX",
6598 bgp_dest_get_prefix(pi->net));
6599
4056a5f6
RZ
6600 list_delete(&pi->extra->aggr_suppressors);
6601 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6602 return true;
6603 }
6604
6605 return false;
6606}
6607
3dc339cd
DA
6608static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6609 struct aspath *aspath,
6610 struct community *comm,
6611 struct ecommunity *ecomm,
6612 struct lcommunity *lcomm)
eaaf8adb
DS
6613{
6614 static struct aspath *ae = NULL;
6615
6616 if (!ae)
6617 ae = aspath_empty();
6618
40381db7 6619 if (!pi)
3dc339cd 6620 return false;
eaaf8adb 6621
40381db7 6622 if (origin != pi->attr->origin)
3dc339cd 6623 return false;
eaaf8adb 6624
40381db7 6625 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6626 return false;
29f7d023 6627
40381db7 6628 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6629 return false;
eaaf8adb 6630
3da2cc32 6631 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6632 return false;
eaaf8adb 6633
dd18c5a9 6634 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6635 return false;
dd18c5a9 6636
40381db7 6637 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6638 return false;
7ce8a8e0 6639
3dc339cd 6640 return true;
eaaf8adb
DS
6641}
6642
5f040085
DS
6643static void bgp_aggregate_install(
6644 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6645 uint8_t origin, struct aspath *aspath, struct community *community,
6646 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6647 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6648{
9bcb3eef 6649 struct bgp_dest *dest;
c701010e 6650 struct bgp_table *table;
6f94b685 6651 struct bgp_path_info *pi, *orig, *new;
20894f50 6652 struct attr *attr;
c701010e
DS
6653
6654 table = bgp->rib[afi][safi];
6655
9bcb3eef 6656 dest = bgp_node_get(table, p);
eaaf8adb 6657
9bcb3eef 6658 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6659 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6660 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6661 break;
6662
6aabb15d
RZ
6663 /*
6664 * If we have paths with different MEDs, then don't install
6665 * (or uninstall) the aggregate route.
6666 */
6667 if (aggregate->match_med && aggregate->med_mismatched)
6668 goto uninstall_aggregate_route;
6669
c701010e 6670 if (aggregate->count > 0) {
eaaf8adb
DS
6671 /*
6672 * If the aggregate information has not changed
6673 * no need to re-install it again.
6674 */
6f94b685 6675 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6676 ecommunity, lcommunity)) {
9bcb3eef 6677 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6678
6679 if (aspath)
6680 aspath_free(aspath);
6681 if (community)
3c1f53de 6682 community_free(&community);
3da2cc32
DS
6683 if (ecommunity)
6684 ecommunity_free(&ecommunity);
dd18c5a9
DS
6685 if (lcommunity)
6686 lcommunity_free(&lcommunity);
eaaf8adb
DS
6687
6688 return;
6689 }
6690
6691 /*
6692 * Mark the old as unusable
6693 */
40381db7 6694 if (pi)
9bcb3eef 6695 bgp_path_info_delete(dest, pi);
eaaf8adb 6696
20894f50
DA
6697 attr = bgp_attr_aggregate_intern(
6698 bgp, origin, aspath, community, ecommunity, lcommunity,
6699 aggregate, atomic_aggregate, p);
6700
6701 if (!attr) {
6702 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6703 return;
6704 }
6705
3da2cc32 6706 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6707 bgp->peer_self, attr, dest);
20894f50 6708
1defdda8 6709 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6710
9bcb3eef
DS
6711 bgp_path_info_add(dest, new);
6712 bgp_process(bgp, dest, afi, safi);
c701010e 6713 } else {
6aabb15d 6714 uninstall_aggregate_route:
6f94b685 6715 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6716 if (pi->peer == bgp->peer_self
6717 && pi->type == ZEBRA_ROUTE_BGP
6718 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6719 break;
6720
6721 /* Withdraw static BGP route from routing table. */
40381db7 6722 if (pi) {
9bcb3eef
DS
6723 bgp_path_info_delete(dest, pi);
6724 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6725 }
6726 }
6727
9bcb3eef 6728 bgp_dest_unlock_node(dest);
c701010e
DS
6729}
6730
6aabb15d
RZ
6731/**
6732 * Check if the current path has different MED than other known paths.
6733 *
6734 * \returns `true` if the MED matched the others else `false`.
6735 */
6736static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6737 struct bgp *bgp, struct bgp_path_info *pi)
6738{
6739 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6740
6741 /* This is the first route being analyzed. */
6742 if (!aggregate->med_initialized) {
6743 aggregate->med_initialized = true;
6744 aggregate->med_mismatched = false;
6745 aggregate->med_matched_value = cur_med;
6746 } else {
6747 /* Check if routes with different MED showed up. */
6748 if (cur_med != aggregate->med_matched_value)
6749 aggregate->med_mismatched = true;
6750 }
6751
6752 return !aggregate->med_mismatched;
6753}
6754
6755/**
6756 * Initializes and tests all routes in the aggregate address path for MED
6757 * values.
6758 *
6759 * \returns `true` if all MEDs are the same otherwise `false`.
6760 */
6761static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6762 struct bgp *bgp, const struct prefix *p,
6763 afi_t afi, safi_t safi)
6764{
6765 struct bgp_table *table = bgp->rib[afi][safi];
6766 const struct prefix *dest_p;
6767 struct bgp_dest *dest, *top;
6768 struct bgp_path_info *pi;
6769 bool med_matched = true;
6770
6771 aggregate->med_initialized = false;
6772
6773 top = bgp_node_get(table, p);
6774 for (dest = bgp_node_get(table, p); dest;
6775 dest = bgp_route_next_until(dest, top)) {
6776 dest_p = bgp_dest_get_prefix(dest);
6777 if (dest_p->prefixlen <= p->prefixlen)
6778 continue;
6779
6780 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6781 if (BGP_PATH_HOLDDOWN(pi))
6782 continue;
6783 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6784 continue;
6785 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6786 med_matched = false;
6787 break;
6788 }
6789 }
6790 if (!med_matched)
6791 break;
6792 }
6793 bgp_dest_unlock_node(top);
6794
6795 return med_matched;
6796}
6797
6798/**
6799 * Toggles the route suppression status for this aggregate address
6800 * configuration.
6801 */
4056a5f6
RZ
6802void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6803 struct bgp *bgp, const struct prefix *p,
6804 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6805{
6806 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6807 const struct prefix *dest_p;
6808 struct bgp_dest *dest, *top;
6809 struct bgp_path_info *pi;
6810 bool toggle_suppression;
6811
6812 /* We've found a different MED we must revert any suppressed routes. */
6813 top = bgp_node_get(table, p);
6814 for (dest = bgp_node_get(table, p); dest;
6815 dest = bgp_route_next_until(dest, top)) {
6816 dest_p = bgp_dest_get_prefix(dest);
6817 if (dest_p->prefixlen <= p->prefixlen)
6818 continue;
6819
6820 toggle_suppression = false;
6821 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6822 if (BGP_PATH_HOLDDOWN(pi))
6823 continue;
6824 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6825 continue;
6826
6aabb15d
RZ
6827 /* We are toggling suppression back. */
6828 if (suppress) {
6aabb15d 6829 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6830 if (aggr_suppress_path(aggregate, pi))
6831 toggle_suppression = true;
6aabb15d
RZ
6832 continue;
6833 }
6834
6aabb15d 6835 /* Install route if there is no more suppression. */
4056a5f6 6836 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6837 toggle_suppression = true;
6aabb15d
RZ
6838 }
6839
6840 if (toggle_suppression)
6841 bgp_process(bgp, dest, afi, safi);
6842 }
6843 bgp_dest_unlock_node(top);
6844}
6845
6846/**
6847 * Aggregate address MED matching incremental test: this function is called
6848 * when the initial aggregation occurred and we are only testing a single
6849 * new path.
6850 *
6851 * In addition to testing and setting the MED validity it also installs back
6852 * suppressed routes (if summary is configured).
6853 *
6854 * Must not be called in `bgp_aggregate_route`.
6855 */
6856static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6857 struct bgp *bgp, const struct prefix *p,
6858 afi_t afi, safi_t safi,
6859 struct bgp_path_info *pi, bool is_adding)
6860{
6861 /* MED matching disabled. */
6862 if (!aggregate->match_med)
6863 return;
6864
6865 /* Aggregation with different MED, nothing to do. */
6866 if (aggregate->med_mismatched)
6867 return;
6868
6869 /*
6870 * Test the current entry:
6871 *
6872 * is_adding == true: if the new entry doesn't match then we must
6873 * install all suppressed routes.
6874 *
6875 * is_adding == false: if the entry being removed was the last
6876 * unmatching entry then we can suppress all routes.
6877 */
6878 if (!is_adding) {
6879 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6880 && aggregate->summary_only)
6881 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6882 safi, true);
6883 } else
6884 bgp_aggregate_med_match(aggregate, bgp, pi);
6885
6886 /* No mismatches, just quit. */
6887 if (!aggregate->med_mismatched)
6888 return;
6889
6890 /* Route summarization is disabled. */
6891 if (!aggregate->summary_only)
6892 return;
6893
6894 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6895}
6896
b5d58c32 6897/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6898void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6899 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6900{
6901 struct bgp_table *table;
9bcb3eef
DS
6902 struct bgp_dest *top;
6903 struct bgp_dest *dest;
d7c0a89a 6904 uint8_t origin;
d62a17ae 6905 struct aspath *aspath = NULL;
d62a17ae 6906 struct community *community = NULL;
3da2cc32 6907 struct ecommunity *ecommunity = NULL;
dd18c5a9 6908 struct lcommunity *lcommunity = NULL;
40381db7 6909 struct bgp_path_info *pi;
d62a17ae 6910 unsigned long match = 0;
d7c0a89a 6911 uint8_t atomic_aggregate = 0;
d62a17ae 6912
9f822fa2
S
6913 /* If the bgp instance is being deleted or self peer is deleted
6914 * then do not create aggregate route
6915 */
892fedb6
DA
6916 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6917 || (bgp->peer_self == NULL))
9f822fa2
S
6918 return;
6919
6aabb15d
RZ
6920 /* Initialize and test routes for MED difference. */
6921 if (aggregate->match_med)
6922 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6923
4056a5f6
RZ
6924 /*
6925 * Reset aggregate count: we might've been called from route map
6926 * update so in that case we must retest all more specific routes.
6927 *
6928 * \see `bgp_route_map_process_update`.
6929 */
6930 aggregate->count = 0;
6931 aggregate->incomplete_origin_count = 0;
6932 aggregate->incomplete_origin_count = 0;
6933 aggregate->egp_origin_count = 0;
6934
d62a17ae 6935 /* ORIGIN attribute: If at least one route among routes that are
6936 aggregated has ORIGIN with the value INCOMPLETE, then the
6937 aggregated route must have the ORIGIN attribute with the value
6938 INCOMPLETE. Otherwise, if at least one route among routes that
6939 are aggregated has ORIGIN with the value EGP, then the aggregated
6940 route must have the origin attribute with the value EGP. In all
6941 other case the value of the ORIGIN attribute of the aggregated
6942 route is INTERNAL. */
6943 origin = BGP_ORIGIN_IGP;
718e3744 6944
d62a17ae 6945 table = bgp->rib[afi][safi];
718e3744 6946
d62a17ae 6947 top = bgp_node_get(table, p);
9bcb3eef
DS
6948 for (dest = bgp_node_get(table, p); dest;
6949 dest = bgp_route_next_until(dest, top)) {
6950 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6951
9bcb3eef 6952 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6953 continue;
d62a17ae 6954
a77e2f4b
S
6955 /* If suppress fib is enabled and route not installed
6956 * in FIB, skip the route
6957 */
6958 if (!bgp_check_advertise(bgp, dest))
6959 continue;
6960
c2ff8b3e 6961 match = 0;
d62a17ae 6962
9bcb3eef 6963 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6964 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6965 continue;
718e3744 6966
40381db7 6967 if (pi->attr->flag
c2ff8b3e
DS
6968 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6969 atomic_aggregate = 1;
d62a17ae 6970
40381db7 6971 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6972 continue;
d62a17ae 6973
f273fef1
DS
6974 /*
6975 * summary-only aggregate route suppress
6976 * aggregated route announcements.
6aabb15d
RZ
6977 *
6978 * MED matching:
6979 * Don't create summaries if MED didn't match
6980 * otherwise neither the specific routes and the
6981 * aggregation will be announced.
f273fef1 6982 */
6aabb15d
RZ
6983 if (aggregate->summary_only
6984 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6985 if (aggr_suppress_path(aggregate, pi))
6986 match++;
d62a17ae 6987 }
c2ff8b3e 6988
365ab2e7
RZ
6989 /*
6990 * Suppress more specific routes that match the route
6991 * map results.
6992 *
6993 * MED matching:
6994 * Don't suppress routes if MED matching is enabled and
6995 * it mismatched otherwise we might end up with no
6996 * routes for this path.
6997 */
6998 if (aggregate->suppress_map_name
6999 && AGGREGATE_MED_VALID(aggregate)
7000 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7001 if (aggr_suppress_path(aggregate, pi))
7002 match++;
d62a17ae 7003 }
c2ff8b3e
DS
7004
7005 aggregate->count++;
7006
f273fef1
DS
7007 /*
7008 * If at least one route among routes that are
7009 * aggregated has ORIGIN with the value INCOMPLETE,
7010 * then the aggregated route MUST have the ORIGIN
7011 * attribute with the value INCOMPLETE. Otherwise, if
7012 * at least one route among routes that are aggregated
7013 * has ORIGIN with the value EGP, then the aggregated
7014 * route MUST have the ORIGIN attribute with the value
7015 * EGP.
7016 */
fc968841
NT
7017 switch (pi->attr->origin) {
7018 case BGP_ORIGIN_INCOMPLETE:
7019 aggregate->incomplete_origin_count++;
7020 break;
7021 case BGP_ORIGIN_EGP:
7022 aggregate->egp_origin_count++;
7023 break;
7024 default:
7025 /*Do nothing.
7026 */
7027 break;
7028 }
c2ff8b3e
DS
7029
7030 if (!aggregate->as_set)
7031 continue;
7032
f273fef1
DS
7033 /*
7034 * as-set aggregate route generate origin, as path,
7035 * and community aggregation.
7036 */
fc968841
NT
7037 /* Compute aggregate route's as-path.
7038 */
ef51a7d8 7039 bgp_compute_aggregate_aspath_hash(aggregate,
7040 pi->attr->aspath);
c2ff8b3e 7041
fc968841
NT
7042 /* Compute aggregate route's community.
7043 */
7044 if (pi->attr->community)
21fec674 7045 bgp_compute_aggregate_community_hash(
fc968841
NT
7046 aggregate,
7047 pi->attr->community);
dd18c5a9 7048
fc968841
NT
7049 /* Compute aggregate route's extended community.
7050 */
7051 if (pi->attr->ecommunity)
4edd83f9 7052 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7053 aggregate,
7054 pi->attr->ecommunity);
7055
7056 /* Compute aggregate route's large community.
7057 */
7058 if (pi->attr->lcommunity)
f1eb1f05 7059 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7060 aggregate,
7061 pi->attr->lcommunity);
d62a17ae 7062 }
c2ff8b3e 7063 if (match)
9bcb3eef 7064 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7065 }
21fec674 7066 if (aggregate->as_set) {
ef51a7d8 7067 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7068 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7069 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7070 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7071 }
7072
f1eb1f05 7073
9bcb3eef 7074 bgp_dest_unlock_node(top);
718e3744 7075
718e3744 7076
fc968841
NT
7077 if (aggregate->incomplete_origin_count > 0)
7078 origin = BGP_ORIGIN_INCOMPLETE;
7079 else if (aggregate->egp_origin_count > 0)
7080 origin = BGP_ORIGIN_EGP;
d62a17ae 7081
229757f1
DA
7082 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7083 origin = aggregate->origin;
7084
fc968841
NT
7085 if (aggregate->as_set) {
7086 if (aggregate->aspath)
7087 /* Retrieve aggregate route's as-path.
7088 */
7089 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7090
fc968841
NT
7091 if (aggregate->community)
7092 /* Retrieve aggregate route's community.
7093 */
7094 community = community_dup(aggregate->community);
3da2cc32 7095
fc968841
NT
7096 if (aggregate->ecommunity)
7097 /* Retrieve aggregate route's ecommunity.
7098 */
7099 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7100
fc968841
NT
7101 if (aggregate->lcommunity)
7102 /* Retrieve aggregate route's lcommunity.
7103 */
7104 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7105 }
718e3744 7106
c701010e 7107 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7108 ecommunity, lcommunity, atomic_aggregate,
7109 aggregate);
718e3744 7110}
7111
5f040085
DS
7112void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7113 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7114{
7115 struct bgp_table *table;
9bcb3eef
DS
7116 struct bgp_dest *top;
7117 struct bgp_dest *dest;
40381db7 7118 struct bgp_path_info *pi;
3b7db173
DS
7119 unsigned long match;
7120
7121 table = bgp->rib[afi][safi];
7122
7123 /* If routes exists below this node, generate aggregate routes. */
7124 top = bgp_node_get(table, p);
9bcb3eef
DS
7125 for (dest = bgp_node_get(table, p); dest;
7126 dest = bgp_route_next_until(dest, top)) {
7127 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7128
9bcb3eef 7129 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7130 continue;
7131 match = 0;
7132
9bcb3eef 7133 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7134 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7135 continue;
7136
40381db7 7137 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7138 continue;
7139
6aabb15d
RZ
7140 if (aggregate->summary_only && pi->extra
7141 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7142 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7143 match++;
3b7db173 7144 }
3b7db173 7145
365ab2e7
RZ
7146 if (aggregate->suppress_map_name
7147 && AGGREGATE_MED_VALID(aggregate)
7148 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7149 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7150 match++;
3b7db173 7151 }
365ab2e7 7152
3b7db173 7153 aggregate->count--;
fc968841
NT
7154
7155 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7156 aggregate->incomplete_origin_count--;
7157 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7158 aggregate->egp_origin_count--;
7159
7160 if (aggregate->as_set) {
7161 /* Remove as-path from aggregate.
7162 */
ef51a7d8 7163 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7164 aggregate,
7165 pi->attr->aspath);
7166
7167 if (pi->attr->community)
7168 /* Remove community from aggregate.
7169 */
21fec674 7170 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7171 aggregate,
7172 pi->attr->community);
7173
7174 if (pi->attr->ecommunity)
7175 /* Remove ecommunity from aggregate.
7176 */
4edd83f9 7177 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7178 aggregate,
7179 pi->attr->ecommunity);
7180
7181 if (pi->attr->lcommunity)
7182 /* Remove lcommunity from aggregate.
7183 */
f1eb1f05 7184 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7185 aggregate,
7186 pi->attr->lcommunity);
7187 }
3b7db173
DS
7188 }
7189
7190 /* If this node was suppressed, process the change. */
7191 if (match)
9bcb3eef 7192 bgp_process(bgp, dest, afi, safi);
3b7db173 7193 }
f1eb1f05 7194 if (aggregate->as_set) {
ef51a7d8 7195 aspath_free(aggregate->aspath);
7196 aggregate->aspath = NULL;
21fec674 7197 if (aggregate->community)
7198 community_free(&aggregate->community);
4edd83f9 7199 if (aggregate->ecommunity)
7200 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7201 if (aggregate->lcommunity)
7202 lcommunity_free(&aggregate->lcommunity);
7203 }
7204
9bcb3eef 7205 bgp_dest_unlock_node(top);
3b7db173 7206}
718e3744 7207
5f040085
DS
7208static void bgp_add_route_to_aggregate(struct bgp *bgp,
7209 const struct prefix *aggr_p,
fc968841
NT
7210 struct bgp_path_info *pinew, afi_t afi,
7211 safi_t safi,
7212 struct bgp_aggregate *aggregate)
7213{
7214 uint8_t origin;
7215 struct aspath *aspath = NULL;
7216 uint8_t atomic_aggregate = 0;
7217 struct community *community = NULL;
7218 struct ecommunity *ecommunity = NULL;
7219 struct lcommunity *lcommunity = NULL;
7220
7221 /* ORIGIN attribute: If at least one route among routes that are
7222 * aggregated has ORIGIN with the value INCOMPLETE, then the
7223 * aggregated route must have the ORIGIN attribute with the value
7224 * INCOMPLETE. Otherwise, if at least one route among routes that
7225 * are aggregated has ORIGIN with the value EGP, then the aggregated
7226 * route must have the origin attribute with the value EGP. In all
7227 * other case the value of the ORIGIN attribute of the aggregated
7228 * route is INTERNAL.
7229 */
7230 origin = BGP_ORIGIN_IGP;
7231
7232 aggregate->count++;
7233
6aabb15d
RZ
7234 /*
7235 * This must be called before `summary` check to avoid
7236 * "suppressing" twice.
7237 */
7238 if (aggregate->match_med)
7239 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7240 pinew, true);
7241
7242 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7243 aggr_suppress_path(aggregate, pinew);
fc968841 7244
365ab2e7
RZ
7245 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7246 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7247 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7248
7249 switch (pinew->attr->origin) {
7250 case BGP_ORIGIN_INCOMPLETE:
7251 aggregate->incomplete_origin_count++;
7252 break;
7253 case BGP_ORIGIN_EGP:
7254 aggregate->egp_origin_count++;
7255 break;
7256 default:
7257 /* Do nothing.
7258 */
7259 break;
7260 }
7261
7262 if (aggregate->incomplete_origin_count > 0)
7263 origin = BGP_ORIGIN_INCOMPLETE;
7264 else if (aggregate->egp_origin_count > 0)
7265 origin = BGP_ORIGIN_EGP;
7266
229757f1
DA
7267 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7268 origin = aggregate->origin;
7269
fc968841
NT
7270 if (aggregate->as_set) {
7271 /* Compute aggregate route's as-path.
7272 */
7273 bgp_compute_aggregate_aspath(aggregate,
7274 pinew->attr->aspath);
7275
7276 /* Compute aggregate route's community.
7277 */
7278 if (pinew->attr->community)
7279 bgp_compute_aggregate_community(
7280 aggregate,
7281 pinew->attr->community);
7282
7283 /* Compute aggregate route's extended community.
7284 */
7285 if (pinew->attr->ecommunity)
7286 bgp_compute_aggregate_ecommunity(
7287 aggregate,
7288 pinew->attr->ecommunity);
7289
7290 /* Compute aggregate route's large community.
7291 */
7292 if (pinew->attr->lcommunity)
7293 bgp_compute_aggregate_lcommunity(
7294 aggregate,
7295 pinew->attr->lcommunity);
7296
7297 /* Retrieve aggregate route's as-path.
7298 */
7299 if (aggregate->aspath)
7300 aspath = aspath_dup(aggregate->aspath);
7301
7302 /* Retrieve aggregate route's community.
7303 */
7304 if (aggregate->community)
7305 community = community_dup(aggregate->community);
7306
7307 /* Retrieve aggregate route's ecommunity.
7308 */
7309 if (aggregate->ecommunity)
7310 ecommunity = ecommunity_dup(aggregate->ecommunity);
7311
7312 /* Retrieve aggregate route's lcommunity.
7313 */
7314 if (aggregate->lcommunity)
7315 lcommunity = lcommunity_dup(aggregate->lcommunity);
7316 }
7317
7318 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7319 aspath, community, ecommunity,
7320 lcommunity, atomic_aggregate, aggregate);
7321}
7322
7323static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7324 safi_t safi,
7325 struct bgp_path_info *pi,
7326 struct bgp_aggregate *aggregate,
5f040085 7327 const struct prefix *aggr_p)
fc968841
NT
7328{
7329 uint8_t origin;
7330 struct aspath *aspath = NULL;
7331 uint8_t atomic_aggregate = 0;
7332 struct community *community = NULL;
7333 struct ecommunity *ecommunity = NULL;
7334 struct lcommunity *lcommunity = NULL;
7335 unsigned long match = 0;
7336
7337 if (BGP_PATH_HOLDDOWN(pi))
7338 return;
7339
7340 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7341 return;
7342
4056a5f6
RZ
7343 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7344 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7345 match++;
fc968841 7346
365ab2e7 7347 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7348 && aggr_suppress_map_test(bgp, aggregate, pi))
7349 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7350 match++;
fc968841 7351
6aabb15d 7352 /*
365ab2e7 7353 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7354 * "unsuppressing" twice.
7355 */
7356 if (aggregate->match_med)
7357 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7358 true);
7359
fc968841
NT
7360 if (aggregate->count > 0)
7361 aggregate->count--;
7362
7363 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7364 aggregate->incomplete_origin_count--;
7365 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7366 aggregate->egp_origin_count--;
7367
7368 if (aggregate->as_set) {
7369 /* Remove as-path from aggregate.
7370 */
7371 bgp_remove_aspath_from_aggregate(aggregate,
7372 pi->attr->aspath);
7373
7374 if (pi->attr->community)
7375 /* Remove community from aggregate.
7376 */
7377 bgp_remove_community_from_aggregate(
7378 aggregate,
7379 pi->attr->community);
7380
7381 if (pi->attr->ecommunity)
7382 /* Remove ecommunity from aggregate.
7383 */
7384 bgp_remove_ecommunity_from_aggregate(
7385 aggregate,
7386 pi->attr->ecommunity);
7387
7388 if (pi->attr->lcommunity)
7389 /* Remove lcommunity from aggregate.
7390 */
7391 bgp_remove_lcommunity_from_aggregate(
7392 aggregate,
7393 pi->attr->lcommunity);
7394 }
7395
7396 /* If this node was suppressed, process the change. */
7397 if (match)
7398 bgp_process(bgp, pi->net, afi, safi);
7399
7400 origin = BGP_ORIGIN_IGP;
7401 if (aggregate->incomplete_origin_count > 0)
7402 origin = BGP_ORIGIN_INCOMPLETE;
7403 else if (aggregate->egp_origin_count > 0)
7404 origin = BGP_ORIGIN_EGP;
7405
229757f1
DA
7406 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7407 origin = aggregate->origin;
7408
fc968841
NT
7409 if (aggregate->as_set) {
7410 /* Retrieve aggregate route's as-path.
7411 */
7412 if (aggregate->aspath)
7413 aspath = aspath_dup(aggregate->aspath);
7414
7415 /* Retrieve aggregate route's community.
7416 */
7417 if (aggregate->community)
7418 community = community_dup(aggregate->community);
7419
7420 /* Retrieve aggregate route's ecommunity.
7421 */
7422 if (aggregate->ecommunity)
7423 ecommunity = ecommunity_dup(aggregate->ecommunity);
7424
7425 /* Retrieve aggregate route's lcommunity.
7426 */
7427 if (aggregate->lcommunity)
7428 lcommunity = lcommunity_dup(aggregate->lcommunity);
7429 }
7430
7431 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7432 aspath, community, ecommunity,
7433 lcommunity, atomic_aggregate, aggregate);
7434}
7435
5a1ae2c2 7436void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7437 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7438{
9bcb3eef
DS
7439 struct bgp_dest *child;
7440 struct bgp_dest *dest;
d62a17ae 7441 struct bgp_aggregate *aggregate;
7442 struct bgp_table *table;
718e3744 7443
d62a17ae 7444 table = bgp->aggregate[afi][safi];
f018db83 7445
d62a17ae 7446 /* No aggregates configured. */
7447 if (bgp_table_top_nolock(table) == NULL)
7448 return;
f018db83 7449
d62a17ae 7450 if (p->prefixlen == 0)
7451 return;
718e3744 7452
40381db7 7453 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7454 return;
718e3744 7455
a77e2f4b
S
7456 /* If suppress fib is enabled and route not installed
7457 * in FIB, do not update the aggregate route
7458 */
7459 if (!bgp_check_advertise(bgp, pi->net))
7460 return;
7461
d62a17ae 7462 child = bgp_node_get(table, p);
718e3744 7463
d62a17ae 7464 /* Aggregate address configuration check. */
9bcb3eef
DS
7465 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7466 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7467
9bcb3eef
DS
7468 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7469 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7470 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7471 aggregate);
d62a17ae 7472 }
b1e62edd 7473 }
9bcb3eef 7474 bgp_dest_unlock_node(child);
718e3744 7475}
7476
5a1ae2c2 7477void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7478 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7479{
9bcb3eef
DS
7480 struct bgp_dest *child;
7481 struct bgp_dest *dest;
d62a17ae 7482 struct bgp_aggregate *aggregate;
7483 struct bgp_table *table;
718e3744 7484
d62a17ae 7485 table = bgp->aggregate[afi][safi];
718e3744 7486
d62a17ae 7487 /* No aggregates configured. */
7488 if (bgp_table_top_nolock(table) == NULL)
7489 return;
718e3744 7490
d62a17ae 7491 if (p->prefixlen == 0)
7492 return;
718e3744 7493
d62a17ae 7494 child = bgp_node_get(table, p);
718e3744 7495
d62a17ae 7496 /* Aggregate address configuration check. */
9bcb3eef
DS
7497 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7498 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7499
9bcb3eef
DS
7500 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7501 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7502 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7503 aggregate, dest_p);
d62a17ae 7504 }
b1e62edd 7505 }
9bcb3eef 7506 bgp_dest_unlock_node(child);
d62a17ae 7507}
718e3744 7508
718e3744 7509/* Aggregate route attribute. */
7510#define AGGREGATE_SUMMARY_ONLY 1
7511#define AGGREGATE_AS_SET 1
fb29348a 7512#define AGGREGATE_AS_UNSET 0
718e3744 7513
229757f1
DA
7514static const char *bgp_origin2str(uint8_t origin)
7515{
7516 switch (origin) {
7517 case BGP_ORIGIN_IGP:
7518 return "igp";
7519 case BGP_ORIGIN_EGP:
7520 return "egp";
7521 case BGP_ORIGIN_INCOMPLETE:
7522 return "incomplete";
7523 }
7524 return "n/a";
7525}
7526
37a87b8f
CS
7527int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7528 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7529{
9bcb3eef 7530 struct bgp_dest *dest;
d62a17ae 7531 struct bgp_aggregate *aggregate;
718e3744 7532
37a87b8f 7533 apply_mask(prefix);
d62a17ae 7534 /* Old configuration check. */
37a87b8f 7535 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7536 if (!dest) {
37a87b8f
CS
7537 snprintf(errmsg, errmsg_len,
7538 "There is no aggregate-address configuration.\n");
7539 return -1;
d62a17ae 7540 }
f6269b4f 7541
9bcb3eef 7542 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7543 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7544 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7545 0, aggregate);
d62a17ae 7546
7547 /* Unlock aggregate address configuration. */
9bcb3eef 7548 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7549
7550 if (aggregate->community)
7551 community_free(&aggregate->community);
7552
7553 if (aggregate->community_hash) {
7554 /* Delete all communities in the hash.
7555 */
7556 hash_clean(aggregate->community_hash,
7557 bgp_aggr_community_remove);
7558 /* Free up the community_hash.
7559 */
7560 hash_free(aggregate->community_hash);
7561 }
7562
7563 if (aggregate->ecommunity)
7564 ecommunity_free(&aggregate->ecommunity);
7565
7566 if (aggregate->ecommunity_hash) {
7567 /* Delete all ecommunities in the hash.
7568 */
7569 hash_clean(aggregate->ecommunity_hash,
7570 bgp_aggr_ecommunity_remove);
7571 /* Free up the ecommunity_hash.
7572 */
7573 hash_free(aggregate->ecommunity_hash);
7574 }
7575
7576 if (aggregate->lcommunity)
7577 lcommunity_free(&aggregate->lcommunity);
7578
7579 if (aggregate->lcommunity_hash) {
7580 /* Delete all lcommunities in the hash.
7581 */
7582 hash_clean(aggregate->lcommunity_hash,
7583 bgp_aggr_lcommunity_remove);
7584 /* Free up the lcommunity_hash.
7585 */
7586 hash_free(aggregate->lcommunity_hash);
7587 }
7588
7589 if (aggregate->aspath)
7590 aspath_free(aggregate->aspath);
7591
7592 if (aggregate->aspath_hash) {
7593 /* Delete all as-paths in the hash.
7594 */
7595 hash_clean(aggregate->aspath_hash,
7596 bgp_aggr_aspath_remove);
7597 /* Free up the aspath_hash.
7598 */
7599 hash_free(aggregate->aspath_hash);
7600 }
7601
d62a17ae 7602 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7603 bgp_dest_unlock_node(dest);
7604 bgp_dest_unlock_node(dest);
d62a17ae 7605
37a87b8f 7606 return 0;
d62a17ae 7607}
7608
37a87b8f
CS
7609int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7610 safi_t safi, const char *rmap, uint8_t summary_only,
7611 uint8_t as_set, uint8_t origin, bool match_med,
7612 const char *suppress_map,
7613 char *errmsg, size_t errmsg_len)
d62a17ae 7614{
d62a17ae 7615 int ret;
9bcb3eef 7616 struct bgp_dest *dest;
d62a17ae 7617 struct bgp_aggregate *aggregate;
fb29348a 7618 uint8_t as_set_new = as_set;
37a87b8f 7619 char buf[PREFIX2STR_BUFFER];
d62a17ae 7620
365ab2e7 7621 if (suppress_map && summary_only) {
37a87b8f 7622 snprintf(errmsg, errmsg_len,
365ab2e7 7623 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7624 return -1;
365ab2e7
RZ
7625 }
7626
37a87b8f 7627 apply_mask(prefix);
d62a17ae 7628
37a87b8f
CS
7629 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7630 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7631 snprintf(
7632 errmsg, errmsg_len,
7633 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7634 prefix2str(prefix, buf, PREFIX_STRLEN));
7635 return -1;
3624ac81
DS
7636 }
7637
d62a17ae 7638 /* Old configuration check. */
37a87b8f 7639 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7640 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7641
20894f50 7642 if (aggregate) {
37a87b8f
CS
7643 snprintf(errmsg, errmsg_len,
7644 "There is already same aggregate network.\n");
d62a17ae 7645 /* try to remove the old entry */
37a87b8f
CS
7646 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7647 errmsg_len);
d62a17ae 7648 if (ret) {
37a87b8f
CS
7649 snprintf(errmsg, errmsg_len,
7650 "Error deleting aggregate.\n");
9bcb3eef 7651 bgp_dest_unlock_node(dest);
37a87b8f 7652 return -1;
d62a17ae 7653 }
7654 }
718e3744 7655
d62a17ae 7656 /* Make aggregate address structure. */
7657 aggregate = bgp_aggregate_new();
7658 aggregate->summary_only = summary_only;
6aabb15d 7659 aggregate->match_med = match_med;
fb29348a
DA
7660
7661 /* Network operators MUST NOT locally generate any new
7662 * announcements containing AS_SET or AS_CONFED_SET. If they have
7663 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7664 * SHOULD withdraw those routes and re-announce routes for the
7665 * aggregate or component prefixes (i.e., the more-specific routes
7666 * subsumed by the previously aggregated route) without AS_SET
7667 * or AS_CONFED_SET in the updates.
7668 */
7f972cd8 7669 if (bgp->reject_as_sets) {
fb29348a
DA
7670 if (as_set == AGGREGATE_AS_SET) {
7671 as_set_new = AGGREGATE_AS_UNSET;
7672 zlog_warn(
63efca0e 7673 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7674 __func__);
37a87b8f
CS
7675 snprintf(
7676 errmsg, errmsg_len,
fb29348a
DA
7677 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7678 }
7679 }
7680
7681 aggregate->as_set = as_set_new;
d62a17ae 7682 aggregate->safi = safi;
229757f1
DA
7683 /* Override ORIGIN attribute if defined.
7684 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7685 * to IGP which is not what rfc4271 says.
7686 * This enables the same behavior, optionally.
7687 */
7688 aggregate->origin = origin;
20894f50
DA
7689
7690 if (rmap) {
7691 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7692 route_map_counter_decrement(aggregate->rmap.map);
7693 aggregate->rmap.name =
7694 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7695 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7696 route_map_counter_increment(aggregate->rmap.map);
7697 }
365ab2e7
RZ
7698
7699 if (suppress_map) {
7700 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7701 route_map_counter_decrement(aggregate->suppress_map);
7702
7703 aggregate->suppress_map_name =
7704 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7705 aggregate->suppress_map =
7706 route_map_lookup_by_name(aggregate->suppress_map_name);
7707 route_map_counter_increment(aggregate->suppress_map);
7708 }
7709
9bcb3eef 7710 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7711
d62a17ae 7712 /* Aggregate address insert into BGP routing table. */
37a87b8f 7713 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7714
37a87b8f 7715 return 0;
718e3744 7716}
7717
37a87b8f
CS
7718DEFPY_YANG(
7719 aggregate_addressv4, aggregate_addressv4_cmd,
7720 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7721 "as-set$as_set_s"
7722 "|summary-only$summary_only"
7723 "|route-map WORD$rmap_name"
7724 "|origin <egp|igp|incomplete>$origin_s"
7725 "|matching-MED-only$match_med"
90e21f35 7726 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7727 "}",
7728 NO_STR
7729 "Configure BGP aggregate entries\n"
7730 "Aggregate prefix\n"
7731 "Aggregate address\n"
7732 "Aggregate mask\n"
7733 "Generate AS set path information\n"
7734 "Filter more specific routes from updates\n"
7735 "Apply route map to aggregate network\n"
7736 "Route map name\n"
7737 "BGP origin code\n"
7738 "Remote EGP\n"
7739 "Local IGP\n"
7740 "Unknown heritage\n"
7741 "Only aggregate routes with matching MED\n"
90e21f35
CS
7742 "Suppress the selected more specific routes\n"
7743 "Route map with the route selectors\n")
37a87b8f
CS
7744{
7745 char base_xpath[XPATH_MAXLEN];
554b3b10 7746 safi_t safi = bgp_node_safi(vty);
554b3b10 7747 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7748
554b3b10
RZ
7749 if (addr_str) {
7750 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7751 == 0) {
7752 vty_out(vty, "%% Inconsistent address and mask\n");
7753 return CMD_WARNING_CONFIG_FAILED;
7754 }
37a87b8f
CS
7755 } else {
7756 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7757 }
7758
37a87b8f
CS
7759 if (!no && origin_s)
7760 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7761
7762 if (!no && as_set_s)
7763 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7764 else
7765 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7766
7767 if (!no && summary_only)
7768 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7769 "true");
7770 else
7771 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7772 "false");
7773
fa423774
CS
7774 if (!no && match_med)
7775 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7776 else
7777 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7778 "false");
7779
37a87b8f
CS
7780 if (rmap_name)
7781 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7782 rmap_name);
7783 else
7784 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7785 NB_OP_DESTROY, NULL);
7786
90e21f35
CS
7787 if (suppress_map)
7788 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7789 suppress_map);
7790 else
7791 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7792 NULL);
7793
37a87b8f
CS
7794 snprintf(
7795 base_xpath, sizeof(base_xpath),
7796 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7797 yang_afi_safi_value2identity(AFI_IP, safi),
7798 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7799
554b3b10 7800 if (no)
37a87b8f
CS
7801 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7802 else
7803 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7804
7805 return nb_cli_apply_changes(vty, base_xpath);
7806}
7807
7808DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7809 "[no] aggregate-address X:X::X:X/M$prefix {"
7810 "as-set$as_set_s"
7811 "|summary-only$summary_only"
7812 "|route-map WORD$rmap_name"
7813 "|origin <egp|igp|incomplete>$origin_s"
7814 "|matching-MED-only$match_med"
90e21f35 7815 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7816 "}",
7817 NO_STR
7818 "Configure BGP aggregate entries\n"
7819 "Aggregate prefix\n"
7820 "Generate AS set path information\n"
7821 "Filter more specific routes from updates\n"
7822 "Apply route map to aggregate network\n"
7823 "Route map name\n"
7824 "BGP origin code\n"
7825 "Remote EGP\n"
7826 "Local IGP\n"
7827 "Unknown heritage\n"
7828 "Only aggregate routes with matching MED\n"
7829 "Suppress the selected more specific routes\n"
90e21f35 7830 "Route map with the route selectors\n")
37a87b8f
CS
7831{
7832 char base_xpath[XPATH_MAXLEN];
7833 safi_t safi = bgp_node_safi(vty);
7834
7835 if (!no && origin_s)
7836 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7837
7838 if (!no && as_set_s)
7839 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7840 else
7841 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7842
7843 if (!no && summary_only)
7844 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7845 "true");
7846 else
7847 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7848 "false");
7849
fa423774
CS
7850 if (!no && match_med)
7851 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7852 else
7853 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7854 "false");
7855
37a87b8f
CS
7856 if (rmap_name)
7857 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7858 rmap_name);
7859
90e21f35
CS
7860 if (suppress_map)
7861 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7862 suppress_map);
7863 else
7864 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7865 NULL);
7866
37a87b8f
CS
7867 snprintf(
7868 base_xpath, sizeof(base_xpath),
7869 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7870 yang_afi_safi_value2identity(AFI_IP6, safi),
7871 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7872
554b3b10 7873 if (no)
37a87b8f
CS
7874 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7875 else
7876 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7877
37a87b8f
CS
7878 return nb_cli_apply_changes(vty, base_xpath);
7879}
7880
7881void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7882 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7883{
7884 uint8_t origin;
7885
7886 vty_out(vty, " aggregate-address %s",
7887 yang_dnode_get_string(dnode, "./prefix"));
7888
7889 if (yang_dnode_get_bool(dnode, "./as-set"))
7890 vty_out(vty, " as-set");
7891
7892 if (yang_dnode_get_bool(dnode, "./summary-only"))
7893 vty_out(vty, " summary-only");
7894
7895 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7896 vty_out(vty, " route-map %s",
7897 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7898
7899 origin = yang_dnode_get_enum(dnode, "./origin");
7900 if (origin != BGP_ORIGIN_UNSPECIFIED)
7901 vty_out(vty, " origin %s", bgp_origin2str(origin));
7902
fa423774
CS
7903 if (yang_dnode_get_bool(dnode, "./match-med"))
7904 vty_out(vty, " matching-MED-only");
7905
37a87b8f 7906 vty_out(vty, "\n");
718e3744 7907}
7908
718e3744 7909/* Redistribute route treatment. */
d62a17ae 7910void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7911 const union g_addr *nexthop, ifindex_t ifindex,
7912 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7913 uint8_t type, unsigned short instance,
7914 route_tag_t tag)
d62a17ae 7915{
4b7e6066 7916 struct bgp_path_info *new;
40381db7
DS
7917 struct bgp_path_info *bpi;
7918 struct bgp_path_info rmap_path;
9bcb3eef 7919 struct bgp_dest *bn;
d62a17ae 7920 struct attr attr;
7921 struct attr *new_attr;
7922 afi_t afi;
b68885f9 7923 route_map_result_t ret;
d62a17ae 7924 struct bgp_redist *red;
7925
7926 /* Make default attribute. */
7927 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7928 /*
7929 * This must not be NULL to satisfy Coverity SA
7930 */
7931 assert(attr.aspath);
9de1f7ff 7932
a4d82a8a 7933 switch (nhtype) {
9de1f7ff
DS
7934 case NEXTHOP_TYPE_IFINDEX:
7935 break;
7936 case NEXTHOP_TYPE_IPV4:
7937 case NEXTHOP_TYPE_IPV4_IFINDEX:
7938 attr.nexthop = nexthop->ipv4;
7939 break;
7940 case NEXTHOP_TYPE_IPV6:
7941 case NEXTHOP_TYPE_IPV6_IFINDEX:
7942 attr.mp_nexthop_global = nexthop->ipv6;
7943 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7944 break;
7945 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7946 switch (p->family) {
7947 case AF_INET:
9de1f7ff 7948 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7949 break;
7950 case AF_INET6:
9de1f7ff
DS
7951 memset(&attr.mp_nexthop_global, 0,
7952 sizeof(attr.mp_nexthop_global));
74489921 7953 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7954 break;
74489921 7955 }
9de1f7ff 7956 break;
d62a17ae 7957 }
74489921 7958 attr.nh_ifindex = ifindex;
f04a80a5 7959
d62a17ae 7960 attr.med = metric;
7961 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7962 attr.tag = tag;
718e3744 7963
d62a17ae 7964 afi = family2afi(p->family);
6aeb9e78 7965
d62a17ae 7966 red = bgp_redist_lookup(bgp, afi, type, instance);
7967 if (red) {
7968 struct attr attr_new;
718e3744 7969
d62a17ae 7970 /* Copy attribute for modification. */
6f4f49b2 7971 attr_new = attr;
718e3744 7972
d62a17ae 7973 if (red->redist_metric_flag)
7974 attr_new.med = red->redist_metric;
718e3744 7975
d62a17ae 7976 /* Apply route-map. */
7977 if (red->rmap.name) {
40381db7
DS
7978 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7979 rmap_path.peer = bgp->peer_self;
7980 rmap_path.attr = &attr_new;
718e3744 7981
d62a17ae 7982 SET_FLAG(bgp->peer_self->rmap_type,
7983 PEER_RMAP_TYPE_REDISTRIBUTE);
7984
1782514f 7985 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 7986
7987 bgp->peer_self->rmap_type = 0;
7988
7989 if (ret == RMAP_DENYMATCH) {
7990 /* Free uninterned attribute. */
7991 bgp_attr_flush(&attr_new);
7992
7993 /* Unintern original. */
7994 aspath_unintern(&attr.aspath);
7995 bgp_redistribute_delete(bgp, p, type, instance);
7996 return;
7997 }
7998 }
7999
637e5ba4 8000 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8001 bgp_attr_add_gshut_community(&attr_new);
8002
d62a17ae 8003 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8004 SAFI_UNICAST, p, NULL);
8005
8006 new_attr = bgp_attr_intern(&attr_new);
8007
9bcb3eef 8008 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8009 if (bpi->peer == bgp->peer_self
8010 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8011 break;
8012
40381db7 8013 if (bpi) {
d62a17ae 8014 /* Ensure the (source route) type is updated. */
40381db7
DS
8015 bpi->type = type;
8016 if (attrhash_cmp(bpi->attr, new_attr)
8017 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8018 bgp_attr_unintern(&new_attr);
8019 aspath_unintern(&attr.aspath);
9bcb3eef 8020 bgp_dest_unlock_node(bn);
d62a17ae 8021 return;
8022 } else {
8023 /* The attribute is changed. */
40381db7 8024 bgp_path_info_set_flag(bn, bpi,
18ee8310 8025 BGP_PATH_ATTR_CHANGED);
d62a17ae 8026
8027 /* Rewrite BGP route information. */
40381db7
DS
8028 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8029 bgp_path_info_restore(bn, bpi);
d62a17ae 8030 else
40381db7
DS
8031 bgp_aggregate_decrement(
8032 bgp, p, bpi, afi, SAFI_UNICAST);
8033 bgp_attr_unintern(&bpi->attr);
8034 bpi->attr = new_attr;
8035 bpi->uptime = bgp_clock();
d62a17ae 8036
8037 /* Process change. */
40381db7 8038 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8039 SAFI_UNICAST);
8040 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8041 bgp_dest_unlock_node(bn);
d62a17ae 8042 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8043
8044 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8045 || (bgp->inst_type
8046 == BGP_INSTANCE_TYPE_DEFAULT)) {
8047
8048 vpn_leak_from_vrf_update(
40381db7 8049 bgp_get_default(), bgp, bpi);
ddb5b488 8050 }
d62a17ae 8051 return;
8052 }
8053 }
8054
8055 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8056 bgp->peer_self, new_attr, bn);
1defdda8 8057 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8058
8059 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8060 bgp_path_info_add(bn, new);
9bcb3eef 8061 bgp_dest_unlock_node(bn);
d62a17ae 8062 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8063
8064 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8065 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8066
8067 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8068 }
d62a17ae 8069 }
8070
8071 /* Unintern original. */
8072 aspath_unintern(&attr.aspath);
718e3744 8073}
8074
d7c0a89a
QY
8075void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8076 unsigned short instance)
718e3744 8077{
d62a17ae 8078 afi_t afi;
9bcb3eef 8079 struct bgp_dest *dest;
40381db7 8080 struct bgp_path_info *pi;
d62a17ae 8081 struct bgp_redist *red;
718e3744 8082
d62a17ae 8083 afi = family2afi(p->family);
718e3744 8084
d62a17ae 8085 red = bgp_redist_lookup(bgp, afi, type, instance);
8086 if (red) {
9bcb3eef
DS
8087 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8088 SAFI_UNICAST, p, NULL);
d62a17ae 8089
9bcb3eef 8090 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8091 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8092 break;
8093
40381db7 8094 if (pi) {
ddb5b488
PZ
8095 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8096 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8097
8098 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8099 bgp, pi);
ddb5b488 8100 }
40381db7 8101 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8102 bgp_path_info_delete(dest, pi);
8103 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8104 }
9bcb3eef 8105 bgp_dest_unlock_node(dest);
d62a17ae 8106 }
8107}
8108
8109/* Withdraw specified route type's route. */
8110void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8111 unsigned short instance)
d62a17ae 8112{
9bcb3eef 8113 struct bgp_dest *dest;
40381db7 8114 struct bgp_path_info *pi;
d62a17ae 8115 struct bgp_table *table;
8116
8117 table = bgp->rib[afi][SAFI_UNICAST];
8118
9bcb3eef
DS
8119 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8120 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8121 if (pi->peer == bgp->peer_self && pi->type == type
8122 && pi->instance == instance)
d62a17ae 8123 break;
8124
40381db7 8125 if (pi) {
ddb5b488
PZ
8126 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8127 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8128
8129 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8130 bgp, pi);
ddb5b488 8131 }
9bcb3eef 8132 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8133 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8134 bgp_path_info_delete(dest, pi);
8135 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8136 }
718e3744 8137 }
718e3744 8138}
6b0655a2 8139
718e3744 8140/* Static function to display route. */
bd494ec5 8141static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8142 json_object *json, bool wide)
718e3744 8143{
be054588 8144 int len = 0;
d62a17ae 8145 char buf[BUFSIZ];
50e05855 8146 char buf2[BUFSIZ];
718e3744 8147
d62a17ae 8148 if (p->family == AF_INET) {
c6462ff4 8149 if (!json) {
8228a9a7 8150 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8151 } else {
8152 json_object_string_add(json, "prefix",
8153 inet_ntop(p->family,
8154 &p->u.prefix, buf,
8155 BUFSIZ));
8156 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8157 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8158 json_object_string_add(json, "network", buf2);
c6462ff4 8159 }
d62a17ae 8160 } else if (p->family == AF_ETHERNET) {
8228a9a7 8161 len = vty_out(vty, "%pFX", p);
b03b8898 8162 } else if (p->family == AF_EVPN) {
57f7feb6 8163 if (!json)
2dbe669b 8164 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8165 else
60466a63 8166 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8167 } else if (p->family == AF_FLOWSPEC) {
8168 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8169 json ?
8170 NLRI_STRING_FORMAT_JSON_SIMPLE :
8171 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8172 } else {
c6462ff4 8173 if (!json)
8228a9a7 8174 len = vty_out(vty, "%pFX", p);
50e05855
AD
8175 else {
8176 json_object_string_add(json, "prefix",
8177 inet_ntop(p->family,
8178 &p->u.prefix, buf,
8179 BUFSIZ));
8180 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8181 prefix2str(p, buf2, PREFIX_STRLEN);
8182 json_object_string_add(json, "network", buf2);
8183 }
9c92b5f7 8184 }
d62a17ae 8185
9c92b5f7 8186 if (!json) {
ae248832 8187 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8188 if (len < 1)
8189 vty_out(vty, "\n%*s", 20, " ");
8190 else
8191 vty_out(vty, "%*s", len, " ");
8192 }
718e3744 8193}
8194
d62a17ae 8195enum bgp_display_type {
8196 normal_list,
718e3744 8197};
8198
bbb46eb5
DA
8199static const char *
8200bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8201{
8202 switch (reason) {
8203 case bgp_path_selection_none:
8204 return "Nothing to Select";
8205 case bgp_path_selection_first:
8206 return "First path received";
8207 case bgp_path_selection_evpn_sticky_mac:
8208 return "EVPN Sticky Mac";
8209 case bgp_path_selection_evpn_seq:
8210 return "EVPN sequence number";
8211 case bgp_path_selection_evpn_lower_ip:
8212 return "EVPN lower IP";
8213 case bgp_path_selection_evpn_local_path:
8214 return "EVPN local ES path";
8215 case bgp_path_selection_evpn_non_proxy:
8216 return "EVPN non proxy";
8217 case bgp_path_selection_weight:
8218 return "Weight";
8219 case bgp_path_selection_local_pref:
8220 return "Local Pref";
8221 case bgp_path_selection_local_route:
8222 return "Local Route";
8223 case bgp_path_selection_confed_as_path:
8224 return "Confederation based AS Path";
8225 case bgp_path_selection_as_path:
8226 return "AS Path";
8227 case bgp_path_selection_origin:
8228 return "Origin";
8229 case bgp_path_selection_med:
8230 return "MED";
8231 case bgp_path_selection_peer:
8232 return "Peer Type";
8233 case bgp_path_selection_confed:
8234 return "Confed Peer Type";
8235 case bgp_path_selection_igp_metric:
8236 return "IGP Metric";
8237 case bgp_path_selection_older:
8238 return "Older Path";
8239 case bgp_path_selection_router_id:
8240 return "Router ID";
8241 case bgp_path_selection_cluster_length:
8242 return "Cluser length";
8243 case bgp_path_selection_stale:
8244 return "Path Staleness";
8245 case bgp_path_selection_local_configured:
8246 return "Locally configured route";
8247 case bgp_path_selection_neighbor_ip:
8248 return "Neighbor IP";
8249 case bgp_path_selection_default:
8250 return "Nothing left to compare";
8251 }
8252 return "Invalid (internal error)";
8253}
8254
18ee8310 8255/* Print the short form route status for a bgp_path_info */
4b7e6066 8256static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8257 struct bgp_path_info *path,
d62a17ae 8258 json_object *json_path)
718e3744 8259{
d62a17ae 8260 if (json_path) {
b05a1c8b 8261
d62a17ae 8262 /* Route status display. */
9b6d8fcf 8263 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8264 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8265
9b6d8fcf 8266 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8267 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8268
4056a5f6 8269 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8270 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8271
9b6d8fcf
DS
8272 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8273 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8274 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8275
d62a17ae 8276 /* Selected */
9b6d8fcf 8277 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8278 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8279
9b6d8fcf 8280 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8281 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8282
bbb46eb5 8283 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8284 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8285 json_object_string_add(json_path, "selectionReason",
8286 bgp_path_selection_reason2str(
8287 path->net->reason));
8288 }
b05a1c8b 8289
9b6d8fcf 8290 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8291 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8292
d62a17ae 8293 /* Internal route. */
9b6d8fcf
DS
8294 if ((path->peer->as)
8295 && (path->peer->as == path->peer->local_as))
d62a17ae 8296 json_object_string_add(json_path, "pathFrom",
8297 "internal");
8298 else
8299 json_object_string_add(json_path, "pathFrom",
8300 "external");
b05a1c8b 8301
d62a17ae 8302 return;
8303 }
b05a1c8b 8304
d62a17ae 8305 /* Route status display. */
9b6d8fcf 8306 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8307 vty_out(vty, "R");
9b6d8fcf 8308 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8309 vty_out(vty, "S");
4056a5f6 8310 else if (bgp_path_suppressed(path))
d62a17ae 8311 vty_out(vty, "s");
9b6d8fcf
DS
8312 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8313 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8314 vty_out(vty, "*");
8315 else
8316 vty_out(vty, " ");
8317
8318 /* Selected */
9b6d8fcf 8319 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8320 vty_out(vty, "h");
9b6d8fcf 8321 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8322 vty_out(vty, "d");
9b6d8fcf 8323 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8324 vty_out(vty, ">");
9b6d8fcf 8325 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8326 vty_out(vty, "=");
8327 else
8328 vty_out(vty, " ");
718e3744 8329
d62a17ae 8330 /* Internal route. */
9b6d8fcf
DS
8331 if (path->peer && (path->peer->as)
8332 && (path->peer->as == path->peer->local_as))
d62a17ae 8333 vty_out(vty, "i");
8334 else
8335 vty_out(vty, " ");
b40d939b 8336}
8337
2ba93fd6
DA
8338static char *bgp_nexthop_hostname(struct peer *peer,
8339 struct bgp_nexthop_cache *bnc)
25b5da8d 8340{
892fedb6 8341 if (peer->hostname
aef999a2 8342 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8343 return peer->hostname;
8344 return NULL;
8345}
8346
b40d939b 8347/* called from terminal list command */
bd494ec5 8348void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8349 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8350 json_object *json_paths, bool wide)
d62a17ae 8351{
aef999a2 8352 int len;
515c2602 8353 struct attr *attr = path->attr;
d62a17ae 8354 json_object *json_path = NULL;
8355 json_object *json_nexthops = NULL;
8356 json_object *json_nexthop_global = NULL;
8357 json_object *json_nexthop_ll = NULL;
6f214dd3 8358 json_object *json_ext_community = NULL;
9df8b37c 8359 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8360 bool nexthop_self =
9b6d8fcf 8361 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8362 bool nexthop_othervrf = false;
43089216 8363 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8364 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8365 char *nexthop_hostname =
8366 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8367 char esi_buf[ESI_STR_LEN];
d62a17ae 8368
8369 if (json_paths)
8370 json_path = json_object_new_object();
8371
8372 /* short status lead text */
9b6d8fcf 8373 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8374
8375 if (!json_paths) {
8376 /* print prefix and mask */
8377 if (!display)
ae248832 8378 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8379 else
ae248832 8380 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8381 } else {
ae248832 8382 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8383 }
47fc97cc 8384
9df8b37c
PZ
8385 /*
8386 * If vrf id of nexthop is different from that of prefix,
8387 * set up printable string to append
8388 */
9b6d8fcf 8389 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8390 const char *self = "";
8391
8392 if (nexthop_self)
8393 self = "<";
8394
8395 nexthop_othervrf = true;
9b6d8fcf 8396 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8397
9b6d8fcf 8398 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8399 snprintf(vrf_id_str, sizeof(vrf_id_str),
8400 "@%s%s", VRFID_NONE_STR, self);
8401 else
8402 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8403 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8404
9b6d8fcf
DS
8405 if (path->extra->bgp_orig->inst_type
8406 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8407
9b6d8fcf 8408 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8409 } else {
8410 const char *self = "";
8411
8412 if (nexthop_self)
8413 self = "<";
8414
8415 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8416 }
8417
445c2480
DS
8418 /*
8419 * For ENCAP and EVPN routes, nexthop address family is not
8420 * neccessarily the same as the prefix address family.
8421 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8422 * EVPN routes are also exchanged with a MP nexthop. Currently,
8423 * this
8424 * is only IPv4, the value will be present in either
8425 * attr->nexthop or
8426 * attr->mp_nexthop_global_in
8427 */
8428 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8429 char buf[BUFSIZ];
8430 char nexthop[128];
8431 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8432
8433 switch (af) {
8434 case AF_INET:
772270f3
QY
8435 snprintf(nexthop, sizeof(nexthop), "%s",
8436 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8437 BUFSIZ));
445c2480
DS
8438 break;
8439 case AF_INET6:
772270f3
QY
8440 snprintf(nexthop, sizeof(nexthop), "%s",
8441 inet_ntop(af, &attr->mp_nexthop_global, buf,
8442 BUFSIZ));
445c2480
DS
8443 break;
8444 default:
772270f3 8445 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8446 break;
d62a17ae 8447 }
d62a17ae 8448
445c2480
DS
8449 if (json_paths) {
8450 json_nexthop_global = json_object_new_object();
8451
515c2602
DA
8452 json_object_string_add(json_nexthop_global, "ip",
8453 nexthop);
8454
939a97f4 8455 if (path->peer->hostname)
515c2602
DA
8456 json_object_string_add(json_nexthop_global,
8457 "hostname",
939a97f4 8458 path->peer->hostname);
515c2602
DA
8459
8460 json_object_string_add(json_nexthop_global, "afi",
8461 (af == AF_INET) ? "ipv4"
8462 : "ipv6");
445c2480
DS
8463 json_object_boolean_true_add(json_nexthop_global,
8464 "used");
aef999a2
DA
8465 } else {
8466 if (nexthop_hostname)
8467 len = vty_out(vty, "%s(%s)%s", nexthop,
8468 nexthop_hostname, vrf_id_str);
8469 else
8470 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8471
ae248832 8472 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8473 if (len < 1)
8474 vty_out(vty, "\n%*s", 36, " ");
8475 else
8476 vty_out(vty, "%*s", len, " ");
8477 }
445c2480
DS
8478 } else if (safi == SAFI_EVPN) {
8479 if (json_paths) {
23d0a753
DA
8480 char buf[BUFSIZ] = {0};
8481
445c2480
DS
8482 json_nexthop_global = json_object_new_object();
8483
515c2602 8484 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8485 inet_ntop(AF_INET,
8486 &attr->nexthop, buf,
8487 sizeof(buf)));
515c2602 8488
939a97f4 8489 if (path->peer->hostname)
515c2602
DA
8490 json_object_string_add(json_nexthop_global,
8491 "hostname",
939a97f4 8492 path->peer->hostname);
515c2602 8493
a4d82a8a
PZ
8494 json_object_string_add(json_nexthop_global, "afi",
8495 "ipv4");
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, "%pI4(%s)%s", &attr->nexthop,
8501 nexthop_hostname, vrf_id_str);
8502 else
8503 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8504 vrf_id_str);
8505
ae248832 8506 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8507 if (len < 1)
8508 vty_out(vty, "\n%*s", 36, " ");
8509 else
8510 vty_out(vty, "%*s", len, " ");
8511 }
d33fc23b 8512 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8513 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8514 if (json_paths) {
23d0a753
DA
8515 char buf[BUFSIZ] = {0};
8516
026b914a 8517 json_nexthop_global = json_object_new_object();
515c2602 8518
026b914a
PG
8519 json_object_string_add(json_nexthop_global,
8520 "afi", "ipv4");
515c2602
DA
8521 json_object_string_add(
8522 json_nexthop_global, "ip",
23d0a753
DA
8523 inet_ntop(AF_INET, &attr->nexthop, buf,
8524 sizeof(buf)));
515c2602 8525
939a97f4 8526 if (path->peer->hostname)
515c2602
DA
8527 json_object_string_add(
8528 json_nexthop_global, "hostname",
939a97f4 8529 path->peer->hostname);
515c2602 8530
50e05855
AD
8531 json_object_boolean_true_add(
8532 json_nexthop_global,
026b914a
PG
8533 "used");
8534 } else {
aef999a2
DA
8535 if (nexthop_hostname)
8536 len = vty_out(vty, "%pI4(%s)%s",
8537 &attr->nexthop,
8538 nexthop_hostname,
8539 vrf_id_str);
8540 else
8541 len = vty_out(vty, "%pI4%s",
8542 &attr->nexthop,
8543 vrf_id_str);
8544
ae248832 8545 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8546 if (len < 1)
8547 vty_out(vty, "\n%*s", 36, " ");
8548 else
8549 vty_out(vty, "%*s", len, " ");
026b914a
PG
8550 }
8551 }
d33fc23b 8552 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8553 if (json_paths) {
23d0a753
DA
8554 char buf[BUFSIZ] = {0};
8555
445c2480 8556 json_nexthop_global = json_object_new_object();
d62a17ae 8557
515c2602 8558 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8559 inet_ntop(AF_INET,
8560 &attr->nexthop, buf,
8561 sizeof(buf)));
515c2602 8562
939a97f4 8563 if (path->peer->hostname)
515c2602
DA
8564 json_object_string_add(json_nexthop_global,
8565 "hostname",
939a97f4 8566 path->peer->hostname);
445c2480 8567
a4d82a8a
PZ
8568 json_object_string_add(json_nexthop_global, "afi",
8569 "ipv4");
445c2480
DS
8570 json_object_boolean_true_add(json_nexthop_global,
8571 "used");
8572 } else {
aef999a2
DA
8573 if (nexthop_hostname)
8574 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8575 nexthop_hostname, vrf_id_str);
8576 else
8577 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8578 vrf_id_str);
9df8b37c 8579
ae248832 8580 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8581 if (len < 1)
8582 vty_out(vty, "\n%*s", 36, " ");
8583 else
8584 vty_out(vty, "%*s", len, " ");
d62a17ae 8585 }
445c2480 8586 }
b05a1c8b 8587
445c2480 8588 /* IPv6 Next Hop */
a4d82a8a 8589 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8590 char buf[BUFSIZ];
d62a17ae 8591
445c2480
DS
8592 if (json_paths) {
8593 json_nexthop_global = json_object_new_object();
a4d82a8a 8594 json_object_string_add(
515c2602
DA
8595 json_nexthop_global, "ip",
8596 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8597 buf, BUFSIZ));
8598
939a97f4 8599 if (path->peer->hostname)
515c2602
DA
8600 json_object_string_add(json_nexthop_global,
8601 "hostname",
939a97f4 8602 path->peer->hostname);
515c2602 8603
a4d82a8a
PZ
8604 json_object_string_add(json_nexthop_global, "afi",
8605 "ipv6");
8606 json_object_string_add(json_nexthop_global, "scope",
8607 "global");
445c2480
DS
8608
8609 /* We display both LL & GL if both have been
8610 * received */
0606039c
DA
8611 if ((attr->mp_nexthop_len
8612 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8613 || (path->peer->conf_if)) {
a4d82a8a 8614 json_nexthop_ll = json_object_new_object();
d62a17ae 8615 json_object_string_add(
515c2602
DA
8616 json_nexthop_ll, "ip",
8617 inet_ntop(AF_INET6,
8618 &attr->mp_nexthop_local, buf,
8619 BUFSIZ));
8620
939a97f4 8621 if (path->peer->hostname)
515c2602
DA
8622 json_object_string_add(
8623 json_nexthop_ll, "hostname",
939a97f4 8624 path->peer->hostname);
515c2602 8625
a4d82a8a
PZ
8626 json_object_string_add(json_nexthop_ll, "afi",
8627 "ipv6");
8628 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8629 "link-local");
d62a17ae 8630
a4d82a8a
PZ
8631 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8632 &attr->mp_nexthop_local)
445c2480
DS
8633 != 0)
8634 && !attr->mp_nexthop_prefer_global)
d62a17ae 8635 json_object_boolean_true_add(
a4d82a8a 8636 json_nexthop_ll, "used");
445c2480
DS
8637 else
8638 json_object_boolean_true_add(
a4d82a8a 8639 json_nexthop_global, "used");
445c2480
DS
8640 } else
8641 json_object_boolean_true_add(
8642 json_nexthop_global, "used");
8643 } else {
8644 /* Display LL if LL/Global both in table unless
8645 * prefer-global is set */
0606039c
DA
8646 if (((attr->mp_nexthop_len
8647 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8648 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8649 || (path->peer->conf_if)) {
8650 if (path->peer->conf_if) {
a4d82a8a 8651 len = vty_out(vty, "%s",
9b6d8fcf 8652 path->peer->conf_if);
ae248832
MK
8653 /* len of IPv6 addr + max len of def
8654 * ifname */
8655 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8656
8657 if (len < 1)
a4d82a8a 8658 vty_out(vty, "\n%*s", 36, " ");
445c2480 8659 else
a4d82a8a 8660 vty_out(vty, "%*s", len, " ");
d62a17ae 8661 } else {
aef999a2
DA
8662 if (nexthop_hostname)
8663 len = vty_out(
8664 vty, "%pI6(%s)%s",
8665 &attr->mp_nexthop_local,
8666 nexthop_hostname,
8667 vrf_id_str);
8668 else
8669 len = vty_out(
8670 vty, "%pI6%s",
8671 &attr->mp_nexthop_local,
8672 vrf_id_str);
8673
ae248832 8674 len = wide ? (41 - len) : (16 - len);
d62a17ae 8675
8676 if (len < 1)
a4d82a8a 8677 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8678 else
a4d82a8a 8679 vty_out(vty, "%*s", len, " ");
d62a17ae 8680 }
445c2480 8681 } else {
aef999a2
DA
8682 if (nexthop_hostname)
8683 len = vty_out(vty, "%pI6(%s)%s",
8684 &attr->mp_nexthop_global,
8685 nexthop_hostname,
8686 vrf_id_str);
8687 else
8688 len = vty_out(vty, "%pI6%s",
8689 &attr->mp_nexthop_global,
8690 vrf_id_str);
8691
ae248832 8692 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8693
8694 if (len < 1)
8695 vty_out(vty, "\n%*s", 36, " ");
8696 else
8697 vty_out(vty, "%*s", len, " ");
d62a17ae 8698 }
8699 }
445c2480 8700 }
718e3744 8701
445c2480
DS
8702 /* MED/Metric */
8703 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8704 if (json_paths)
50e05855 8705 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8706 else if (wide)
8707 vty_out(vty, "%7u", attr->med);
0fbac0b4 8708 else
445c2480 8709 vty_out(vty, "%10u", attr->med);
ae248832
MK
8710 else if (!json_paths) {
8711 if (wide)
8712 vty_out(vty, "%*s", 7, " ");
8713 else
8714 vty_out(vty, "%*s", 10, " ");
8715 }
d62a17ae 8716
445c2480
DS
8717 /* Local Pref */
8718 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8719 if (json_paths)
50e05855 8720 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8721 attr->local_pref);
8722 else
445c2480
DS
8723 vty_out(vty, "%7u", attr->local_pref);
8724 else if (!json_paths)
8725 vty_out(vty, " ");
d62a17ae 8726
445c2480
DS
8727 if (json_paths)
8728 json_object_int_add(json_path, "weight", attr->weight);
8729 else
8730 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8731
445c2480
DS
8732 if (json_paths) {
8733 char buf[BUFSIZ];
a4d82a8a
PZ
8734 json_object_string_add(
8735 json_path, "peerId",
9b6d8fcf 8736 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8737 }
b05a1c8b 8738
445c2480
DS
8739 /* Print aspath */
8740 if (attr->aspath) {
0fbac0b4 8741 if (json_paths)
50e05855 8742 json_object_string_add(json_path, "path",
0fbac0b4
DA
8743 attr->aspath->str);
8744 else
445c2480 8745 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8746 }
f1aa5d8a 8747
445c2480
DS
8748 /* Print origin */
8749 if (json_paths)
a4d82a8a
PZ
8750 json_object_string_add(json_path, "origin",
8751 bgp_origin_long_str[attr->origin]);
445c2480
DS
8752 else
8753 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8754
9df8b37c 8755 if (json_paths) {
d071f237 8756 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8757 json_object_string_add(json_path, "esi",
8758 esi_to_str(&attr->esi,
8759 esi_buf, sizeof(esi_buf)));
8760 }
6f214dd3
CS
8761 if (safi == SAFI_EVPN &&
8762 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8763 json_ext_community = json_object_new_object();
8764 json_object_string_add(json_ext_community,
8765 "string",
8766 attr->ecommunity->str);
8767 json_object_object_add(json_path,
8768 "extendedCommunity",
8769 json_ext_community);
8770 }
8771
9df8b37c
PZ
8772 if (nexthop_self)
8773 json_object_boolean_true_add(json_path,
8774 "announceNexthopSelf");
8775 if (nexthop_othervrf) {
8776 json_object_string_add(json_path, "nhVrfName",
8777 nexthop_vrfname);
8778
8779 json_object_int_add(json_path, "nhVrfId",
8780 ((nexthop_vrfid == VRF_UNKNOWN)
8781 ? -1
8782 : (int)nexthop_vrfid));
8783 }
8784 }
8785
d62a17ae 8786 if (json_paths) {
8787 if (json_nexthop_global || json_nexthop_ll) {
8788 json_nexthops = json_object_new_array();
f1aa5d8a 8789
d62a17ae 8790 if (json_nexthop_global)
8791 json_object_array_add(json_nexthops,
8792 json_nexthop_global);
f1aa5d8a 8793
d62a17ae 8794 if (json_nexthop_ll)
8795 json_object_array_add(json_nexthops,
8796 json_nexthop_ll);
f1aa5d8a 8797
d62a17ae 8798 json_object_object_add(json_path, "nexthops",
8799 json_nexthops);
8800 }
8801
8802 json_object_array_add(json_paths, json_path);
8803 } else {
8804 vty_out(vty, "\n");
6f214dd3 8805
b5e140c8 8806 if (safi == SAFI_EVPN) {
229587fb
AK
8807 struct bgp_path_es_info *path_es_info = NULL;
8808
8809 if (path->extra)
8810 path_es_info = path->extra->es_info;
8811
d071f237 8812 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8813 /* XXX - add these params to the json out */
b5e140c8 8814 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8815 vty_out(vty, "ESI:%s",
8816 esi_to_str(&attr->esi, esi_buf,
8817 sizeof(esi_buf)));
8818 if (path_es_info && path_es_info->es)
8819 vty_out(vty, " VNI: %u",
8820 path_es_info->vni);
8821 vty_out(vty, "\n");
b5e140c8
AK
8822 }
8823 if (attr->flag &
8824 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8825 vty_out(vty, "%*s", 20, " ");
8826 vty_out(vty, "%s\n", attr->ecommunity->str);
8827 }
6f214dd3
CS
8828 }
8829
49e5a4a0 8830#ifdef ENABLE_BGP_VNC
d62a17ae 8831 /* prints an additional line, indented, with VNC info, if
8832 * present */
8833 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8834 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8835#endif
d62a17ae 8836 }
8837}
718e3744 8838
8839/* called from terminal list command */
5f040085
DS
8840void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8841 struct attr *attr, safi_t safi, bool use_json,
ae248832 8842 json_object *json_ar, bool wide)
d62a17ae 8843{
8844 json_object *json_status = NULL;
8845 json_object *json_net = NULL;
aef999a2 8846 int len;
d62a17ae 8847 char buff[BUFSIZ];
dc387b0f 8848
d62a17ae 8849 /* Route status display. */
8850 if (use_json) {
8851 json_status = json_object_new_object();
8852 json_net = json_object_new_object();
8853 } else {
8854 vty_out(vty, "*");
8855 vty_out(vty, ">");
8856 vty_out(vty, " ");
8857 }
718e3744 8858
d62a17ae 8859 /* print prefix and mask */
50e05855 8860 if (use_json) {
dc387b0f
LK
8861 if (safi == SAFI_EVPN)
8862 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8863 else if (p->family == AF_INET || p->family == AF_INET6) {
8864 json_object_string_add(
8865 json_net, "addrPrefix",
8866 inet_ntop(p->family, &p->u.prefix, buff,
8867 BUFSIZ));
8868 json_object_int_add(json_net, "prefixLen",
8869 p->prefixlen);
8870 prefix2str(p, buff, PREFIX_STRLEN);
8871 json_object_string_add(json_net, "network", buff);
8872 }
50e05855 8873 } else
ae248832 8874 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8875
8876 /* Print attribute */
8877 if (attr) {
8878 if (use_json) {
23d0a753
DA
8879 char buf[BUFSIZ] = {0};
8880
d62a17ae 8881 if (p->family == AF_INET
8882 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8883 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8884 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8885 json_object_string_add(
8886 json_net, "nextHop",
23d0a753
DA
8887 inet_ntop(
8888 AF_INET,
8889 &attr->mp_nexthop_global_in,
8890 buf, sizeof(buf)));
d62a17ae 8891 else
8892 json_object_string_add(
8893 json_net, "nextHop",
23d0a753
DA
8894 inet_ntop(AF_INET,
8895 &attr->nexthop, buf,
8896 sizeof(buf)));
d62a17ae 8897 } else if (p->family == AF_INET6
8898 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8899 char buf[BUFSIZ];
8900
8901 json_object_string_add(
aa0a10fc 8902 json_net, "nextHopGlobal",
d62a17ae 8903 inet_ntop(AF_INET6,
8904 &attr->mp_nexthop_global, buf,
8905 BUFSIZ));
23d0a753
DA
8906 } else if (p->family == AF_EVPN
8907 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8908 char buf[BUFSIZ] = {0};
8909
8910 json_object_string_add(
8911 json_net, "nextHop",
8912 inet_ntop(AF_INET,
8913 &attr->mp_nexthop_global_in,
8914 buf, sizeof(buf)));
8915 }
d62a17ae 8916
8917 if (attr->flag
8918 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8919 json_object_int_add(json_net, "metric",
8920 attr->med);
8921
0fbac0b4 8922 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8923 json_object_int_add(json_net, "locPrf",
0fbac0b4 8924 attr->local_pref);
d62a17ae 8925
8926 json_object_int_add(json_net, "weight", attr->weight);
8927
8928 /* Print aspath */
0fbac0b4 8929 if (attr->aspath)
50e05855 8930 json_object_string_add(json_net, "path",
0fbac0b4 8931 attr->aspath->str);
d62a17ae 8932
8933 /* Print origin */
8934 json_object_string_add(json_net, "bgpOriginCode",
8935 bgp_origin_str[attr->origin]);
8936 } else {
8937 if (p->family == AF_INET
8938 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8939 || safi == SAFI_EVPN
8940 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8941 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8942 || safi == SAFI_EVPN)
23d0a753
DA
8943 vty_out(vty, "%-16pI4",
8944 &attr->mp_nexthop_global_in);
ae248832 8945 else if (wide)
23d0a753 8946 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8947 else
23d0a753 8948 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8949 } else if (p->family == AF_INET6
8950 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8951 char buf[BUFSIZ];
8952
8953 len = vty_out(
8954 vty, "%s",
8955 inet_ntop(AF_INET6,
8956 &attr->mp_nexthop_global, buf,
8957 BUFSIZ));
ae248832 8958 len = wide ? (41 - len) : (16 - len);
d62a17ae 8959 if (len < 1)
8960 vty_out(vty, "\n%*s", 36, " ");
8961 else
8962 vty_out(vty, "%*s", len, " ");
8963 }
8964 if (attr->flag
8965 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8966 if (wide)
8967 vty_out(vty, "%7u", attr->med);
8968 else
8969 vty_out(vty, "%10u", attr->med);
8970 else if (wide)
8971 vty_out(vty, " ");
d62a17ae 8972 else
8973 vty_out(vty, " ");
718e3744 8974
d62a17ae 8975 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8976 vty_out(vty, "%7u", attr->local_pref);
8977 else
8978 vty_out(vty, " ");
8979
8980 vty_out(vty, "%7u ", attr->weight);
8981
8982 /* Print aspath */
8983 if (attr->aspath)
8984 aspath_print_vty(vty, "%s", attr->aspath, " ");
8985
8986 /* Print origin */
8987 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8988 }
8989 }
8990 if (use_json) {
8991 json_object_boolean_true_add(json_status, "*");
8992 json_object_boolean_true_add(json_status, ">");
8993 json_object_object_add(json_net, "appliedStatusSymbols",
8994 json_status);
1608ff77 8995
dc387b0f
LK
8996 prefix2str(p, buff, PREFIX_STRLEN);
8997 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8998 } else
8999 vty_out(vty, "\n");
9000}
9001
bd494ec5 9002void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9003 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9004 json_object *json)
9005{
9006 json_object *json_out = NULL;
9007 struct attr *attr;
9008 mpls_label_t label = MPLS_INVALID_LABEL;
9009
9b6d8fcf 9010 if (!path->extra)
d62a17ae 9011 return;
9012
9013 if (json)
9014 json_out = json_object_new_object();
9015
9016 /* short status lead text */
9b6d8fcf 9017 route_vty_short_status_out(vty, path, json_out);
d62a17ae 9018
9019 /* print prefix and mask */
9020 if (json == NULL) {
9021 if (!display)
ae248832 9022 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9023 else
9024 vty_out(vty, "%*s", 17, " ");
9025 }
9026
9027 /* Print attribute */
9b6d8fcf 9028 attr = path->attr;
05864da7
DS
9029 if (((p->family == AF_INET)
9030 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9031 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9032 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9033 char buf[BUFSIZ] = {0};
9034
05864da7
DS
9035 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9036 || safi == SAFI_EVPN) {
9037 if (json)
9038 json_object_string_add(
9039 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9040 inet_ntop(AF_INET,
9041 &attr->mp_nexthop_global_in,
9042 buf, sizeof(buf)));
05864da7 9043 else
23d0a753
DA
9044 vty_out(vty, "%-16pI4",
9045 &attr->mp_nexthop_global_in);
05864da7
DS
9046 } else {
9047 if (json)
9048 json_object_string_add(
9049 json_out, "nexthop",
23d0a753
DA
9050 inet_ntop(AF_INET, &attr->nexthop, buf,
9051 sizeof(buf)));
05864da7 9052 else
23d0a753 9053 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9054 }
9055 } else if (((p->family == AF_INET6)
9056 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9057 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9058 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9059 char buf_a[512];
9060
9061 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9062 if (json)
9063 json_object_string_add(
9064 json_out, "mpNexthopGlobalIn",
9065 inet_ntop(AF_INET6,
9066 &attr->mp_nexthop_global,
9067 buf_a, sizeof(buf_a)));
9068 else
9069 vty_out(vty, "%s",
9070 inet_ntop(AF_INET6,
9071 &attr->mp_nexthop_global,
9072 buf_a, sizeof(buf_a)));
9073 } else if (attr->mp_nexthop_len
9074 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9075 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9076 &attr->mp_nexthop_global,
9077 &attr->mp_nexthop_local);
9078 if (json)
9079 json_object_string_add(json_out,
9080 "mpNexthopGlobalLocal",
9081 buf_a);
9082 else
9083 vty_out(vty, "%s", buf_a);
d62a17ae 9084 }
9085 }
9086
9b6d8fcf 9087 label = decode_label(&path->extra->label[0]);
d62a17ae 9088
9089 if (bgp_is_valid_label(&label)) {
9090 if (json) {
9091 json_object_int_add(json_out, "notag", label);
9092 json_object_array_add(json, json_out);
9093 } else {
9094 vty_out(vty, "notag/%d", label);
9095 vty_out(vty, "\n");
9096 }
9097 }
9098}
718e3744 9099
bd494ec5 9100void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9101 struct bgp_path_info *path, int display,
d62a17ae 9102 json_object *json_paths)
718e3744 9103{
d62a17ae 9104 struct attr *attr;
14f51eba 9105 char buf[BUFSIZ] = {0};
d62a17ae 9106 json_object *json_path = NULL;
14f51eba
LK
9107 json_object *json_nexthop = NULL;
9108 json_object *json_overlay = NULL;
856ca177 9109
9b6d8fcf 9110 if (!path->extra)
d62a17ae 9111 return;
718e3744 9112
14f51eba
LK
9113 if (json_paths) {
9114 json_path = json_object_new_object();
9115 json_overlay = json_object_new_object();
9116 json_nexthop = json_object_new_object();
9117 }
9118
d62a17ae 9119 /* short status lead text */
9b6d8fcf 9120 route_vty_short_status_out(vty, path, json_path);
856ca177 9121
d62a17ae 9122 /* print prefix and mask */
9123 if (!display)
ae248832 9124 route_vty_out_route(p, vty, json_path, false);
d62a17ae 9125 else
9126 vty_out(vty, "%*s", 17, " ");
9127
9128 /* Print attribute */
9b6d8fcf 9129 attr = path->attr;
05864da7
DS
9130 char buf1[BUFSIZ];
9131 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9132
05864da7
DS
9133 switch (af) {
9134 case AF_INET:
9135 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9136 if (!json_path) {
9137 vty_out(vty, "%-16s", buf);
9138 } else {
9139 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9140
05864da7 9141 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9142
05864da7
DS
9143 json_object_object_add(json_path, "nexthop",
9144 json_nexthop);
9145 }
9146 break;
9147 case AF_INET6:
9148 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9149 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9150 if (!json_path) {
9151 vty_out(vty, "%s(%s)", buf, buf1);
9152 } else {
9153 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9154
05864da7
DS
9155 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9156 buf1);
14f51eba 9157
05864da7 9158 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9159
05864da7
DS
9160 json_object_object_add(json_path, "nexthop",
9161 json_nexthop);
9162 }
9163 break;
9164 default:
9165 if (!json_path) {
9166 vty_out(vty, "?");
9167 } else {
9168 json_object_string_add(json_nexthop, "Error",
9169 "Unsupported address-family");
d62a17ae 9170 }
05864da7 9171 }
988258b4 9172
6c924775
DS
9173 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9174
9175 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9176 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9177 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9178 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9179
05864da7
DS
9180 if (!json_path)
9181 vty_out(vty, "/%s", buf);
9182 else
9183 json_object_string_add(json_overlay, "gw", buf);
9184
9185 if (attr->ecommunity) {
9186 char *mac = NULL;
9187 struct ecommunity_val *routermac = ecommunity_lookup(
9188 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9189 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9190
9191 if (routermac)
9192 mac = ecom_mac2str((char *)routermac->val);
9193 if (mac) {
9194 if (!json_path) {
c4efd0f4 9195 vty_out(vty, "/%s", mac);
05864da7
DS
9196 } else {
9197 json_object_string_add(json_overlay, "rmac",
9198 mac);
988258b4 9199 }
05864da7 9200 XFREE(MTYPE_TMP, mac);
988258b4 9201 }
05864da7 9202 }
718e3744 9203
05864da7
DS
9204 if (!json_path) {
9205 vty_out(vty, "\n");
9206 } else {
9207 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9208
05864da7 9209 json_object_array_add(json_paths, json_path);
14f51eba 9210 }
d62a17ae 9211}
718e3744 9212
d62a17ae 9213/* dampening route */
5f040085
DS
9214static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9215 struct bgp_path_info *path, int display,
9216 afi_t afi, safi_t safi, bool use_json,
9217 json_object *json)
d62a17ae 9218{
9219 struct attr *attr;
9220 int len;
9221 char timebuf[BGP_UPTIME_LEN];
9222
9223 /* short status lead text */
9b6d8fcf 9224 route_vty_short_status_out(vty, path, json);
d62a17ae 9225
9226 /* print prefix and mask */
9227 if (!use_json) {
9228 if (!display)
ae248832 9229 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9230 else
9231 vty_out(vty, "%*s", 17, " ");
9232 }
9233
9b6d8fcf 9234 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9235 len = 17 - len;
9236 if (len < 1) {
9237 if (!use_json)
9238 vty_out(vty, "\n%*s", 34, " ");
9239 } else {
9240 if (use_json)
9241 json_object_int_add(json, "peerHost", len);
9242 else
9243 vty_out(vty, "%*s", len, " ");
9244 }
9245
9246 if (use_json)
a935f597
DA
9247 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9248 safi, use_json, json);
d62a17ae 9249 else
9b6d8fcf
DS
9250 vty_out(vty, "%s ",
9251 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9252 BGP_UPTIME_LEN, afi, safi,
9253 use_json, json));
d62a17ae 9254
9255 /* Print attribute */
9b6d8fcf 9256 attr = path->attr;
d62a17ae 9257
05864da7
DS
9258 /* Print aspath */
9259 if (attr->aspath) {
d62a17ae 9260 if (use_json)
05864da7
DS
9261 json_object_string_add(json, "asPath",
9262 attr->aspath->str);
d62a17ae 9263 else
05864da7 9264 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9265 }
05864da7
DS
9266
9267 /* Print origin */
9268 if (use_json)
9269 json_object_string_add(json, "origin",
9270 bgp_origin_str[attr->origin]);
9271 else
9272 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9273
d62a17ae 9274 if (!use_json)
9275 vty_out(vty, "\n");
9276}
718e3744 9277
d62a17ae 9278/* flap route */
5f040085
DS
9279static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9280 struct bgp_path_info *path, int display,
9281 afi_t afi, safi_t safi, bool use_json,
9282 json_object *json)
784d3a42 9283{
d62a17ae 9284 struct attr *attr;
9285 struct bgp_damp_info *bdi;
9286 char timebuf[BGP_UPTIME_LEN];
9287 int len;
784d3a42 9288
9b6d8fcf 9289 if (!path->extra)
d62a17ae 9290 return;
784d3a42 9291
9b6d8fcf 9292 bdi = path->extra->damp_info;
784d3a42 9293
d62a17ae 9294 /* short status lead text */
9b6d8fcf 9295 route_vty_short_status_out(vty, path, json);
784d3a42 9296
d62a17ae 9297 /* print prefix and mask */
9298 if (!use_json) {
9299 if (!display)
ae248832 9300 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9301 else
9302 vty_out(vty, "%*s", 17, " ");
9303 }
784d3a42 9304
9b6d8fcf 9305 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9306 len = 16 - len;
9307 if (len < 1) {
9308 if (!use_json)
9309 vty_out(vty, "\n%*s", 33, " ");
9310 } else {
9311 if (use_json)
9312 json_object_int_add(json, "peerHost", len);
9313 else
9314 vty_out(vty, "%*s", len, " ");
9315 }
784d3a42 9316
d62a17ae 9317 len = vty_out(vty, "%d", bdi->flap);
9318 len = 5 - len;
9319 if (len < 1) {
9320 if (!use_json)
9321 vty_out(vty, " ");
9322 } else {
9323 if (use_json)
9324 json_object_int_add(json, "bdiFlap", len);
9325 else
9326 vty_out(vty, "%*s", len, " ");
9327 }
9328
9329 if (use_json)
9330 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9331 json);
9332 else
996c9314
LB
9333 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9334 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9335
9b6d8fcf
DS
9336 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9337 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9338 if (use_json)
9b6d8fcf 9339 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9340 BGP_UPTIME_LEN, afi, safi,
9341 use_json, json);
d62a17ae 9342 else
9343 vty_out(vty, "%s ",
9b6d8fcf 9344 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9345 BGP_UPTIME_LEN, afi,
9346 safi, use_json, json));
d62a17ae 9347 } else {
9348 if (!use_json)
9349 vty_out(vty, "%*s ", 8, " ");
9350 }
9351
9352 /* Print attribute */
9b6d8fcf 9353 attr = path->attr;
d62a17ae 9354
05864da7
DS
9355 /* Print aspath */
9356 if (attr->aspath) {
d62a17ae 9357 if (use_json)
05864da7
DS
9358 json_object_string_add(json, "asPath",
9359 attr->aspath->str);
d62a17ae 9360 else
05864da7 9361 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9362 }
05864da7
DS
9363
9364 /* Print origin */
9365 if (use_json)
9366 json_object_string_add(json, "origin",
9367 bgp_origin_str[attr->origin]);
9368 else
9369 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9370
d62a17ae 9371 if (!use_json)
9372 vty_out(vty, "\n");
9373}
9374
9375static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9376 int *first, const char *header,
9377 json_object *json_adv_to)
9378{
9379 char buf1[INET6_ADDRSTRLEN];
9380 json_object *json_peer = NULL;
9381
9382 if (json_adv_to) {
9383 /* 'advertised-to' is a dictionary of peers we have advertised
9384 * this
9385 * prefix too. The key is the peer's IP or swpX, the value is
9386 * the
9387 * hostname if we know it and "" if not.
9388 */
9389 json_peer = json_object_new_object();
9390
9391 if (peer->hostname)
9392 json_object_string_add(json_peer, "hostname",
9393 peer->hostname);
9394
9395 if (peer->conf_if)
9396 json_object_object_add(json_adv_to, peer->conf_if,
9397 json_peer);
9398 else
9399 json_object_object_add(
9400 json_adv_to,
9401 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9402 json_peer);
9403 } else {
9404 if (*first) {
9405 vty_out(vty, "%s", header);
9406 *first = 0;
9407 }
9408
9409 if (peer->hostname
892fedb6 9410 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9411 if (peer->conf_if)
9412 vty_out(vty, " %s(%s)", peer->hostname,
9413 peer->conf_if);
9414 else
9415 vty_out(vty, " %s(%s)", peer->hostname,
9416 sockunion2str(&peer->su, buf1,
9417 SU_ADDRSTRLEN));
9418 } else {
9419 if (peer->conf_if)
9420 vty_out(vty, " %s", peer->conf_if);
9421 else
9422 vty_out(vty, " %s",
9423 sockunion2str(&peer->su, buf1,
9424 SU_ADDRSTRLEN));
9425 }
9426 }
784d3a42
PG
9427}
9428
dcc68b5e
MS
9429static void route_vty_out_tx_ids(struct vty *vty,
9430 struct bgp_addpath_info_data *d)
9431{
9432 int i;
9433
9434 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9435 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9436 d->addpath_tx_id[i],
9437 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9438 }
9439}
9440
5e4d4c8a 9441static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9442 struct bgp_path_info *pi,
9443 struct attr *attr,
9444 json_object *json_path)
5e4d4c8a
AK
9445{
9446 char esi_buf[ESI_STR_LEN];
9447 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9448 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9449 ATTR_ES_PEER_ROUTER);
9450 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9451 ATTR_ES_PEER_ACTIVE);
9452 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9453 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9454 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9455 if (json_path) {
9456 json_object *json_es_info = NULL;
9457
9458 json_object_string_add(
9459 json_path, "esi",
9460 esi_buf);
9461 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9462 json_es_info = json_object_new_object();
9463 if (es_local)
9464 json_object_boolean_true_add(
9465 json_es_info, "localEs");
9466 if (peer_active)
9467 json_object_boolean_true_add(
9468 json_es_info, "peerActive");
9469 if (peer_proxy)
9470 json_object_boolean_true_add(
9471 json_es_info, "peerProxy");
9472 if (peer_router)
9473 json_object_boolean_true_add(
9474 json_es_info, "peerRouter");
9475 if (attr->mm_sync_seqnum)
9476 json_object_int_add(
9477 json_es_info, "peerSeq",
9478 attr->mm_sync_seqnum);
9479 json_object_object_add(
9480 json_path, "es_info",
9481 json_es_info);
9482 }
9483 } else {
9484 if (bgp_evpn_attr_is_sync(attr))
9485 vty_out(vty,
9486 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9487 esi_buf,
9488 es_local ? "local-es":"",
9489 peer_proxy ? "proxy " : "",
9490 peer_active ? "active ":"",
9491 peer_router ? "router ":"",
9492 attr->mm_sync_seqnum);
9493 else
9494 vty_out(vty, " ESI %s %s\n",
9495 esi_buf,
9496 es_local ? "local-es":"");
9497 }
9498}
9499
9500void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9501 struct bgp_dest *bn, struct bgp_path_info *path,
9502 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9503{
9504 char buf[INET6_ADDRSTRLEN];
9505 char buf1[BUFSIZ];
515c2602 9506 struct attr *attr = path->attr;
d62a17ae 9507 int sockunion_vty_out(struct vty *, union sockunion *);
9508 time_t tbuf;
9509 json_object *json_bestpath = NULL;
9510 json_object *json_cluster_list = NULL;
9511 json_object *json_cluster_list_list = NULL;
9512 json_object *json_ext_community = NULL;
9513 json_object *json_last_update = NULL;
7fd077aa 9514 json_object *json_pmsi = NULL;
d62a17ae 9515 json_object *json_nexthop_global = NULL;
9516 json_object *json_nexthop_ll = NULL;
9517 json_object *json_nexthops = NULL;
9518 json_object *json_path = NULL;
9519 json_object *json_peer = NULL;
9520 json_object *json_string = NULL;
9521 json_object *json_adv_to = NULL;
9522 int first = 0;
9523 struct listnode *node, *nnode;
9524 struct peer *peer;
9525 int addpath_capable;
9526 int has_adj;
9527 unsigned int first_as;
1defdda8 9528 bool nexthop_self =
9b6d8fcf 9529 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9530 int i;
2ba93fd6
DA
9531 char *nexthop_hostname =
9532 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9533
9534 if (json_paths) {
9535 json_path = json_object_new_object();
9536 json_peer = json_object_new_object();
9537 json_nexthop_global = json_object_new_object();
9538 }
9539
44c69747 9540 if (path->extra) {
b57ba6d2 9541 char tag_buf[30];
d62a17ae 9542
d62a17ae 9543 tag_buf[0] = '\0';
9b6d8fcf
DS
9544 if (path->extra && path->extra->num_labels) {
9545 bgp_evpn_label2str(path->extra->label,
9546 path->extra->num_labels, tag_buf,
a4d82a8a 9547 sizeof(tag_buf));
d62a17ae 9548 }
d7325ee7 9549 if (safi == SAFI_EVPN) {
44c69747 9550 if (!json_paths) {
2dbe669b
DA
9551 vty_out(vty, " Route %pFX",
9552 (struct prefix_evpn *)
9553 bgp_dest_get_prefix(bn));
44c69747
LK
9554 if (tag_buf[0] != '\0')
9555 vty_out(vty, " VNI %s", tag_buf);
9556 vty_out(vty, "\n");
9557 } else {
9558 if (tag_buf[0])
9559 json_object_string_add(json_path, "VNI",
9560 tag_buf);
9561 }
d7325ee7
DD
9562 }
9563
44c69747 9564 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9565 struct bgp_path_info *parent_ri;
9bcb3eef 9566 struct bgp_dest *dest, *pdest;
d62a17ae 9567
9b6d8fcf 9568 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9569 dest = parent_ri->net;
9570 if (dest && dest->pdest) {
9571 pdest = dest->pdest;
9572 prefix_rd2str(
9573 (struct prefix_rd *)bgp_dest_get_prefix(
9574 pdest),
9575 buf1, sizeof(buf1));
d7325ee7 9576 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9577 vty_out(vty,
9578 " Imported from %s:%pFX, VNI %s\n",
9579 buf1,
9580 (struct prefix_evpn *)
9581 bgp_dest_get_prefix(
9582 dest),
9583 tag_buf);
d7325ee7 9584 } else
2dbe669b
DA
9585 vty_out(vty,
9586 " Imported from %s:%pFX\n",
9587 buf1,
9588 (struct prefix_evpn *)
9589 bgp_dest_get_prefix(
9590 dest));
d62a17ae 9591 }
9592 }
9593 }
d62a17ae 9594
05864da7
DS
9595 /* Line1 display AS-path, Aggregator */
9596 if (attr->aspath) {
9597 if (json_paths) {
9598 if (!attr->aspath->json)
9599 aspath_str_update(attr->aspath, true);
9600 json_object_lock(attr->aspath->json);
9601 json_object_object_add(json_path, "aspath",
9602 attr->aspath->json);
9603 } else {
9604 if (attr->aspath->segments)
9605 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9606 else
05864da7 9607 vty_out(vty, " Local");
d62a17ae 9608 }
05864da7 9609 }
d62a17ae 9610
05864da7
DS
9611 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9612 if (json_paths)
9613 json_object_boolean_true_add(json_path, "removed");
9614 else
9615 vty_out(vty, ", (removed)");
9616 }
d62a17ae 9617
05864da7
DS
9618 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9619 if (json_paths)
9620 json_object_boolean_true_add(json_path, "stale");
9621 else
9622 vty_out(vty, ", (stale)");
9623 }
d62a17ae 9624
05864da7
DS
9625 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9626 if (json_paths) {
23d0a753
DA
9627 char buf[BUFSIZ] = {0};
9628
05864da7
DS
9629 json_object_int_add(json_path, "aggregatorAs",
9630 attr->aggregator_as);
23d0a753
DA
9631 json_object_string_add(json_path, "aggregatorId",
9632 inet_ntop(AF_INET,
9633 &attr->aggregator_addr,
9634 buf, sizeof(buf)));
87c82131
DA
9635 if (attr->aggregator_as == BGP_AS_ZERO)
9636 json_object_boolean_true_add(
9637 json_path, "aggregatorAsMalformed");
9638 else
9639 json_object_boolean_false_add(
9640 json_path, "aggregatorAsMalformed");
05864da7 9641 } else {
87c82131
DA
9642 if (attr->aggregator_as == BGP_AS_ZERO)
9643 vty_out(vty,
23d0a753 9644 ", (aggregated by %u(malformed) %pI4)",
87c82131 9645 attr->aggregator_as,
23d0a753 9646 &attr->aggregator_addr);
87c82131 9647 else
23d0a753 9648 vty_out(vty, ", (aggregated by %u %pI4)",
87c82131 9649 attr->aggregator_as,
23d0a753 9650 &attr->aggregator_addr);
d62a17ae 9651 }
05864da7 9652 }
d62a17ae 9653
05864da7
DS
9654 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9655 PEER_FLAG_REFLECTOR_CLIENT)) {
9656 if (json_paths)
9657 json_object_boolean_true_add(json_path,
9658 "rxedFromRrClient");
9659 else
9660 vty_out(vty, ", (Received from a RR-client)");
9661 }
d62a17ae 9662
05864da7
DS
9663 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9664 PEER_FLAG_RSERVER_CLIENT)) {
9665 if (json_paths)
9666 json_object_boolean_true_add(json_path,
9667 "rxedFromRsClient");
9668 else
9669 vty_out(vty, ", (Received from a RS-client)");
9670 }
d62a17ae 9671
05864da7
DS
9672 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9673 if (json_paths)
9674 json_object_boolean_true_add(json_path,
9675 "dampeningHistoryEntry");
9676 else
9677 vty_out(vty, ", (history entry)");
9678 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9679 if (json_paths)
9680 json_object_boolean_true_add(json_path,
9681 "dampeningSuppressed");
9682 else
9683 vty_out(vty, ", (suppressed due to dampening)");
9684 }
d62a17ae 9685
05864da7
DS
9686 if (!json_paths)
9687 vty_out(vty, "\n");
d62a17ae 9688
05864da7
DS
9689 /* Line2 display Next-hop, Neighbor, Router-id */
9690 /* Display the nexthop */
9bcb3eef 9691 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9692
9693 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9694 || bn_p->family == AF_EVPN)
05864da7
DS
9695 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9696 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9697 char buf[BUFSIZ] = {0};
9698
05864da7
DS
9699 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9700 || safi == SAFI_EVPN) {
515c2602 9701 if (json_paths) {
d62a17ae 9702 json_object_string_add(
515c2602 9703 json_nexthop_global, "ip",
23d0a753
DA
9704 inet_ntop(AF_INET,
9705 &attr->mp_nexthop_global_in,
9706 buf, sizeof(buf)));
515c2602 9707
939a97f4 9708 if (path->peer->hostname)
515c2602
DA
9709 json_object_string_add(
9710 json_nexthop_global, "hostname",
939a97f4 9711 path->peer->hostname);
aef999a2
DA
9712 } else {
9713 if (nexthop_hostname)
9714 vty_out(vty, " %pI4(%s)",
9715 &attr->mp_nexthop_global_in,
9716 nexthop_hostname);
9717 else
9718 vty_out(vty, " %pI4",
9719 &attr->mp_nexthop_global_in);
9720 }
d62a17ae 9721 } else {
515c2602 9722 if (json_paths) {
05864da7 9723 json_object_string_add(
515c2602 9724 json_nexthop_global, "ip",
23d0a753
DA
9725 inet_ntop(AF_INET, &attr->nexthop, buf,
9726 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->nexthop,
9736 nexthop_hostname);
9737 else
9738 vty_out(vty, " %pI4",
9739 &attr->nexthop);
9740 }
d62a17ae 9741 }
9742
05864da7
DS
9743 if (json_paths)
9744 json_object_string_add(json_nexthop_global, "afi",
9745 "ipv4");
9746 } else {
9747 if (json_paths) {
9748 json_object_string_add(
515c2602
DA
9749 json_nexthop_global, "ip",
9750 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9751 buf, INET6_ADDRSTRLEN));
9752
939a97f4 9753 if (path->peer->hostname)
515c2602
DA
9754 json_object_string_add(json_nexthop_global,
9755 "hostname",
939a97f4 9756 path->peer->hostname);
515c2602 9757
05864da7
DS
9758 json_object_string_add(json_nexthop_global, "afi",
9759 "ipv6");
9760 json_object_string_add(json_nexthop_global, "scope",
9761 "global");
9762 } else {
aef999a2
DA
9763 if (nexthop_hostname)
9764 vty_out(vty, " %pI6(%s)",
9765 &attr->mp_nexthop_global,
9766 nexthop_hostname);
9767 else
9768 vty_out(vty, " %pI6",
9769 &attr->mp_nexthop_global);
d62a17ae 9770 }
05864da7 9771 }
d62a17ae 9772
05864da7
DS
9773 /* Display the IGP cost or 'inaccessible' */
9774 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9775 if (json_paths)
9776 json_object_boolean_false_add(json_nexthop_global,
9777 "accessible");
9778 else
9779 vty_out(vty, " (inaccessible)");
9780 } else {
9781 if (path->extra && path->extra->igpmetric) {
d62a17ae 9782 if (json_paths)
05864da7
DS
9783 json_object_int_add(json_nexthop_global,
9784 "metric",
9785 path->extra->igpmetric);
d62a17ae 9786 else
05864da7
DS
9787 vty_out(vty, " (metric %u)",
9788 path->extra->igpmetric);
d62a17ae 9789 }
9790
05864da7 9791 /* IGP cost is 0, display this only for json */
d62a17ae 9792 else {
d62a17ae 9793 if (json_paths)
05864da7
DS
9794 json_object_int_add(json_nexthop_global,
9795 "metric", 0);
d62a17ae 9796 }
d62a17ae 9797
05864da7
DS
9798 if (json_paths)
9799 json_object_boolean_true_add(json_nexthop_global,
9800 "accessible");
9801 }
d62a17ae 9802
05864da7
DS
9803 /* Display peer "from" output */
9804 /* This path was originated locally */
9805 if (path->peer == bgp->peer_self) {
d62a17ae 9806
05864da7 9807 if (safi == SAFI_EVPN
b54892e0 9808 || (bn_p->family == AF_INET
05864da7 9809 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9810 if (json_paths)
05864da7
DS
9811 json_object_string_add(json_peer, "peerId",
9812 "0.0.0.0");
d62a17ae 9813 else
05864da7
DS
9814 vty_out(vty, " from 0.0.0.0 ");
9815 } else {
d62a17ae 9816 if (json_paths)
05864da7
DS
9817 json_object_string_add(json_peer, "peerId",
9818 "::");
d62a17ae 9819 else
05864da7 9820 vty_out(vty, " from :: ");
d62a17ae 9821 }
d62a17ae 9822
23d0a753
DA
9823 if (json_paths) {
9824 char buf[BUFSIZ] = {0};
9825
05864da7 9826 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9827 inet_ntop(AF_INET,
9828 &bgp->router_id, buf,
9829 sizeof(buf)));
9830 } else {
9831 vty_out(vty, "(%pI4)", &bgp->router_id);
9832 }
05864da7 9833 }
d62a17ae 9834
05864da7
DS
9835 /* We RXed this path from one of our peers */
9836 else {
9837
9838 if (json_paths) {
9839 json_object_string_add(json_peer, "peerId",
9840 sockunion2str(&path->peer->su,
9841 buf,
9842 SU_ADDRSTRLEN));
9843 json_object_string_add(json_peer, "routerId",
9844 inet_ntop(AF_INET,
9845 &path->peer->remote_id,
9846 buf1, sizeof(buf1)));
9847
9848 if (path->peer->hostname)
9849 json_object_string_add(json_peer, "hostname",
9850 path->peer->hostname);
9851
9852 if (path->peer->domainname)
9853 json_object_string_add(json_peer, "domainname",
9854 path->peer->domainname);
9855
9856 if (path->peer->conf_if)
9857 json_object_string_add(json_peer, "interface",
9858 path->peer->conf_if);
9859 } else {
9860 if (path->peer->conf_if) {
9861 if (path->peer->hostname
892fedb6
DA
9862 && CHECK_FLAG(path->peer->bgp->flags,
9863 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9864 vty_out(vty, " from %s(%s)",
9865 path->peer->hostname,
9866 path->peer->conf_if);
d62a17ae 9867 else
05864da7 9868 vty_out(vty, " from %s",
9b6d8fcf 9869 path->peer->conf_if);
d62a17ae 9870 } else {
05864da7 9871 if (path->peer->hostname
892fedb6
DA
9872 && CHECK_FLAG(path->peer->bgp->flags,
9873 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9874 vty_out(vty, " from %s(%s)",
9875 path->peer->hostname,
9876 path->peer->host);
d62a17ae 9877 else
05864da7
DS
9878 vty_out(vty, " from %s",
9879 sockunion2str(&path->peer->su,
9880 buf,
9881 SU_ADDRSTRLEN));
d62a17ae 9882 }
d62a17ae 9883
05864da7 9884 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9885 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9886 else
9887 vty_out(vty, " (%s)",
9888 inet_ntop(AF_INET,
9889 &path->peer->remote_id, buf1,
9890 sizeof(buf1)));
d62a17ae 9891 }
05864da7 9892 }
9df8b37c 9893
05864da7
DS
9894 /*
9895 * Note when vrfid of nexthop is different from that of prefix
9896 */
9897 if (path->extra && path->extra->bgp_orig) {
9898 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9899
05864da7
DS
9900 if (json_paths) {
9901 const char *vn;
9df8b37c 9902
05864da7
DS
9903 if (path->extra->bgp_orig->inst_type
9904 == BGP_INSTANCE_TYPE_DEFAULT)
9905 vn = VRF_DEFAULT_NAME;
9906 else
9907 vn = path->extra->bgp_orig->name;
9df8b37c 9908
05864da7 9909 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9910
05864da7
DS
9911 if (nexthop_vrfid == VRF_UNKNOWN) {
9912 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9913 } else {
05864da7
DS
9914 json_object_int_add(json_path, "nhVrfId",
9915 (int)nexthop_vrfid);
9df8b37c 9916 }
05864da7
DS
9917 } else {
9918 if (nexthop_vrfid == VRF_UNKNOWN)
9919 vty_out(vty, " vrf ?");
137147c6
DS
9920 else {
9921 struct vrf *vrf;
9922
9923 vrf = vrf_lookup_by_id(nexthop_vrfid);
9924 vty_out(vty, " vrf %s(%u)",
9925 VRF_LOGNAME(vrf), nexthop_vrfid);
9926 }
9df8b37c 9927 }
05864da7 9928 }
9df8b37c 9929
05864da7
DS
9930 if (nexthop_self) {
9931 if (json_paths) {
9932 json_object_boolean_true_add(json_path,
9933 "announceNexthopSelf");
9934 } else {
9935 vty_out(vty, " announce-nh-self");
9df8b37c 9936 }
05864da7 9937 }
9df8b37c 9938
05864da7
DS
9939 if (!json_paths)
9940 vty_out(vty, "\n");
d62a17ae 9941
05864da7
DS
9942 /* display the link-local nexthop */
9943 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9944 if (json_paths) {
9945 json_nexthop_ll = json_object_new_object();
9946 json_object_string_add(
515c2602
DA
9947 json_nexthop_ll, "ip",
9948 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9949 buf, INET6_ADDRSTRLEN));
9950
939a97f4 9951 if (path->peer->hostname)
515c2602
DA
9952 json_object_string_add(json_nexthop_ll,
9953 "hostname",
939a97f4 9954 path->peer->hostname);
515c2602 9955
05864da7
DS
9956 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9957 json_object_string_add(json_nexthop_ll, "scope",
9958 "link-local");
d62a17ae 9959
05864da7
DS
9960 json_object_boolean_true_add(json_nexthop_ll,
9961 "accessible");
d62a17ae 9962
05864da7 9963 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9964 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9965 "used");
9966 else
9967 json_object_boolean_true_add(
9968 json_nexthop_global, "used");
9969 } else {
9970 vty_out(vty, " (%s) %s\n",
9971 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9972 buf, INET6_ADDRSTRLEN),
9973 attr->mp_nexthop_prefer_global
9974 ? "(prefer-global)"
9975 : "(used)");
d62a17ae 9976 }
05864da7
DS
9977 }
9978 /* If we do not have a link-local nexthop then we must flag the
9979 global as "used" */
9980 else {
9981 if (json_paths)
9982 json_object_boolean_true_add(json_nexthop_global,
9983 "used");
9984 }
d62a17ae 9985
b5e140c8 9986 if (safi == SAFI_EVPN &&
5e4d4c8a 9987 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9988 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
9989 }
9990
05864da7
DS
9991 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9992 * Int/Ext/Local, Atomic, best */
9993 if (json_paths)
9994 json_object_string_add(json_path, "origin",
9995 bgp_origin_long_str[attr->origin]);
9996 else
9997 vty_out(vty, " Origin %s",
9998 bgp_origin_long_str[attr->origin]);
9df8b37c 9999
05864da7 10000 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10001 if (json_paths)
05864da7 10002 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10003 else
05864da7
DS
10004 vty_out(vty, ", metric %u", attr->med);
10005 }
9df8b37c 10006
05864da7
DS
10007 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10008 if (json_paths)
0fbac0b4 10009 json_object_int_add(json_path, "locPrf",
05864da7
DS
10010 attr->local_pref);
10011 else
10012 vty_out(vty, ", localpref %u", attr->local_pref);
10013 }
9df8b37c 10014
05864da7
DS
10015 if (attr->weight != 0) {
10016 if (json_paths)
10017 json_object_int_add(json_path, "weight", attr->weight);
10018 else
10019 vty_out(vty, ", weight %u", attr->weight);
10020 }
9df8b37c 10021
05864da7
DS
10022 if (attr->tag != 0) {
10023 if (json_paths)
10024 json_object_int_add(json_path, "tag", attr->tag);
10025 else
10026 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10027 }
9df8b37c 10028
05864da7
DS
10029 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10030 if (json_paths)
10031 json_object_boolean_false_add(json_path, "valid");
10032 else
10033 vty_out(vty, ", invalid");
10034 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10035 if (json_paths)
10036 json_object_boolean_true_add(json_path, "valid");
10037 else
10038 vty_out(vty, ", valid");
10039 }
9df8b37c 10040
05864da7
DS
10041 if (path->peer != bgp->peer_self) {
10042 if (path->peer->as == path->peer->local_as) {
10043 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10044 if (json_paths)
10045 json_object_string_add(
10046 json_peer, "type",
10047 "confed-internal");
d62a17ae 10048 else
05864da7 10049 vty_out(vty, ", confed-internal");
d62a17ae 10050 } else {
05864da7
DS
10051 if (json_paths)
10052 json_object_string_add(
10053 json_peer, "type", "internal");
10054 else
10055 vty_out(vty, ", internal");
9df8b37c 10056 }
05864da7
DS
10057 } else {
10058 if (bgp_confederation_peers_check(bgp,
10059 path->peer->as)) {
10060 if (json_paths)
10061 json_object_string_add(
10062 json_peer, "type",
10063 "confed-external");
d62a17ae 10064 else
05864da7 10065 vty_out(vty, ", confed-external");
d62a17ae 10066 } else {
05864da7
DS
10067 if (json_paths)
10068 json_object_string_add(
10069 json_peer, "type", "external");
10070 else
10071 vty_out(vty, ", external");
d62a17ae 10072 }
10073 }
05864da7
DS
10074 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10075 if (json_paths) {
10076 json_object_boolean_true_add(json_path, "aggregated");
10077 json_object_boolean_true_add(json_path, "local");
10078 } else {
10079 vty_out(vty, ", aggregated, local");
10080 }
10081 } else if (path->type != ZEBRA_ROUTE_BGP) {
10082 if (json_paths)
10083 json_object_boolean_true_add(json_path, "sourced");
10084 else
10085 vty_out(vty, ", sourced");
10086 } else {
10087 if (json_paths) {
10088 json_object_boolean_true_add(json_path, "sourced");
10089 json_object_boolean_true_add(json_path, "local");
10090 } else {
10091 vty_out(vty, ", sourced, local");
d62a17ae 10092 }
05864da7 10093 }
718e3744 10094
05864da7 10095 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10096 if (json_paths)
05864da7
DS
10097 json_object_boolean_true_add(json_path,
10098 "atomicAggregate");
d62a17ae 10099 else
05864da7
DS
10100 vty_out(vty, ", atomic-aggregate");
10101 }
d62a17ae 10102
05864da7
DS
10103 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10104 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10105 && bgp_path_info_mpath_count(path))) {
10106 if (json_paths)
10107 json_object_boolean_true_add(json_path, "multipath");
10108 else
10109 vty_out(vty, ", multipath");
10110 }
50e05855 10111
05864da7
DS
10112 // Mark the bestpath(s)
10113 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10114 first_as = aspath_get_first_as(attr->aspath);
718e3744 10115
05864da7
DS
10116 if (json_paths) {
10117 if (!json_bestpath)
10118 json_bestpath = json_object_new_object();
10119 json_object_int_add(json_bestpath, "bestpathFromAs",
10120 first_as);
10121 } else {
10122 if (first_as)
10123 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10124 else
05864da7 10125 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10126 }
05864da7 10127 }
718e3744 10128
05864da7
DS
10129 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10130 if (json_paths) {
10131 if (!json_bestpath)
10132 json_bestpath = json_object_new_object();
10133 json_object_boolean_true_add(json_bestpath, "overall");
10134 json_object_string_add(
10135 json_bestpath, "selectionReason",
10136 bgp_path_selection_reason2str(bn->reason));
10137 } else {
10138 vty_out(vty, ", best");
10139 vty_out(vty, " (%s)",
10140 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10141 }
05864da7 10142 }
718e3744 10143
05864da7
DS
10144 if (json_bestpath)
10145 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10146
05864da7
DS
10147 if (!json_paths)
10148 vty_out(vty, "\n");
10149
10150 /* Line 4 display Community */
10151 if (attr->community) {
10152 if (json_paths) {
10153 if (!attr->community->json)
10154 community_str(attr->community, true);
10155 json_object_lock(attr->community->json);
10156 json_object_object_add(json_path, "community",
10157 attr->community->json);
10158 } else {
10159 vty_out(vty, " Community: %s\n",
10160 attr->community->str);
d62a17ae 10161 }
05864da7 10162 }
718e3744 10163
05864da7
DS
10164 /* Line 5 display Extended-community */
10165 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10166 if (json_paths) {
10167 json_ext_community = json_object_new_object();
10168 json_object_string_add(json_ext_community, "string",
10169 attr->ecommunity->str);
10170 json_object_object_add(json_path, "extendedCommunity",
10171 json_ext_community);
d62a17ae 10172 } else {
05864da7
DS
10173 vty_out(vty, " Extended Community: %s\n",
10174 attr->ecommunity->str);
d62a17ae 10175 }
05864da7 10176 }
718e3744 10177
05864da7
DS
10178 /* Line 6 display Large community */
10179 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10180 if (json_paths) {
10181 if (!attr->lcommunity->json)
10182 lcommunity_str(attr->lcommunity, true);
10183 json_object_lock(attr->lcommunity->json);
10184 json_object_object_add(json_path, "largeCommunity",
10185 attr->lcommunity->json);
10186 } else {
10187 vty_out(vty, " Large Community: %s\n",
10188 attr->lcommunity->str);
d62a17ae 10189 }
05864da7 10190 }
718e3744 10191
05864da7
DS
10192 /* Line 7 display Originator, Cluster-id */
10193 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10194 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10195 char buf[BUFSIZ] = {0};
10196
05864da7 10197 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10198 if (json_paths)
05864da7
DS
10199 json_object_string_add(
10200 json_path, "originatorId",
23d0a753
DA
10201 inet_ntop(AF_INET, &attr->originator_id,
10202 buf, sizeof(buf)));
d62a17ae 10203 else
23d0a753
DA
10204 vty_out(vty, " Originator: %pI4",
10205 &attr->originator_id);
d62a17ae 10206 }
856ca177 10207
05864da7 10208 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10209 struct cluster_list *cluster =
10210 bgp_attr_get_cluster(attr);
05864da7 10211 int i;
d62a17ae 10212
10213 if (json_paths) {
05864da7
DS
10214 json_cluster_list = json_object_new_object();
10215 json_cluster_list_list =
10216 json_object_new_array();
10217
779fee93 10218 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10219 json_string = json_object_new_string(
779fee93
DS
10220 inet_ntop(AF_INET,
10221 &cluster->list[i],
10222 buf, sizeof(buf)));
05864da7
DS
10223 json_object_array_add(
10224 json_cluster_list_list,
10225 json_string);
10226 }
718e3744 10227
05864da7
DS
10228 /*
10229 * struct cluster_list does not have
10230 * "str" variable like aspath and community
10231 * do. Add this someday if someone asks
10232 * for it.
10233 * json_object_string_add(json_cluster_list,
779fee93 10234 * "string", cluster->str);
05864da7
DS
10235 */
10236 json_object_object_add(json_cluster_list,
10237 "list",
10238 json_cluster_list_list);
10239 json_object_object_add(json_path, "clusterList",
10240 json_cluster_list);
0dc8ee70 10241 } else {
05864da7
DS
10242 vty_out(vty, ", Cluster list: ");
10243
779fee93 10244 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10245 vty_out(vty, "%pI4 ",
779fee93 10246 &cluster->list[i]);
05864da7 10247 }
0dc8ee70 10248 }
d62a17ae 10249 }
718e3744 10250
d62a17ae 10251 if (!json_paths)
10252 vty_out(vty, "\n");
05864da7 10253 }
d62a17ae 10254
05864da7 10255 if (path->extra && path->extra->damp_info)
40ec3340 10256 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10257
05864da7
DS
10258 /* Remote Label */
10259 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10260 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10261 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10262
05864da7
DS
10263 if (json_paths)
10264 json_object_int_add(json_path, "remoteLabel", label);
10265 else
10266 vty_out(vty, " Remote label: %d\n", label);
10267 }
d62a17ae 10268
e496b420
HS
10269 /* Remote SID */
10270 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10271 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10272 if (json_paths)
10273 json_object_string_add(json_path, "remoteSid", buf);
10274 else
10275 vty_out(vty, " Remote SID: %s\n", buf);
10276 }
10277
05864da7
DS
10278 /* Label Index */
10279 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10280 if (json_paths)
10281 json_object_int_add(json_path, "labelIndex",
10282 attr->label_index);
10283 else
10284 vty_out(vty, " Label Index: %d\n",
10285 attr->label_index);
10286 }
d62a17ae 10287
05864da7
DS
10288 /* Line 8 display Addpath IDs */
10289 if (path->addpath_rx_id
10290 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10291 if (json_paths) {
10292 json_object_int_add(json_path, "addpathRxId",
10293 path->addpath_rx_id);
d62a17ae 10294
05864da7
DS
10295 /* Keep backwards compatibility with the old API
10296 * by putting TX All's ID in the old field
10297 */
10298 json_object_int_add(
10299 json_path, "addpathTxId",
10300 path->tx_addpath
10301 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10302
05864da7
DS
10303 /* ... but create a specific field for each
10304 * strategy
10305 */
10306 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10307 json_object_int_add(
10308 json_path,
10309 bgp_addpath_names(i)->id_json_name,
10310 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10311 }
05864da7
DS
10312 } else {
10313 vty_out(vty, " AddPath ID: RX %u, ",
10314 path->addpath_rx_id);
d62a17ae 10315
05864da7 10316 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10317 }
05864da7 10318 }
520d5d76 10319
05864da7
DS
10320 /* If we used addpath to TX a non-bestpath we need to display
10321 * "Advertised to" on a path-by-path basis
10322 */
10323 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10324 first = 1;
dcc68b5e 10325
05864da7
DS
10326 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10327 addpath_capable =
10328 bgp_addpath_encode_tx(peer, afi, safi);
10329 has_adj = bgp_adj_out_lookup(
10330 peer, path->net,
10331 bgp_addpath_id_for_peer(peer, afi, safi,
10332 &path->tx_addpath));
10333
10334 if ((addpath_capable && has_adj)
10335 || (!addpath_capable && has_adj
10336 && CHECK_FLAG(path->flags,
10337 BGP_PATH_SELECTED))) {
10338 if (json_path && !json_adv_to)
10339 json_adv_to = json_object_new_object();
dcc68b5e 10340
05864da7
DS
10341 route_vty_out_advertised_to(
10342 vty, peer, &first,
10343 " Advertised to:", json_adv_to);
d62a17ae 10344 }
10345 }
718e3744 10346
05864da7
DS
10347 if (json_path) {
10348 if (json_adv_to) {
10349 json_object_object_add(
10350 json_path, "advertisedTo", json_adv_to);
d62a17ae 10351 }
05864da7
DS
10352 } else {
10353 if (!first) {
10354 vty_out(vty, "\n");
d62a17ae 10355 }
10356 }
05864da7 10357 }
b05a1c8b 10358
05864da7
DS
10359 /* Line 9 display Uptime */
10360 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10361 if (json_paths) {
10362 json_last_update = json_object_new_object();
10363 json_object_int_add(json_last_update, "epoch", tbuf);
10364 json_object_string_add(json_last_update, "string",
10365 ctime(&tbuf));
10366 json_object_object_add(json_path, "lastUpdate",
10367 json_last_update);
10368 } else
10369 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10370
05864da7
DS
10371 /* Line 10 display PMSI tunnel attribute, if present */
10372 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10373 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10374 bgp_attr_get_pmsi_tnl_type(attr),
10375 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10376
05864da7
DS
10377 if (json_paths) {
10378 json_pmsi = json_object_new_object();
10379 json_object_string_add(json_pmsi, "tunnelType", str);
10380 json_object_int_add(json_pmsi, "label",
10381 label2vni(&attr->label));
10382 json_object_object_add(json_path, "pmsi", json_pmsi);
10383 } else
10384 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10385 str, label2vni(&attr->label));
d62a17ae 10386 }
f1aa5d8a 10387
92269aa2
DS
10388 /* Output some debug about internal state of the dest flags */
10389 if (json_paths) {
10390 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10391 json_object_boolean_true_add(json_path, "processScheduled");
10392 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10393 json_object_boolean_true_add(json_path, "userCleared");
10394 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10395 json_object_boolean_true_add(json_path, "labelChanged");
10396 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10397 json_object_boolean_true_add(json_path, "registeredForLabel");
10398 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10399 json_object_boolean_true_add(json_path, "selectDefered");
10400 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10401 json_object_boolean_true_add(json_path, "fibInstalled");
10402 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10403 json_object_boolean_true_add(json_path, "fibPending");
10404 }
10405
d62a17ae 10406 /* We've constructed the json object for this path, add it to the json
10407 * array of paths
10408 */
10409 if (json_paths) {
10410 if (json_nexthop_global || json_nexthop_ll) {
10411 json_nexthops = json_object_new_array();
f1aa5d8a 10412
d62a17ae 10413 if (json_nexthop_global)
10414 json_object_array_add(json_nexthops,
10415 json_nexthop_global);
f1aa5d8a 10416
d62a17ae 10417 if (json_nexthop_ll)
10418 json_object_array_add(json_nexthops,
10419 json_nexthop_ll);
f1aa5d8a 10420
d62a17ae 10421 json_object_object_add(json_path, "nexthops",
10422 json_nexthops);
10423 }
10424
10425 json_object_object_add(json_path, "peer", json_peer);
10426 json_object_array_add(json_paths, json_path);
05864da7 10427 }
b366b518
BB
10428}
10429
96ade3ed 10430#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10431#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10432#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10433
d62a17ae 10434static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10435 const char *prefix_list_str, afi_t afi,
10436 safi_t safi, enum bgp_show_type type);
10437static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10438 const char *filter, afi_t afi, safi_t safi,
10439 enum bgp_show_type type);
10440static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10441 const char *rmap_str, afi_t afi, safi_t safi,
10442 enum bgp_show_type type);
10443static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10444 const char *com, int exact, afi_t afi,
10445 safi_t safi);
10446static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10447 const char *prefix, afi_t afi, safi_t safi,
10448 enum bgp_show_type type);
a4d82a8a 10449static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10450 afi_t afi, safi_t safi, enum bgp_show_type type,
10451 bool use_json);
7f323236
DW
10452static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10453 const char *comstr, int exact, afi_t afi,
96f3485c 10454 safi_t safi, uint8_t show_flags);
d62a17ae 10455
1ae44dfc
LB
10456
10457static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10458 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10459 void *output_arg, char *rd, int is_last,
10460 unsigned long *output_cum, unsigned long *total_cum,
10461 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10462{
40381db7 10463 struct bgp_path_info *pi;
9bcb3eef 10464 struct bgp_dest *dest;
d62a17ae 10465 int header = 1;
10466 int display;
1ae44dfc
LB
10467 unsigned long output_count = 0;
10468 unsigned long total_count = 0;
d62a17ae 10469 struct prefix *p;
d62a17ae 10470 json_object *json_paths = NULL;
10471 int first = 1;
96f3485c
MK
10472 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10473 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10474 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10475
1ae44dfc
LB
10476 if (output_cum && *output_cum != 0)
10477 header = 0;
10478
9386b588 10479 if (use_json && !*json_header_depth) {
96f3485c
MK
10480 if (all)
10481 *json_header_depth = 1;
10482 else {
10483 vty_out(vty, "{\n");
10484 *json_header_depth = 2;
10485 }
10486
d62a17ae 10487 vty_out(vty,
23d0a753
DA
10488 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10489 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10490 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10491 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10492 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10493 ? VRF_DEFAULT_NAME
10494 : bgp->name,
10495 table->version, &bgp->router_id,
01eced22 10496 bgp->default_local_pref, bgp->as);
9386b588 10497 if (rd) {
445c2480 10498 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10499 ++*json_header_depth;
10500 }
d62a17ae 10501 }
718e3744 10502
445c2480
DS
10503 if (use_json && rd) {
10504 vty_out(vty, " \"%s\" : { ", rd);
10505 }
10506
d62a17ae 10507 /* Start processing of routes. */
9bcb3eef
DS
10508 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10509 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10510
9bcb3eef 10511 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10512 if (pi == NULL)
98ce9a06 10513 continue;
d62a17ae 10514
98ce9a06 10515 display = 0;
98ce9a06
DS
10516 if (use_json)
10517 json_paths = json_object_new_array();
10518 else
10519 json_paths = NULL;
d62a17ae 10520
6f94b685 10521 for (; pi; pi = pi->next) {
98ce9a06
DS
10522 total_count++;
10523 if (type == bgp_show_type_flap_statistics
10524 || type == bgp_show_type_flap_neighbor
10525 || type == bgp_show_type_dampend_paths
10526 || type == bgp_show_type_damp_neighbor) {
40381db7 10527 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10528 continue;
10529 }
10530 if (type == bgp_show_type_regexp) {
10531 regex_t *regex = output_arg;
d62a17ae 10532
40381db7 10533 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10534 == REG_NOMATCH)
10535 continue;
10536 }
10537 if (type == bgp_show_type_prefix_list) {
10538 struct prefix_list *plist = output_arg;
d62a17ae 10539
9bcb3eef 10540 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10541 != PREFIX_PERMIT)
10542 continue;
10543 }
10544 if (type == bgp_show_type_filter_list) {
10545 struct as_list *as_list = output_arg;
d62a17ae 10546
40381db7 10547 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10548 != AS_FILTER_PERMIT)
10549 continue;
10550 }
10551 if (type == bgp_show_type_route_map) {
10552 struct route_map *rmap = output_arg;
9b6d8fcf 10553 struct bgp_path_info path;
98ce9a06 10554 struct attr dummy_attr;
b68885f9 10555 route_map_result_t ret;
d62a17ae 10556
6f4f49b2 10557 dummy_attr = *pi->attr;
d62a17ae 10558
40381db7 10559 path.peer = pi->peer;
9b6d8fcf 10560 path.attr = &dummy_attr;
d62a17ae 10561
1782514f 10562 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10563 if (ret == RMAP_DENYMATCH)
10564 continue;
10565 }
10566 if (type == bgp_show_type_neighbor
10567 || type == bgp_show_type_flap_neighbor
10568 || type == bgp_show_type_damp_neighbor) {
10569 union sockunion *su = output_arg;
10570
40381db7
DS
10571 if (pi->peer == NULL
10572 || pi->peer->su_remote == NULL
10573 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10574 continue;
10575 }
10576 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10577 uint32_t destination;
d62a17ae 10578
9bcb3eef 10579 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10580 if (IN_CLASSC(destination)
9bcb3eef 10581 && dest_p->prefixlen == 24)
98ce9a06
DS
10582 continue;
10583 if (IN_CLASSB(destination)
9bcb3eef 10584 && dest_p->prefixlen == 16)
98ce9a06
DS
10585 continue;
10586 if (IN_CLASSA(destination)
9bcb3eef 10587 && dest_p->prefixlen == 8)
98ce9a06
DS
10588 continue;
10589 }
10590 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10591 p = output_arg;
9bcb3eef 10592 if (!prefix_match(p, dest_p))
98ce9a06
DS
10593 continue;
10594 }
10595 if (type == bgp_show_type_community_all) {
40381db7 10596 if (!pi->attr->community)
98ce9a06
DS
10597 continue;
10598 }
10599 if (type == bgp_show_type_community) {
10600 struct community *com = output_arg;
d62a17ae 10601
40381db7
DS
10602 if (!pi->attr->community
10603 || !community_match(pi->attr->community,
98ce9a06
DS
10604 com))
10605 continue;
10606 }
10607 if (type == bgp_show_type_community_exact) {
10608 struct community *com = output_arg;
d62a17ae 10609
40381db7
DS
10610 if (!pi->attr->community
10611 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10612 continue;
10613 }
10614 if (type == bgp_show_type_community_list) {
10615 struct community_list *list = output_arg;
d62a17ae 10616
40381db7 10617 if (!community_list_match(pi->attr->community,
a4d82a8a 10618 list))
98ce9a06
DS
10619 continue;
10620 }
a4d82a8a 10621 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10622 struct community_list *list = output_arg;
d62a17ae 10623
98ce9a06 10624 if (!community_list_exact_match(
40381db7 10625 pi->attr->community, list))
98ce9a06
DS
10626 continue;
10627 }
10628 if (type == bgp_show_type_lcommunity) {
10629 struct lcommunity *lcom = output_arg;
d62a17ae 10630
40381db7
DS
10631 if (!pi->attr->lcommunity
10632 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10633 lcom))
10634 continue;
10635 }
36a206db 10636
10637 if (type == bgp_show_type_lcommunity_exact) {
10638 struct lcommunity *lcom = output_arg;
10639
10640 if (!pi->attr->lcommunity
10641 || !lcommunity_cmp(pi->attr->lcommunity,
10642 lcom))
10643 continue;
10644 }
98ce9a06
DS
10645 if (type == bgp_show_type_lcommunity_list) {
10646 struct community_list *list = output_arg;
d62a17ae 10647
40381db7 10648 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10649 list))
98ce9a06
DS
10650 continue;
10651 }
36a206db 10652 if (type
10653 == bgp_show_type_lcommunity_list_exact) {
10654 struct community_list *list = output_arg;
10655
10656 if (!lcommunity_list_exact_match(
10657 pi->attr->lcommunity, list))
10658 continue;
10659 }
98ce9a06 10660 if (type == bgp_show_type_lcommunity_all) {
40381db7 10661 if (!pi->attr->lcommunity)
98ce9a06
DS
10662 continue;
10663 }
10664 if (type == bgp_show_type_dampend_paths
10665 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10666 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10667 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10668 continue;
10669 }
10670
10671 if (!use_json && header) {
23d0a753
DA
10672 vty_out(vty,
10673 "BGP table version is %" PRIu64
10674 ", local router ID is %pI4, vrf id ",
10675 table->version, &bgp->router_id);
9df8b37c
PZ
10676 if (bgp->vrf_id == VRF_UNKNOWN)
10677 vty_out(vty, "%s", VRFID_NONE_STR);
10678 else
10679 vty_out(vty, "%u", bgp->vrf_id);
10680 vty_out(vty, "\n");
01eced22
AD
10681 vty_out(vty, "Default local pref %u, ",
10682 bgp->default_local_pref);
10683 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10684 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10685 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10686 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10687 if (type == bgp_show_type_dampend_paths
10688 || type == bgp_show_type_damp_neighbor)
98ce9a06 10689 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10690 else if (type == bgp_show_type_flap_statistics
10691 || type == bgp_show_type_flap_neighbor)
98ce9a06 10692 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10693 else
ae248832
MK
10694 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10695 : BGP_SHOW_HEADER));
98ce9a06 10696 header = 0;
d62a17ae 10697 }
98ce9a06
DS
10698 if (rd != NULL && !display && !output_count) {
10699 if (!use_json)
10700 vty_out(vty,
10701 "Route Distinguisher: %s\n",
10702 rd);
d62a17ae 10703 }
98ce9a06
DS
10704 if (type == bgp_show_type_dampend_paths
10705 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10706 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10707 AFI_IP, safi, use_json,
10708 json_paths);
98ce9a06
DS
10709 else if (type == bgp_show_type_flap_statistics
10710 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10711 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10712 AFI_IP, safi, use_json,
10713 json_paths);
98ce9a06 10714 else
9bcb3eef 10715 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10716 json_paths, wide);
98ce9a06 10717 display++;
d62a17ae 10718 }
10719
98ce9a06
DS
10720 if (display) {
10721 output_count++;
10722 if (!use_json)
10723 continue;
10724
625d2931 10725 /* encode prefix */
9bcb3eef 10726 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10727 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10728
1840384b 10729
b54892e0
DS
10730 bgp_fs_nlri_get_string(
10731 (unsigned char *)
9bcb3eef
DS
10732 dest_p->u.prefix_flowspec.ptr,
10733 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10734 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10735 family2afi(dest_p->u
10736 .prefix_flowspec.family));
625d2931 10737 if (first)
b54892e0 10738 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10739 dest_p->u.prefix_flowspec
b54892e0 10740 .prefixlen);
625d2931 10741 else
b54892e0 10742 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10743 dest_p->u.prefix_flowspec
b54892e0 10744 .prefixlen);
625d2931 10745 } else {
625d2931 10746 if (first)
1b78780b 10747 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10748 else
1b78780b 10749 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10750 }
98ce9a06 10751 vty_out(vty, "%s",
f4ec52f7
DA
10752 json_object_to_json_string_ext(
10753 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10754 json_object_free(json_paths);
449feb8e 10755 json_paths = NULL;
98ce9a06 10756 first = 0;
1f83ed02
DS
10757 } else
10758 json_object_free(json_paths);
98ce9a06
DS
10759 }
10760
1ae44dfc
LB
10761 if (output_cum) {
10762 output_count += *output_cum;
10763 *output_cum = output_count;
10764 }
10765 if (total_cum) {
10766 total_count += *total_cum;
10767 *total_cum = total_count;
10768 }
d62a17ae 10769 if (use_json) {
9386b588 10770 if (rd) {
a4d82a8a 10771 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10772 }
10773 if (is_last) {
a4d82a8a
PZ
10774 unsigned long i;
10775 for (i = 0; i < *json_header_depth; ++i)
10776 vty_out(vty, " } ");
96f3485c
MK
10777 if (!all)
10778 vty_out(vty, "\n");
9386b588 10779 }
d62a17ae 10780 } else {
1ae44dfc
LB
10781 if (is_last) {
10782 /* No route is displayed */
10783 if (output_count == 0) {
10784 if (type == bgp_show_type_normal)
10785 vty_out(vty,
10786 "No BGP prefixes displayed, %ld exist\n",
10787 total_count);
10788 } else
d62a17ae 10789 vty_out(vty,
1ae44dfc
LB
10790 "\nDisplayed %ld routes and %ld total paths\n",
10791 output_count, total_count);
10792 }
d62a17ae 10793 }
718e3744 10794
d62a17ae 10795 return CMD_SUCCESS;
718e3744 10796}
10797
1ae44dfc
LB
10798int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10799 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10800 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10801{
9bcb3eef 10802 struct bgp_dest *dest, *next;
1ae44dfc
LB
10803 unsigned long output_cum = 0;
10804 unsigned long total_cum = 0;
9386b588 10805 unsigned long json_header_depth = 0;
67009e22 10806 struct bgp_table *itable;
0136788c 10807 bool show_msg;
96f3485c 10808 uint8_t show_flags = 0;
0136788c
LB
10809
10810 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10811
96f3485c
MK
10812 if (use_json)
10813 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10814
9bcb3eef
DS
10815 for (dest = bgp_table_top(table); dest; dest = next) {
10816 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10817
9bcb3eef
DS
10818 next = bgp_route_next(dest);
10819 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10820 continue;
67009e22 10821
9bcb3eef 10822 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10823 if (itable != NULL) {
1ae44dfc 10824 struct prefix_rd prd;
06b9f471 10825 char rd[RD_ADDRSTRLEN];
1ae44dfc 10826
9bcb3eef 10827 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10828 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10829 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10830 rd, next == NULL, &output_cum,
10831 &total_cum, &json_header_depth,
10832 show_flags);
0136788c
LB
10833 if (next == NULL)
10834 show_msg = false;
1ae44dfc
LB
10835 }
10836 }
0136788c
LB
10837 if (show_msg) {
10838 if (output_cum == 0)
10839 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10840 total_cum);
10841 else
10842 vty_out(vty,
10843 "\nDisplayed %ld routes and %ld total paths\n",
10844 output_cum, total_cum);
10845 }
1ae44dfc
LB
10846 return CMD_SUCCESS;
10847}
d62a17ae 10848static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10849 enum bgp_show_type type, void *output_arg,
10850 uint8_t show_flags)
fee0f4c6 10851{
d62a17ae 10852 struct bgp_table *table;
9386b588 10853 unsigned long json_header_depth = 0;
96f3485c 10854 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10855
d62a17ae 10856 if (bgp == NULL) {
10857 bgp = bgp_get_default();
10858 }
fee0f4c6 10859
d62a17ae 10860 if (bgp == NULL) {
10861 if (!use_json)
10862 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10863 else
10864 vty_out(vty, "{}\n");
d62a17ae 10865 return CMD_WARNING;
10866 }
4dd6177e 10867
1ae44dfc 10868 table = bgp->rib[afi][safi];
d62a17ae 10869 /* use MPLS and ENCAP specific shows until they are merged */
10870 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10871 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10872 output_arg, use_json);
d62a17ae 10873 }
dba3c1d3
PG
10874
10875 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10876 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10877 output_arg, use_json,
10878 1, NULL, NULL);
10879 }
d62a17ae 10880 /* labeled-unicast routes live in the unicast table */
10881 else if (safi == SAFI_LABELED_UNICAST)
10882 safi = SAFI_UNICAST;
fee0f4c6 10883
96f3485c
MK
10884 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10885 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10886}
10887
d62a17ae 10888static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10889 safi_t safi, uint8_t show_flags)
f186de26 10890{
d62a17ae 10891 struct listnode *node, *nnode;
10892 struct bgp *bgp;
10893 int is_first = 1;
9f049418 10894 bool route_output = false;
96f3485c 10895 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10896
d62a17ae 10897 if (use_json)
10898 vty_out(vty, "{\n");
9f689658 10899
d62a17ae 10900 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10901 route_output = true;
d62a17ae 10902 if (use_json) {
10903 if (!is_first)
10904 vty_out(vty, ",\n");
10905 else
10906 is_first = 0;
10907
10908 vty_out(vty, "\"%s\":",
10909 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10910 ? VRF_DEFAULT_NAME
d62a17ae 10911 : bgp->name);
10912 } else {
10913 vty_out(vty, "\nInstance %s:\n",
10914 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10915 ? VRF_DEFAULT_NAME
d62a17ae 10916 : bgp->name);
10917 }
10918 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10919 show_flags);
d62a17ae 10920 }
9f689658 10921
d62a17ae 10922 if (use_json)
10923 vty_out(vty, "}\n");
9f049418
DS
10924 else if (!route_output)
10925 vty_out(vty, "%% BGP instance not found\n");
f186de26 10926}
10927
718e3744 10928/* Header of detailed BGP route information */
d62a17ae 10929void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10930 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10931 afi_t afi, safi_t safi, json_object *json)
10932{
40381db7 10933 struct bgp_path_info *pi;
b54892e0 10934 const struct prefix *p;
d62a17ae 10935 struct peer *peer;
10936 struct listnode *node, *nnode;
06b9f471 10937 char buf1[RD_ADDRSTRLEN];
0291c246 10938 char prefix_str[BUFSIZ];
d62a17ae 10939 int count = 0;
10940 int best = 0;
10941 int suppress = 0;
c5f1e1b2
C
10942 int accept_own = 0;
10943 int route_filter_translated_v4 = 0;
10944 int route_filter_v4 = 0;
10945 int route_filter_translated_v6 = 0;
10946 int route_filter_v6 = 0;
10947 int llgr_stale = 0;
10948 int no_llgr = 0;
10949 int accept_own_nexthop = 0;
10950 int blackhole = 0;
d62a17ae 10951 int no_export = 0;
10952 int no_advertise = 0;
10953 int local_as = 0;
c5f1e1b2 10954 int no_peer = 0;
d62a17ae 10955 int first = 1;
10956 int has_valid_label = 0;
10957 mpls_label_t label = 0;
10958 json_object *json_adv_to = NULL;
9bedbb1e 10959
9bcb3eef
DS
10960 p = bgp_dest_get_prefix(dest);
10961 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10962
10963 if (has_valid_label)
9bcb3eef 10964 label = label_pton(&dest->local_label);
d62a17ae 10965
44c69747 10966 if (safi == SAFI_EVPN) {
d62a17ae 10967
44c69747 10968 if (!json) {
2dbe669b 10969 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 10970 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 10971 : "",
2dbe669b 10972 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
10973 } else {
10974 json_object_string_add(json, "rd",
10975 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10976 "");
10977 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10978 }
10979 } else {
10980 if (!json) {
8228a9a7 10981 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 10982 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
10983 ? prefix_rd2str(prd, buf1,
10984 sizeof(buf1))
10985 : ""),
10986 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 10987
44c69747
LK
10988 } else
10989 json_object_string_add(json, "prefix",
10990 prefix2str(p, prefix_str, sizeof(prefix_str)));
10991 }
10992
10993 if (has_valid_label) {
10994 if (json)
10995 json_object_int_add(json, "localLabel", label);
10996 else
d62a17ae 10997 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10998 }
10999
11000 if (!json)
d62a17ae 11001 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11002 vty_out(vty, "not allocated\n");
718e3744 11003
9bcb3eef 11004 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11005 count++;
40381db7 11006 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11007 best = count;
4056a5f6 11008 if (bgp_path_suppressed(pi))
d62a17ae 11009 suppress = 1;
cee9c031 11010
40381db7 11011 if (pi->attr->community == NULL)
cee9c031
QY
11012 continue;
11013
11014 no_advertise += community_include(
40381db7
DS
11015 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11016 no_export += community_include(pi->attr->community,
cee9c031 11017 COMMUNITY_NO_EXPORT);
40381db7 11018 local_as += community_include(pi->attr->community,
cee9c031 11019 COMMUNITY_LOCAL_AS);
40381db7 11020 accept_own += community_include(pi->attr->community,
cee9c031
QY
11021 COMMUNITY_ACCEPT_OWN);
11022 route_filter_translated_v4 += community_include(
40381db7 11023 pi->attr->community,
cee9c031
QY
11024 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11025 route_filter_translated_v6 += community_include(
40381db7 11026 pi->attr->community,
cee9c031
QY
11027 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11028 route_filter_v4 += community_include(
40381db7 11029 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11030 route_filter_v6 += community_include(
40381db7
DS
11031 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11032 llgr_stale += community_include(pi->attr->community,
cee9c031 11033 COMMUNITY_LLGR_STALE);
40381db7 11034 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11035 COMMUNITY_NO_LLGR);
11036 accept_own_nexthop +=
40381db7 11037 community_include(pi->attr->community,
cee9c031 11038 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11039 blackhole += community_include(pi->attr->community,
cee9c031 11040 COMMUNITY_BLACKHOLE);
40381db7 11041 no_peer += community_include(pi->attr->community,
cee9c031 11042 COMMUNITY_NO_PEER);
d62a17ae 11043 }
718e3744 11044 }
718e3744 11045
d62a17ae 11046 if (!json) {
11047 vty_out(vty, "Paths: (%d available", count);
11048 if (best) {
11049 vty_out(vty, ", best #%d", best);
b84060bb
PG
11050 if (safi == SAFI_UNICAST) {
11051 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11052 vty_out(vty, ", table %s",
11053 VRF_DEFAULT_NAME);
11054 else
11055 vty_out(vty, ", vrf %s",
11056 bgp->name);
11057 }
d62a17ae 11058 } else
11059 vty_out(vty, ", no best path");
11060
c5f1e1b2
C
11061 if (accept_own)
11062 vty_out(vty,
11063 ", accept own local route exported and imported in different VRF");
11064 else if (route_filter_translated_v4)
11065 vty_out(vty,
11066 ", mark translated RTs for VPNv4 route filtering");
11067 else if (route_filter_v4)
11068 vty_out(vty,
11069 ", attach RT as-is for VPNv4 route filtering");
11070 else if (route_filter_translated_v6)
11071 vty_out(vty,
11072 ", mark translated RTs for VPNv6 route filtering");
11073 else if (route_filter_v6)
11074 vty_out(vty,
11075 ", attach RT as-is for VPNv6 route filtering");
11076 else if (llgr_stale)
11077 vty_out(vty,
11078 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11079 else if (no_llgr)
11080 vty_out(vty,
11081 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11082 else if (accept_own_nexthop)
11083 vty_out(vty,
11084 ", accept local nexthop");
11085 else if (blackhole)
11086 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11087 else if (no_export)
11088 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11089 else if (no_advertise)
11090 vty_out(vty, ", not advertised to any peer");
d62a17ae 11091 else if (local_as)
11092 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11093 else if (no_peer)
11094 vty_out(vty,
11095 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11096
11097 if (suppress)
11098 vty_out(vty,
11099 ", Advertisements suppressed by an aggregate.");
11100 vty_out(vty, ")\n");
11101 }
718e3744 11102
d62a17ae 11103 /* If we are not using addpath then we can display Advertised to and
11104 * that will
11105 * show what peers we advertised the bestpath to. If we are using
11106 * addpath
11107 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11108 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11109 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11110 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11111 if (json && !json_adv_to)
11112 json_adv_to = json_object_new_object();
11113
11114 route_vty_out_advertised_to(
11115 vty, peer, &first,
11116 " Advertised to non peer-group peers:\n ",
11117 json_adv_to);
11118 }
11119 }
11120
11121 if (json) {
11122 if (json_adv_to) {
11123 json_object_object_add(json, "advertisedTo",
11124 json_adv_to);
11125 }
11126 } else {
11127 if (first)
11128 vty_out(vty, " Not advertised to any peer");
11129 vty_out(vty, "\n");
11130 }
11131 }
718e3744 11132}
11133
44c69747 11134static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11135 struct bgp_dest *bgp_node, struct vty *vty,
11136 struct bgp *bgp, afi_t afi, safi_t safi,
11137 json_object *json, enum bgp_path_type pathtype,
11138 int *display)
44c69747
LK
11139{
11140 struct bgp_path_info *pi;
11141 int header = 1;
11142 char rdbuf[RD_ADDRSTRLEN];
11143 json_object *json_header = NULL;
11144 json_object *json_paths = NULL;
11145
9bcb3eef 11146 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
11147
11148 if (json && !json_paths) {
11149 /* Instantiate json_paths only if path is valid */
11150 json_paths = json_object_new_array();
11151 if (pfx_rd) {
11152 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11153 json_header = json_object_new_object();
11154 } else
11155 json_header = json;
11156 }
11157
11158 if (header) {
11159 route_vty_out_detail_header(
11160 vty, bgp, bgp_node, pfx_rd,
11161 AFI_IP, safi, json_header);
11162 header = 0;
11163 }
11164 (*display)++;
11165
11166 if (pathtype == BGP_PATH_SHOW_ALL
11167 || (pathtype == BGP_PATH_SHOW_BESTPATH
11168 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11169 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11170 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11171 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11172 route_vty_out_detail(vty, bgp, bgp_node,
11173 pi, AFI_IP, safi,
11174 json_paths);
11175 }
11176
11177 if (json && json_paths) {
11178 json_object_object_add(json_header, "paths", json_paths);
11179
11180 if (pfx_rd)
11181 json_object_object_add(json, rdbuf, json_header);
11182 }
11183}
11184
718e3744 11185/* Display specified route of BGP table. */
d62a17ae 11186static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11187 struct bgp_table *rib, const char *ip_str,
11188 afi_t afi, safi_t safi,
11189 struct prefix_rd *prd, int prefix_check,
9f049418 11190 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11191{
11192 int ret;
d62a17ae 11193 int display = 0;
11194 struct prefix match;
9bcb3eef
DS
11195 struct bgp_dest *dest;
11196 struct bgp_dest *rm;
d62a17ae 11197 struct bgp_table *table;
11198 json_object *json = NULL;
11199 json_object *json_paths = NULL;
11200
11201 /* Check IP address argument. */
11202 ret = str2prefix(ip_str, &match);
11203 if (!ret) {
11204 vty_out(vty, "address is malformed\n");
11205 return CMD_WARNING;
11206 }
718e3744 11207
d62a17ae 11208 match.family = afi2family(afi);
b05a1c8b 11209
44c69747 11210 if (use_json)
d62a17ae 11211 json = json_object_new_object();
718e3744 11212
44c69747 11213 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11214 for (dest = bgp_table_top(rib); dest;
11215 dest = bgp_route_next(dest)) {
11216 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11217
9bcb3eef 11218 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11219 continue;
9bcb3eef 11220 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11221 if (!table)
ea47320b 11222 continue;
d62a17ae 11223
ea47320b
DL
11224 if ((rm = bgp_node_match(table, &match)) == NULL)
11225 continue;
d62a17ae 11226
9bcb3eef 11227 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11228 if (prefix_check
b54892e0 11229 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11230 bgp_dest_unlock_node(rm);
ea47320b
DL
11231 continue;
11232 }
d62a17ae 11233
9bcb3eef 11234 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11235 bgp, afi, safi, json, pathtype,
11236 &display);
44c69747 11237
9bcb3eef 11238 bgp_dest_unlock_node(rm);
44c69747
LK
11239 }
11240 } else if (safi == SAFI_EVPN) {
9bcb3eef 11241 struct bgp_dest *longest_pfx;
cded3b72 11242 bool is_exact_pfxlen_match = false;
44c69747 11243
9bcb3eef
DS
11244 for (dest = bgp_table_top(rib); dest;
11245 dest = bgp_route_next(dest)) {
11246 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11247
9bcb3eef 11248 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11249 continue;
9bcb3eef 11250 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11251 if (!table)
11252 continue;
11253
11254 longest_pfx = NULL;
cded3b72 11255 is_exact_pfxlen_match = false;
44c69747
LK
11256 /*
11257 * Search through all the prefixes for a match. The
11258 * pfx's are enumerated in ascending order of pfxlens.
11259 * So, the last pfx match is the longest match. Set
11260 * is_exact_pfxlen_match when we get exact pfxlen match
11261 */
11262 for (rm = bgp_table_top(table); rm;
11263 rm = bgp_route_next(rm)) {
b54892e0 11264 const struct prefix *rm_p =
9bcb3eef 11265 bgp_dest_get_prefix(rm);
44c69747
LK
11266 /*
11267 * Get prefixlen of the ip-prefix within type5
11268 * evpn route
11269 */
b54892e0
DS
11270 if (evpn_type5_prefix_match(rm_p, &match)
11271 && rm->info) {
44c69747
LK
11272 longest_pfx = rm;
11273 int type5_pfxlen =
b54892e0
DS
11274 bgp_evpn_get_type5_prefixlen(
11275 rm_p);
44c69747 11276 if (type5_pfxlen == match.prefixlen) {
cded3b72 11277 is_exact_pfxlen_match = true;
9bcb3eef 11278 bgp_dest_unlock_node(rm);
44c69747
LK
11279 break;
11280 }
d62a17ae 11281 }
11282 }
ea47320b 11283
44c69747
LK
11284 if (!longest_pfx)
11285 continue;
11286
11287 if (prefix_check && !is_exact_pfxlen_match)
11288 continue;
11289
11290 rm = longest_pfx;
9bcb3eef 11291 bgp_dest_lock_node(rm);
44c69747 11292
9bcb3eef 11293 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11294 bgp, afi, safi, json, pathtype,
11295 &display);
44c69747 11296
9bcb3eef 11297 bgp_dest_unlock_node(rm);
d62a17ae 11298 }
98a9dbc7 11299 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11300 if (use_json)
11301 json_paths = json_object_new_array();
11302
63a0b7a9
PG
11303 display = bgp_flowspec_display_match_per_ip(afi, rib,
11304 &match, prefix_check,
11305 vty,
11306 use_json,
11307 json_paths);
d5f20468
SP
11308 if (use_json) {
11309 if (display)
11310 json_object_object_add(json, "paths",
11311 json_paths);
11312 else
11313 json_object_free(json_paths);
11314 }
d62a17ae 11315 } else {
9bcb3eef
DS
11316 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11317 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11318 if (!prefix_check
9bcb3eef
DS
11319 || dest_p->prefixlen == match.prefixlen) {
11320 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11321 safi, json, pathtype,
11322 &display);
d62a17ae 11323 }
11324
9bcb3eef 11325 bgp_dest_unlock_node(dest);
d62a17ae 11326 }
11327 }
e5eee9af 11328
d62a17ae 11329 if (use_json) {
996c9314 11330 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11331 json, JSON_C_TO_STRING_PRETTY |
11332 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11333 json_object_free(json);
11334 } else {
11335 if (!display) {
11336 vty_out(vty, "%% Network not in table\n");
11337 return CMD_WARNING;
11338 }
11339 }
b05a1c8b 11340
d62a17ae 11341 return CMD_SUCCESS;
718e3744 11342}
11343
fee0f4c6 11344/* Display specified route of Main RIB */
d62a17ae 11345static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11346 afi_t afi, safi_t safi, struct prefix_rd *prd,
11347 int prefix_check, enum bgp_path_type pathtype,
9f049418 11348 bool use_json)
d62a17ae 11349{
9b86009a 11350 if (!bgp) {
d62a17ae 11351 bgp = bgp_get_default();
9b86009a
RW
11352 if (!bgp) {
11353 if (!use_json)
11354 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11355 else
11356 vty_out(vty, "{}\n");
9b86009a
RW
11357 return CMD_WARNING;
11358 }
11359 }
d62a17ae 11360
11361 /* labeled-unicast routes live in the unicast table */
11362 if (safi == SAFI_LABELED_UNICAST)
11363 safi = SAFI_UNICAST;
11364
11365 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11366 afi, safi, prd, prefix_check, pathtype,
11367 use_json);
11368}
11369
11370static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11371 struct cmd_token **argv, bool exact, afi_t afi,
11372 safi_t safi, bool uj)
d62a17ae 11373{
11374 struct lcommunity *lcom;
11375 struct buffer *b;
11376 int i;
11377 char *str;
11378 int first = 0;
96f3485c 11379 uint8_t show_flags = 0;
4f28b2b5 11380 int ret;
96f3485c
MK
11381
11382 if (uj)
11383 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11384
11385 b = buffer_new(1024);
11386 for (i = 0; i < argc; i++) {
11387 if (first)
11388 buffer_putc(b, ' ');
11389 else {
11390 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11391 first = 1;
11392 buffer_putstr(b, argv[i]->arg);
11393 }
11394 }
11395 }
11396 buffer_putc(b, '\0');
57d187bc 11397
d62a17ae 11398 str = buffer_getstr(b);
11399 buffer_free(b);
57d187bc 11400
d62a17ae 11401 lcom = lcommunity_str2com(str);
11402 XFREE(MTYPE_TMP, str);
11403 if (!lcom) {
11404 vty_out(vty, "%% Large-community malformed\n");
11405 return CMD_WARNING;
11406 }
57d187bc 11407
4f28b2b5 11408 ret = bgp_show(vty, bgp, afi, safi,
36a206db 11409 (exact ? bgp_show_type_lcommunity_exact
ae248832 11410 : bgp_show_type_lcommunity),
96f3485c 11411 lcom, show_flags);
4f28b2b5
DS
11412
11413 lcommunity_free(&lcom);
11414 return ret;
57d187bc
JS
11415}
11416
d62a17ae 11417static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11418 const char *lcom, bool exact, afi_t afi,
11419 safi_t safi, bool uj)
57d187bc 11420{
d62a17ae 11421 struct community_list *list;
96f3485c
MK
11422 uint8_t show_flags = 0;
11423
11424 if (uj)
11425 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11426
57d187bc 11427
e237b0d2 11428 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11429 LARGE_COMMUNITY_LIST_MASTER);
11430 if (list == NULL) {
11431 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11432 lcom);
11433 return CMD_WARNING;
11434 }
57d187bc 11435
36a206db 11436 return bgp_show(vty, bgp, afi, safi,
11437 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11438 : bgp_show_type_lcommunity_list),
96f3485c 11439 list, show_flags);
fee0f4c6 11440}
11441
52951b63
DS
11442DEFUN (show_ip_bgp_large_community_list,
11443 show_ip_bgp_large_community_list_cmd,
36a206db 11444 "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
11445 SHOW_STR
11446 IP_STR
11447 BGP_STR
11448 BGP_INSTANCE_HELP_STR
9bedbb1e 11449 BGP_AFI_HELP_STR
4dd6177e 11450 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11451 "Display routes matching the large-community-list\n"
11452 "large-community-list number\n"
11453 "large-community-list name\n"
36a206db 11454 "Exact match of the large-communities\n"
52951b63
DS
11455 JSON_STR)
11456{
d62a17ae 11457 afi_t afi = AFI_IP6;
11458 safi_t safi = SAFI_UNICAST;
11459 int idx = 0;
36a206db 11460 bool exact_match = 0;
4d678463 11461 struct bgp *bgp = NULL;
9f049418 11462 bool uj = use_json(argc, argv);
d62a17ae 11463
4d678463
KA
11464 if (uj)
11465 argc--;
11466
11467 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11468 &bgp, uj);
11469 if (!idx)
11470 return CMD_WARNING;
d62a17ae 11471
11472 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11473
11474 const char *clist_number_or_name = argv[++idx]->arg;
11475
11476 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11477 exact_match = 1;
11478
11479 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11480 exact_match, afi, safi, uj);
52951b63
DS
11481}
11482DEFUN (show_ip_bgp_large_community,
11483 show_ip_bgp_large_community_cmd,
36a206db 11484 "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
11485 SHOW_STR
11486 IP_STR
11487 BGP_STR
11488 BGP_INSTANCE_HELP_STR
9bedbb1e 11489 BGP_AFI_HELP_STR
4dd6177e 11490 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11491 "Display routes matching the large-communities\n"
11492 "List of large-community numbers\n"
36a206db 11493 "Exact match of the large-communities\n"
52951b63
DS
11494 JSON_STR)
11495{
d62a17ae 11496 afi_t afi = AFI_IP6;
11497 safi_t safi = SAFI_UNICAST;
11498 int idx = 0;
36a206db 11499 bool exact_match = 0;
4d678463 11500 struct bgp *bgp = NULL;
9f049418 11501 bool uj = use_json(argc, argv);
96f3485c 11502 uint8_t show_flags = 0;
d62a17ae 11503
96f3485c
MK
11504 if (uj) {
11505 argc--;
11506 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11507 }
4d678463 11508
96f3485c
MK
11509 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11510 &bgp, uj);
11511 if (!idx)
11512 return CMD_WARNING;
d62a17ae 11513
36a206db 11514 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11515 if (argv_find(argv, argc, "exact-match", &idx))
11516 exact_match = 1;
11517 return bgp_show_lcommunity(vty, bgp, argc, argv,
11518 exact_match, afi, safi, uj);
11519 } else
d62a17ae 11520 return bgp_show(vty, bgp, afi, safi,
96f3485c 11521 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11522}
11523
71f1613a
DA
11524static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11525 safi_t safi, struct json_object *json_array);
d62a17ae 11526static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11527 safi_t safi, struct json_object *json);
e01ca200 11528
7b2ff250 11529
9ab0cf58
PG
11530DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11531 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11532 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11533 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11534{
11535 bool uj = use_json(argc, argv);
11536 struct bgp *bgp = NULL;
ec76a1d1
DA
11537 safi_t safi = SAFI_UNICAST;
11538 afi_t afi = AFI_IP6;
4265b261 11539 int idx = 0;
6c9d22e2
PG
11540 struct json_object *json_all = NULL;
11541 struct json_object *json_afi_safi = NULL;
4265b261
PG
11542
11543 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11544 &bgp, false);
71f1613a 11545 if (!idx)
4265b261 11546 return CMD_WARNING;
6c9d22e2 11547
4265b261 11548 if (uj)
6c9d22e2 11549 json_all = json_object_new_object();
4265b261 11550
9ab0cf58
PG
11551 FOREACH_AFI_SAFI (afi, safi) {
11552 /*
11553 * So limit output to those afi/safi pairs that
11554 * actually have something interesting in them
11555 */
11556 if (strmatch(get_afi_safi_str(afi, safi, true),
11557 "Unknown")) {
11558 continue;
11559 }
11560 if (uj) {
11561 json_afi_safi = json_object_new_array();
11562 json_object_object_add(
11563 json_all,
11564 get_afi_safi_str(afi, safi, true),
11565 json_afi_safi);
11566 } else {
11567 json_afi_safi = NULL;
6c9d22e2 11568 }
9ab0cf58
PG
11569
11570 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11571 }
6c9d22e2
PG
11572
11573 if (uj) {
9ab0cf58
PG
11574 vty_out(vty, "%s",
11575 json_object_to_json_string_ext(
11576 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11577 json_object_free(json_all);
4265b261 11578 }
6c9d22e2 11579
4265b261
PG
11580 return CMD_SUCCESS;
11581}
11582
7b2ff250 11583/* BGP route print out function without JSON */
14718643
PG
11584DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11585 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11586 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11587 SHOW_STR
11588 IP_STR
11589 BGP_STR
11590 BGP_INSTANCE_HELP_STR
11591 L2VPN_HELP_STR
11592 EVPN_HELP_STR
11593 "BGP RIB advertisement statistics\n"
11594 JSON_STR)
11595{
ec76a1d1
DA
11596 afi_t afi = AFI_IP6;
11597 safi_t safi = SAFI_UNICAST;
14718643
PG
11598 struct bgp *bgp = NULL;
11599 int idx = 0, ret;
11600 bool uj = use_json(argc, argv);
11601 struct json_object *json_afi_safi = NULL, *json = NULL;
11602
11603 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11604 &bgp, false);
11605 if (!idx)
11606 return CMD_WARNING;
11607
11608 if (uj)
11609 json_afi_safi = json_object_new_array();
11610 else
11611 json_afi_safi = NULL;
11612
11613 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11614
11615 if (uj) {
11616 json = json_object_new_object();
11617 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11618 json_afi_safi);
11619 vty_out(vty, "%s", json_object_to_json_string_ext(
11620 json, JSON_C_TO_STRING_PRETTY));
11621 json_object_free(json);
11622 }
11623 return ret;
11624}
11625
893cccd0 11626/* BGP route print out function without JSON */
9ab0cf58
PG
11627DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11628 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11629 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11630 "]]\
893cccd0 11631 statistics [json]",
9ab0cf58
PG
11632 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11633 BGP_SAFI_WITH_LABEL_HELP_STR
11634 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11635{
ec76a1d1
DA
11636 afi_t afi = AFI_IP6;
11637 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11638 struct bgp *bgp = NULL;
11639 int idx = 0, ret;
11640 bool uj = use_json(argc, argv);
6c9d22e2 11641 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11642
11643 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11644 &bgp, false);
11645 if (!idx)
11646 return CMD_WARNING;
6c9d22e2 11647
893cccd0 11648 if (uj)
6c9d22e2
PG
11649 json_afi_safi = json_object_new_array();
11650 else
11651 json_afi_safi = NULL;
11652
11653 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11654
11655 if (uj) {
11656 json = json_object_new_object();
11657 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11658 json_afi_safi);
9ab0cf58
PG
11659 vty_out(vty, "%s",
11660 json_object_to_json_string_ext(
11661 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11662 json_object_free(json);
11663 }
11664 return ret;
893cccd0 11665}
7b2ff250
DW
11666
11667/* BGP route print out function without JSON */
96f3485c 11668DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11669 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11670 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11671 "]]\
96f3485c 11672 <[all$all] dampening <parameters>\
7b2ff250
DW
11673 |route-map WORD\
11674 |prefix-list WORD\
11675 |filter-list WORD\
7b2ff250
DW
11676 |community-list <(1-500)|WORD> [exact-match]\
11677 |A.B.C.D/M longer-prefixes\
11678 |X:X::X:X/M longer-prefixes\
893cccd0 11679 >",
9ab0cf58
PG
11680 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11681 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11682 "Display the entries for all address families\n"
9ab0cf58
PG
11683 "Display detailed information about dampening\n"
11684 "Display detail of configured dampening parameters\n"
11685 "Display routes matching the route-map\n"
11686 "A route-map to match on\n"
11687 "Display routes conforming to the prefix-list\n"
11688 "Prefix-list name\n"
11689 "Display routes conforming to the filter-list\n"
11690 "Regular expression access list name\n"
11691 "Display routes matching the community-list\n"
11692 "community-list number\n"
11693 "community-list name\n"
11694 "Exact match of the communities\n"
11695 "IPv4 prefix\n"
11696 "Display route and more specific routes\n"
11697 "IPv6 prefix\n"
11698 "Display route and more specific routes\n")
718e3744 11699{
d62a17ae 11700 afi_t afi = AFI_IP6;
11701 safi_t safi = SAFI_UNICAST;
11702 int exact_match = 0;
d62a17ae 11703 struct bgp *bgp = NULL;
11704 int idx = 0;
96f3485c
MK
11705 uint8_t show_flags = 0;
11706
11707 /* [<ipv4|ipv6> [all]] */
11708 if (all) {
11709 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11710 if (argv_find(argv, argc, "ipv4", &idx))
11711 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11712
11713 if (argv_find(argv, argc, "ipv6", &idx))
11714 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11715 }
d62a17ae 11716
11717 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11718 &bgp, false);
d62a17ae 11719 if (!idx)
11720 return CMD_WARNING;
11721
d62a17ae 11722 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11723 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11724 return bgp_show_dampening_parameters(vty, afi, safi,
11725 show_flags);
d62a17ae 11726 }
c016b6c7 11727
d62a17ae 11728 if (argv_find(argv, argc, "prefix-list", &idx))
11729 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11730 safi, bgp_show_type_prefix_list);
11731
11732 if (argv_find(argv, argc, "filter-list", &idx))
11733 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11734 safi, bgp_show_type_filter_list);
11735
d62a17ae 11736 if (argv_find(argv, argc, "route-map", &idx))
11737 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11738 safi, bgp_show_type_route_map);
11739
d62a17ae 11740 if (argv_find(argv, argc, "community-list", &idx)) {
11741 const char *clist_number_or_name = argv[++idx]->arg;
11742 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11743 exact_match = 1;
11744 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11745 exact_match, afi, safi);
11746 }
11747 /* prefix-longer */
11748 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11749 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11750 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11751 safi,
11752 bgp_show_type_prefix_longer);
11753
7b2ff250
DW
11754 return CMD_WARNING;
11755}
11756
11757/* BGP route print out function with JSON */
ae248832 11758DEFPY (show_ip_bgp_json,
7b2ff250
DW
11759 show_ip_bgp_json_cmd,
11760 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11761 [all$all]\
cf4898bc
QY
11762 [cidr-only\
11763 |dampening <flap-statistics|dampened-paths>\
11764 |community [AA:NN|local-AS|no-advertise|no-export\
11765 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11766 |accept-own|accept-own-nexthop|route-filter-v6\
11767 |route-filter-v4|route-filter-translated-v6\
11768 |route-filter-translated-v4] [exact-match]\
ae248832 11769 ] [json$uj | wide$wide]",
7b2ff250
DW
11770 SHOW_STR
11771 IP_STR
11772 BGP_STR
11773 BGP_INSTANCE_HELP_STR
11774 BGP_AFI_HELP_STR
11775 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11776 "Display the entries for all address families\n"
7b2ff250
DW
11777 "Display only routes with non-natural netmasks\n"
11778 "Display detailed information about dampening\n"
11779 "Display flap statistics of routes\n"
11780 "Display paths suppressed due to dampening\n"
11781 "Display routes matching the communities\n"
d0086e8e
AD
11782 COMMUNITY_AANN_STR
11783 "Do not send outside local AS (well-known community)\n"
11784 "Do not advertise to any peer (well-known community)\n"
11785 "Do not export to next AS (well-known community)\n"
11786 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11787 "Do not export to any peer (well-known community)\n"
11788 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11789 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11790 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11791 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11792 "Should accept VPN route with local nexthop (well-known community)\n"
11793 "RT VPNv6 route filtering (well-known community)\n"
11794 "RT VPNv4 route filtering (well-known community)\n"
11795 "RT translated VPNv6 route filtering (well-known community)\n"
11796 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11797 "Exact match of the communities\n"
ae248832
MK
11798 JSON_STR
11799 "Increase table width for longer prefixes\n")
7b2ff250
DW
11800{
11801 afi_t afi = AFI_IP6;
11802 safi_t safi = SAFI_UNICAST;
11803 enum bgp_show_type sh_type = bgp_show_type_normal;
11804 struct bgp *bgp = NULL;
11805 int idx = 0;
d0086e8e 11806 int exact_match = 0;
96f3485c
MK
11807 char *community = NULL;
11808 bool first = true;
11809 uint8_t show_flags = 0;
9f049418 11810
96f3485c
MK
11811
11812 if (uj) {
9f049418 11813 argc--;
96f3485c
MK
11814 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11815 }
11816
11817 /* [<ipv4|ipv6> [all]] */
11818 if (all) {
11819 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11820
11821 if (argv_find(argv, argc, "ipv4", &idx))
11822 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11823
11824 if (argv_find(argv, argc, "ipv6", &idx))
11825 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11826 }
11827
11828 if (wide)
11829 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11830
11831 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11832 &bgp, uj);
7b2ff250
DW
11833 if (!idx)
11834 return CMD_WARNING;
11835
7b2ff250 11836 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11837 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11838
11839 if (argv_find(argv, argc, "dampening", &idx)) {
11840 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11841 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11842 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11843 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11844 }
11845
11846 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11847 char *maybecomm = NULL;
d0086e8e 11848
79bc257a
RW
11849 if (idx + 1 < argc) {
11850 if (argv[idx + 1]->type == VARIABLE_TKN)
11851 maybecomm = argv[idx + 1]->arg;
11852 else
11853 maybecomm = argv[idx + 1]->text;
11854 }
11855
cf4898bc
QY
11856 if (maybecomm && !strmatch(maybecomm, "json")
11857 && !strmatch(maybecomm, "exact-match"))
11858 community = maybecomm;
d0086e8e 11859
cf4898bc
QY
11860 if (argv_find(argv, argc, "exact-match", &idx))
11861 exact_match = 1;
d0086e8e 11862
96f3485c
MK
11863 if (!community)
11864 sh_type = bgp_show_type_community_all;
11865 }
11866
11867 if (!all) {
11868 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11869 if (community)
11870 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11871 exact_match, afi, safi,
11872 show_flags);
cf4898bc 11873 else
96f3485c
MK
11874 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11875 show_flags);
11876 } else {
11877 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11878 * AFI_IP6 */
11879
11880 if (uj)
11881 vty_out(vty, "{\n");
11882
11883 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11884 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11885 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11886 ? AFI_IP
11887 : AFI_IP6;
11888 FOREACH_SAFI (safi) {
96f3485c
MK
11889 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11890 continue;
11891
11892 if (uj) {
11893 if (first)
11894 first = false;
11895 else
11896 vty_out(vty, ",\n");
11897 vty_out(vty, "\"%s\":{\n",
11898 get_afi_safi_str(afi, safi,
11899 true));
11900 } else
11901 vty_out(vty,
11902 "\nFor address family: %s\n",
11903 get_afi_safi_str(afi, safi,
11904 false));
11905
11906 if (community)
11907 bgp_show_community(vty, bgp, community,
11908 exact_match, afi,
11909 safi, show_flags);
11910 else
11911 bgp_show(vty, bgp, afi, safi, sh_type,
11912 NULL, show_flags);
11913 if (uj)
11914 vty_out(vty, "}\n");
11915 }
11916 } else {
11917 /* show <ip> bgp all: for each AFI and SAFI*/
11918 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
11919 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11920 continue;
11921
11922 if (uj) {
11923 if (first)
11924 first = false;
11925 else
11926 vty_out(vty, ",\n");
d0086e8e 11927
96f3485c
MK
11928 vty_out(vty, "\"%s\":{\n",
11929 get_afi_safi_str(afi, safi,
11930 true));
11931 } else
11932 vty_out(vty,
11933 "\nFor address family: %s\n",
11934 get_afi_safi_str(afi, safi,
11935 false));
11936
11937 if (community)
11938 bgp_show_community(vty, bgp, community,
11939 exact_match, afi,
11940 safi, show_flags);
11941 else
11942 bgp_show(vty, bgp, afi, safi, sh_type,
11943 NULL, show_flags);
11944 if (uj)
11945 vty_out(vty, "}\n");
11946 }
11947 }
11948 if (uj)
11949 vty_out(vty, "}\n");
11950 }
11951 return CMD_SUCCESS;
a636c635 11952}
47fc97cc 11953
718e3744 11954DEFUN (show_ip_bgp_route,
11955 show_ip_bgp_route_cmd,
3efd0893 11956 "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 11957 SHOW_STR
11958 IP_STR
11959 BGP_STR
a636c635 11960 BGP_INSTANCE_HELP_STR
4f280b15 11961 BGP_AFI_HELP_STR
4dd6177e 11962 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11963 "Network in the BGP routing table to display\n"
0c7b1b01 11964 "IPv4 prefix\n"
8c3deaae 11965 "Network in the BGP routing table to display\n"
0c7b1b01 11966 "IPv6 prefix\n"
4092b06c 11967 "Display only the bestpath\n"
b05a1c8b 11968 "Display only multipaths\n"
9973d184 11969 JSON_STR)
4092b06c 11970{
d62a17ae 11971 int prefix_check = 0;
ae19d7dd 11972
d62a17ae 11973 afi_t afi = AFI_IP6;
11974 safi_t safi = SAFI_UNICAST;
11975 char *prefix = NULL;
11976 struct bgp *bgp = NULL;
11977 enum bgp_path_type path_type;
9f049418 11978 bool uj = use_json(argc, argv);
b05a1c8b 11979
d62a17ae 11980 int idx = 0;
ae19d7dd 11981
d62a17ae 11982 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11983 &bgp, uj);
d62a17ae 11984 if (!idx)
11985 return CMD_WARNING;
c41247f5 11986
d62a17ae 11987 if (!bgp) {
11988 vty_out(vty,
11989 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11990 return CMD_WARNING;
11991 }
a636c635 11992
d62a17ae 11993 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11994 if (argv_find(argv, argc, "A.B.C.D", &idx)
11995 || argv_find(argv, argc, "X:X::X:X", &idx))
11996 prefix_check = 0;
11997 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11998 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11999 prefix_check = 1;
12000
12001 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12002 && afi != AFI_IP6) {
12003 vty_out(vty,
12004 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12005 return CMD_WARNING;
12006 }
12007 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12008 && afi != AFI_IP) {
12009 vty_out(vty,
12010 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12011 return CMD_WARNING;
12012 }
12013
12014 prefix = argv[idx]->arg;
12015
12016 /* [<bestpath|multipath>] */
12017 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12018 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12019 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12020 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12021 else
360660c6 12022 path_type = BGP_PATH_SHOW_ALL;
a636c635 12023
d62a17ae 12024 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
12025 path_type, uj);
4092b06c
DS
12026}
12027
8c3deaae
QY
12028DEFUN (show_ip_bgp_regexp,
12029 show_ip_bgp_regexp_cmd,
3e5b31b3 12030 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12031 SHOW_STR
12032 IP_STR
12033 BGP_STR
b00b230a 12034 BGP_INSTANCE_HELP_STR
4f280b15 12035 BGP_AFI_HELP_STR
4dd6177e 12036 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12037 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12038 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12039 JSON_STR)
8c3deaae 12040{
d62a17ae 12041 afi_t afi = AFI_IP6;
12042 safi_t safi = SAFI_UNICAST;
12043 struct bgp *bgp = NULL;
3e5b31b3
DA
12044 bool uj = use_json(argc, argv);
12045 char *regstr = NULL;
8c3deaae 12046
d62a17ae 12047 int idx = 0;
12048 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12049 &bgp, false);
d62a17ae 12050 if (!idx)
12051 return CMD_WARNING;
8c3deaae 12052
d62a17ae 12053 // get index of regex
3e5b31b3
DA
12054 if (argv_find(argv, argc, "REGEX", &idx))
12055 regstr = argv[idx]->arg;
8c3deaae 12056
5f71d11c 12057 assert(regstr);
3e5b31b3
DA
12058 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12059 bgp_show_type_regexp, uj);
8c3deaae
QY
12060}
12061
ae248832 12062DEFPY (show_ip_bgp_instance_all,
a636c635 12063 show_ip_bgp_instance_all_cmd,
ae248832 12064 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12065 SHOW_STR
a636c635 12066 IP_STR
4092b06c 12067 BGP_STR
a636c635 12068 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12069 BGP_AFI_HELP_STR
4dd6177e 12070 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12071 JSON_STR
12072 "Increase table width for longer prefixes\n")
4092b06c 12073{
d62a17ae 12074 afi_t afi = AFI_IP;
12075 safi_t safi = SAFI_UNICAST;
12076 struct bgp *bgp = NULL;
d62a17ae 12077 int idx = 0;
96f3485c 12078 uint8_t show_flags = 0;
ae19d7dd 12079
96f3485c 12080 if (uj) {
d62a17ae 12081 argc--;
96f3485c
MK
12082 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12083 }
12084
12085 if (wide)
12086 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12087
9f049418
DS
12088 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12089 &bgp, uj);
12090 if (!idx)
12091 return CMD_WARNING;
12092
96f3485c 12093 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12094 return CMD_SUCCESS;
e3e29b32
LB
12095}
12096
a4d82a8a 12097static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12098 afi_t afi, safi_t safi, enum bgp_show_type type,
12099 bool use_json)
718e3744 12100{
d62a17ae 12101 regex_t *regex;
12102 int rc;
96f3485c
MK
12103 uint8_t show_flags = 0;
12104
12105 if (use_json)
12106 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12107
c3900853 12108 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12109 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12110 regstr);
12111 return CMD_WARNING_CONFIG_FAILED;
12112 }
12113
d62a17ae 12114 regex = bgp_regcomp(regstr);
12115 if (!regex) {
12116 vty_out(vty, "Can't compile regexp %s\n", regstr);
12117 return CMD_WARNING;
12118 }
a636c635 12119
96f3485c 12120 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 12121 bgp_regex_free(regex);
12122 return rc;
e3e29b32
LB
12123}
12124
d62a17ae 12125static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12126 const char *prefix_list_str, afi_t afi,
12127 safi_t safi, enum bgp_show_type type)
e3e29b32 12128{
d62a17ae 12129 struct prefix_list *plist;
96f3485c 12130 uint8_t show_flags = 0;
718e3744 12131
d62a17ae 12132 plist = prefix_list_lookup(afi, prefix_list_str);
12133 if (plist == NULL) {
12134 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12135 prefix_list_str);
12136 return CMD_WARNING;
12137 }
718e3744 12138
96f3485c 12139 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
12140}
12141
d62a17ae 12142static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12143 const char *filter, afi_t afi, safi_t safi,
12144 enum bgp_show_type type)
4092b06c 12145{
d62a17ae 12146 struct as_list *as_list;
96f3485c 12147 uint8_t show_flags = 0;
718e3744 12148
d62a17ae 12149 as_list = as_list_lookup(filter);
12150 if (as_list == NULL) {
12151 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12152 filter);
12153 return CMD_WARNING;
12154 }
a636c635 12155
96f3485c 12156 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12157}
12158
d62a17ae 12159static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12160 const char *rmap_str, afi_t afi, safi_t safi,
12161 enum bgp_show_type type)
718e3744 12162{
d62a17ae 12163 struct route_map *rmap;
96f3485c 12164 uint8_t show_flags = 0;
bb46e94f 12165
d62a17ae 12166 rmap = route_map_lookup_by_name(rmap_str);
12167 if (!rmap) {
12168 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12169 return CMD_WARNING;
12170 }
12171
96f3485c 12172 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12173}
12174
7f323236
DW
12175static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12176 const char *comstr, int exact, afi_t afi,
96f3485c 12177 safi_t safi, uint8_t show_flags)
d62a17ae 12178{
12179 struct community *com;
d62a17ae 12180 int ret = 0;
12181
7f323236 12182 com = community_str2com(comstr);
d62a17ae 12183 if (!com) {
7f323236 12184 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12185 return CMD_WARNING;
12186 }
12187
12188 ret = bgp_show(vty, bgp, afi, safi,
12189 (exact ? bgp_show_type_community_exact
12190 : bgp_show_type_community),
96f3485c 12191 com, show_flags);
3c1f53de 12192 community_free(&com);
46c3ce83 12193
d62a17ae 12194 return ret;
718e3744 12195}
12196
d62a17ae 12197static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12198 const char *com, int exact, afi_t afi,
12199 safi_t safi)
50ef26d4 12200{
d62a17ae 12201 struct community_list *list;
96f3485c 12202 uint8_t show_flags = 0;
50ef26d4 12203
e237b0d2 12204 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12205 if (list == NULL) {
12206 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12207 return CMD_WARNING;
12208 }
718e3744 12209
d62a17ae 12210 return bgp_show(vty, bgp, afi, safi,
12211 (exact ? bgp_show_type_community_list_exact
12212 : bgp_show_type_community_list),
96f3485c 12213 list, show_flags);
50ef26d4 12214}
12215
d62a17ae 12216static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12217 const char *prefix, afi_t afi, safi_t safi,
12218 enum bgp_show_type type)
718e3744 12219{
d62a17ae 12220 int ret;
12221 struct prefix *p;
96f3485c 12222 uint8_t show_flags = 0;
47fc97cc 12223
d62a17ae 12224 p = prefix_new();
95cbbd2a 12225
d62a17ae 12226 ret = str2prefix(prefix, p);
12227 if (!ret) {
12228 vty_out(vty, "%% Malformed Prefix\n");
12229 return CMD_WARNING;
12230 }
47e9b292 12231
96f3485c 12232 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12233 prefix_free(&p);
d62a17ae 12234 return ret;
12235}
12236
d62a17ae 12237enum bgp_stats {
12238 BGP_STATS_MAXBITLEN = 0,
12239 BGP_STATS_RIB,
12240 BGP_STATS_PREFIXES,
12241 BGP_STATS_TOTPLEN,
12242 BGP_STATS_UNAGGREGATEABLE,
12243 BGP_STATS_MAX_AGGREGATEABLE,
12244 BGP_STATS_AGGREGATES,
12245 BGP_STATS_SPACE,
12246 BGP_STATS_ASPATH_COUNT,
12247 BGP_STATS_ASPATH_MAXHOPS,
12248 BGP_STATS_ASPATH_TOTHOPS,
12249 BGP_STATS_ASPATH_MAXSIZE,
12250 BGP_STATS_ASPATH_TOTSIZE,
12251 BGP_STATS_ASN_HIGHEST,
12252 BGP_STATS_MAX,
a636c635 12253};
2815e61f 12254
9ab0cf58 12255#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12256#define TABLE_STATS_IDX_JSON 1
12257
12258static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12259 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12260 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12261 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12262 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12263 "unaggregateablePrefixes"},
12264 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12265 "maximumAggregateablePrefixes"},
12266 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12267 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12268 [BGP_STATS_SPACE] = {"Address space advertised",
12269 "addressSpaceAdvertised"},
9ab0cf58
PG
12270 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12271 "advertisementsWithPaths"},
12272 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12273 "longestAsPath"},
12274 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12275 "largestAsPath"},
12276 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12277 "averageAsPathLengthHops"},
12278 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12279 "averageAsPathSizeBytes"},
12280 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12281 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12282};
2815e61f 12283
d62a17ae 12284struct bgp_table_stats {
12285 struct bgp_table *table;
12286 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12287 double total_space;
ff7924f6
PJ
12288};
12289
a636c635
DW
12290#if 0
12291#define TALLY_SIGFIG 100000
12292static unsigned long
12293ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 12294{
a636c635
DW
12295 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
12296 unsigned long res = (newtot * TALLY_SIGFIG) / count;
12297 unsigned long ret = newtot / count;
07d0c4ed 12298
a636c635
DW
12299 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
12300 return ret + 1;
12301 else
12302 return ret;
12303}
12304#endif
ff7924f6 12305
9bcb3eef 12306static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12307 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12308{
9bcb3eef 12309 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12310 struct bgp_path_info *pi;
b54892e0 12311 const struct prefix *rn_p;
d62a17ae 12312
9bcb3eef 12313 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12314 return;
d62a17ae 12315
9bcb3eef 12316 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12317 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12318 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12319
a636c635
DW
12320#if 0
12321 ts->counts[BGP_STATS_AVGPLEN]
12322 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
12323 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 12324 rn_p->prefixlen);
a636c635 12325#endif
d62a17ae 12326
9c14ec72 12327 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12328 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12329 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12330
9bcb3eef 12331 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12332 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12333 /* announced address space */
12334 if (space)
b54892e0 12335 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12336 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12337 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12338
9c14ec72 12339
9bcb3eef 12340 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12341 ts->counts[BGP_STATS_RIB]++;
12342
05864da7
DS
12343 if (CHECK_FLAG(pi->attr->flag,
12344 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12345 ts->counts[BGP_STATS_AGGREGATES]++;
12346
12347 /* as-path stats */
05864da7 12348 if (pi->attr->aspath) {
9c14ec72
RW
12349 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12350 unsigned int size = aspath_size(pi->attr->aspath);
12351 as_t highest = aspath_highest(pi->attr->aspath);
12352
12353 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12354
12355 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12356 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12357
12358 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12359 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12360
12361 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12362 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 12363#if 0
07d0c4ed 12364 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
12365 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12366 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
12367 hops);
12368 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
12369 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12370 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
12371 size);
12372#endif
9c14ec72
RW
12373 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12374 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12375 }
12376 }
12377}
12378
12379static int bgp_table_stats_walker(struct thread *t)
12380{
9bcb3eef
DS
12381 struct bgp_dest *dest, *ndest;
12382 struct bgp_dest *top;
9c14ec72
RW
12383 struct bgp_table_stats *ts = THREAD_ARG(t);
12384 unsigned int space = 0;
12385
12386 if (!(top = bgp_table_top(ts->table)))
12387 return 0;
12388
12389 switch (ts->table->afi) {
12390 case AFI_IP:
12391 space = IPV4_MAX_BITLEN;
12392 break;
12393 case AFI_IP6:
12394 space = IPV6_MAX_BITLEN;
12395 break;
12396 default:
12397 return 0;
12398 }
12399
12400 ts->counts[BGP_STATS_MAXBITLEN] = space;
12401
9bcb3eef 12402 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12403 if (ts->table->safi == SAFI_MPLS_VPN
12404 || ts->table->safi == SAFI_ENCAP
12405 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12406 struct bgp_table *table;
12407
9bcb3eef 12408 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12409 if (!table)
12410 continue;
12411
12412 top = bgp_table_top(table);
9bcb3eef
DS
12413 for (ndest = bgp_table_top(table); ndest;
12414 ndest = bgp_route_next(ndest))
12415 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12416 } else {
9bcb3eef 12417 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12418 }
12419 }
9c14ec72 12420
d62a17ae 12421 return 0;
2815e61f 12422}
ff7924f6 12423
71f1613a
DA
12424static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12425 struct json_object *json_array)
12426{
12427 struct listnode *node, *nnode;
12428 struct bgp *bgp;
12429
12430 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12431 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12432}
12433
12434static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12435 safi_t safi, struct json_object *json_array)
2815e61f 12436{
d62a17ae 12437 struct bgp_table_stats ts;
12438 unsigned int i;
893cccd0
PG
12439 int ret = CMD_SUCCESS;
12440 char temp_buf[20];
6c9d22e2
PG
12441 struct json_object *json = NULL;
12442
12443 if (json_array)
12444 json = json_object_new_object();
019386c2 12445
d62a17ae 12446 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12447 char warning_msg[50];
12448
12449 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12450 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12451 safi);
6c9d22e2
PG
12452
12453 if (!json)
893cccd0
PG
12454 vty_out(vty, "%s\n", warning_msg);
12455 else
9ab0cf58 12456 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12457
893cccd0
PG
12458 ret = CMD_WARNING;
12459 goto end_table_stats;
d62a17ae 12460 }
019386c2 12461
893cccd0 12462 if (!json)
5290ceab
DA
12463 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12464 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12465 else
12466 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12467
d62a17ae 12468 /* labeled-unicast routes live in the unicast table */
12469 if (safi == SAFI_LABELED_UNICAST)
12470 safi = SAFI_UNICAST;
019386c2 12471
d62a17ae 12472 memset(&ts, 0, sizeof(ts));
12473 ts.table = bgp->rib[afi][safi];
12474 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12475
d62a17ae 12476 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12477 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12478 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12479 continue;
12480
12481 switch (i) {
a636c635
DW
12482#if 0
12483 case BGP_STATS_ASPATH_AVGHOPS:
12484 case BGP_STATS_ASPATH_AVGSIZE:
12485 case BGP_STATS_AVGPLEN:
12486 vty_out (vty, "%-30s: ", table_stats_strs[i]);
12487 vty_out (vty, "%12.2f",
12488 (float)ts.counts[i] / (float)TALLY_SIGFIG);
12489 break;
12490#endif
d62a17ae 12491 case BGP_STATS_ASPATH_TOTHOPS:
12492 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12493 if (!json) {
9ab0cf58
PG
12494 snprintf(
12495 temp_buf, sizeof(temp_buf), "%12.2f",
12496 ts.counts[i]
12497 ? (float)ts.counts[i]
12498 / (float)ts.counts
12499 [BGP_STATS_ASPATH_COUNT]
12500 : 0);
893cccd0 12501 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12502 table_stats_strs[i]
12503 [TABLE_STATS_IDX_VTY],
893cccd0 12504 temp_buf);
9ab0cf58
PG
12505 } else {
12506 json_object_double_add(
12507 json,
12508 table_stats_strs[i]
12509 [TABLE_STATS_IDX_JSON],
12510 ts.counts[i]
12511 ? (double)ts.counts[i]
12512 / (double)ts.counts
d62a17ae 12513 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12514 : 0);
12515 }
d62a17ae 12516 break;
12517 case BGP_STATS_TOTPLEN:
6c9d22e2 12518 if (!json) {
9ab0cf58
PG
12519 snprintf(
12520 temp_buf, sizeof(temp_buf), "%12.2f",
12521 ts.counts[i]
12522 ? (float)ts.counts[i]
12523 / (float)ts.counts
12524 [BGP_STATS_PREFIXES]
12525 : 0);
893cccd0 12526 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12527 table_stats_strs[i]
12528 [TABLE_STATS_IDX_VTY],
893cccd0 12529 temp_buf);
9ab0cf58
PG
12530 } else {
12531 json_object_double_add(
12532 json,
12533 table_stats_strs[i]
12534 [TABLE_STATS_IDX_JSON],
12535 ts.counts[i]
12536 ? (double)ts.counts[i]
12537 / (double)ts.counts
d62a17ae 12538 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12539 : 0);
12540 }
d62a17ae 12541 break;
12542 case BGP_STATS_SPACE:
6c9d22e2
PG
12543 if (!json) {
12544 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12545 ts.total_space);
893cccd0 12546 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12547 table_stats_strs[i]
12548 [TABLE_STATS_IDX_VTY],
893cccd0 12549 temp_buf);
9ab0cf58
PG
12550 } else {
12551 json_object_double_add(
12552 json,
12553 table_stats_strs[i]
12554 [TABLE_STATS_IDX_JSON],
12555 (double)ts.total_space);
12556 }
8d0ab76d 12557 if (afi == AFI_IP6) {
6c9d22e2
PG
12558 if (!json) {
12559 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12560 "%12g",
12561 ts.total_space
12562 * pow(2.0, -128 + 32));
6c9d22e2
PG
12563 vty_out(vty, "%30s: %s\n",
12564 "/32 equivalent %s\n",
12565 temp_buf);
9ab0cf58
PG
12566 } else {
12567 json_object_double_add(
12568 json, "/32equivalent",
12569 (double)(ts.total_space
12570 * pow(2.0,
12571 -128 + 32)));
12572 }
6c9d22e2
PG
12573 if (!json) {
12574 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12575 "%12g",
12576 ts.total_space
12577 * pow(2.0, -128 + 48));
6c9d22e2
PG
12578 vty_out(vty, "%30s: %s\n",
12579 "/48 equivalent %s\n",
12580 temp_buf);
9ab0cf58
PG
12581 } else {
12582 json_object_double_add(
12583 json, "/48equivalent",
12584 (double)(ts.total_space
12585 * pow(2.0,
12586 -128 + 48)));
12587 }
8d0ab76d 12588 } else {
6c9d22e2
PG
12589 if (!json) {
12590 snprintf(temp_buf, sizeof(temp_buf),
12591 "%12.2f",
9ab0cf58
PG
12592 ts.total_space * 100.
12593 * pow(2.0, -32));
6c9d22e2 12594 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12595 "% announced ", temp_buf);
12596 } else {
12597 json_object_double_add(
12598 json, "%announced",
12599 (double)(ts.total_space * 100.
12600 * pow(2.0, -32)));
12601 }
6c9d22e2
PG
12602 if (!json) {
12603 snprintf(temp_buf, sizeof(temp_buf),
12604 "%12.2f",
9ab0cf58
PG
12605 ts.total_space
12606 * pow(2.0, -32 + 8));
6c9d22e2
PG
12607 vty_out(vty, "%30s: %s\n",
12608 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12609 } else {
12610 json_object_double_add(
12611 json, "/8equivalent",
12612 (double)(ts.total_space
12613 * pow(2.0, -32 + 8)));
12614 }
6c9d22e2
PG
12615 if (!json) {
12616 snprintf(temp_buf, sizeof(temp_buf),
12617 "%12.2f",
9ab0cf58
PG
12618 ts.total_space
12619 * pow(2.0, -32 + 24));
6c9d22e2 12620 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12621 "/24 equivalent ", temp_buf);
12622 } else {
12623 json_object_double_add(
12624 json, "/24equivalent",
12625 (double)(ts.total_space
12626 * pow(2.0, -32 + 24)));
12627 }
8d0ab76d 12628 }
d62a17ae 12629 break;
12630 default:
6c9d22e2
PG
12631 if (!json) {
12632 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12633 ts.counts[i]);
893cccd0 12634 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12635 table_stats_strs[i]
12636 [TABLE_STATS_IDX_VTY],
12637 temp_buf);
12638 } else {
12639 json_object_int_add(
12640 json,
12641 table_stats_strs[i]
12642 [TABLE_STATS_IDX_JSON],
12643 ts.counts[i]);
12644 }
d62a17ae 12645 }
893cccd0
PG
12646 if (!json)
12647 vty_out(vty, "\n");
d62a17ae 12648 }
9ab0cf58 12649end_table_stats:
6c9d22e2
PG
12650 if (json)
12651 json_object_array_add(json_array, json);
893cccd0 12652 return ret;
d62a17ae 12653}
12654
71f1613a
DA
12655static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12656 safi_t safi, struct json_object *json_array)
12657{
12658 if (!bgp) {
12659 bgp_table_stats_all(vty, afi, safi, json_array);
12660 return CMD_SUCCESS;
12661 }
12662
12663 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12664}
12665
d62a17ae 12666enum bgp_pcounts {
12667 PCOUNT_ADJ_IN = 0,
12668 PCOUNT_DAMPED,
12669 PCOUNT_REMOVED,
12670 PCOUNT_HISTORY,
12671 PCOUNT_STALE,
12672 PCOUNT_VALID,
12673 PCOUNT_ALL,
12674 PCOUNT_COUNTED,
7e3d9632 12675 PCOUNT_BPATH_SELECTED,
d62a17ae 12676 PCOUNT_PFCNT, /* the figure we display to users */
12677 PCOUNT_MAX,
a636c635 12678};
718e3744 12679
2b64873d 12680static const char *const pcount_strs[] = {
9d303b37
DL
12681 [PCOUNT_ADJ_IN] = "Adj-in",
12682 [PCOUNT_DAMPED] = "Damped",
12683 [PCOUNT_REMOVED] = "Removed",
12684 [PCOUNT_HISTORY] = "History",
12685 [PCOUNT_STALE] = "Stale",
12686 [PCOUNT_VALID] = "Valid",
12687 [PCOUNT_ALL] = "All RIB",
12688 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12689 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12690 [PCOUNT_PFCNT] = "Useable",
12691 [PCOUNT_MAX] = NULL,
a636c635 12692};
718e3744 12693
d62a17ae 12694struct peer_pcounts {
12695 unsigned int count[PCOUNT_MAX];
12696 const struct peer *peer;
12697 const struct bgp_table *table;
54317cba 12698 safi_t safi;
a636c635 12699};
47fc97cc 12700
9bcb3eef 12701static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12702{
54317cba
JW
12703 const struct bgp_adj_in *ain;
12704 const struct bgp_path_info *pi;
d62a17ae 12705 const struct peer *peer = pc->peer;
12706
54317cba
JW
12707 for (ain = rn->adj_in; ain; ain = ain->next)
12708 if (ain->peer == peer)
12709 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12710
9bcb3eef 12711 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12712
54317cba
JW
12713 if (pi->peer != peer)
12714 continue;
d62a17ae 12715
54317cba 12716 pc->count[PCOUNT_ALL]++;
d62a17ae 12717
54317cba
JW
12718 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12719 pc->count[PCOUNT_DAMPED]++;
12720 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12721 pc->count[PCOUNT_HISTORY]++;
12722 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12723 pc->count[PCOUNT_REMOVED]++;
12724 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12725 pc->count[PCOUNT_STALE]++;
12726 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12727 pc->count[PCOUNT_VALID]++;
12728 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12729 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12730 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12731 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12732
12733 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12734 pc->count[PCOUNT_COUNTED]++;
12735 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12736 flog_err(
12737 EC_LIB_DEVELOPMENT,
12738 "Attempting to count but flags say it is unusable");
12739 } else {
40381db7 12740 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12741 flog_err(
12742 EC_LIB_DEVELOPMENT,
12743 "Not counted but flags say we should");
d62a17ae 12744 }
12745 }
54317cba
JW
12746}
12747
12748static int bgp_peer_count_walker(struct thread *t)
12749{
9bcb3eef 12750 struct bgp_dest *rn, *rm;
54317cba
JW
12751 const struct bgp_table *table;
12752 struct peer_pcounts *pc = THREAD_ARG(t);
12753
12754 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12755 || pc->safi == SAFI_EVPN) {
12756 /* Special handling for 2-level routing tables. */
12757 for (rn = bgp_table_top(pc->table); rn;
12758 rn = bgp_route_next(rn)) {
9bcb3eef 12759 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12760 if (table != NULL)
12761 for (rm = bgp_table_top(table); rm;
12762 rm = bgp_route_next(rm))
12763 bgp_peer_count_proc(rm, pc);
12764 }
12765 } else
12766 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12767 bgp_peer_count_proc(rn, pc);
12768
d62a17ae 12769 return 0;
718e3744 12770}
12771
d62a17ae 12772static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12773 safi_t safi, bool use_json)
856ca177 12774{
d62a17ae 12775 struct peer_pcounts pcounts = {.peer = peer};
12776 unsigned int i;
12777 json_object *json = NULL;
12778 json_object *json_loop = NULL;
856ca177 12779
d62a17ae 12780 if (use_json) {
12781 json = json_object_new_object();
12782 json_loop = json_object_new_object();
12783 }
718e3744 12784
d62a17ae 12785 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12786 || !peer->bgp->rib[afi][safi]) {
12787 if (use_json) {
12788 json_object_string_add(
12789 json, "warning",
12790 "No such neighbor or address family");
12791 vty_out(vty, "%s\n", json_object_to_json_string(json));
12792 json_object_free(json);
d5f20468 12793 json_object_free(json_loop);
d62a17ae 12794 } else
12795 vty_out(vty, "%% No such neighbor or address family\n");
12796
12797 return CMD_WARNING;
12798 }
2a71e9ce 12799
d62a17ae 12800 memset(&pcounts, 0, sizeof(pcounts));
12801 pcounts.peer = peer;
12802 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12803 pcounts.safi = safi;
d62a17ae 12804
12805 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12806 * stats for the thread-walk (i.e. ensure this can't be blamed on
12807 * on just vty_read()).
12808 */
d62a17ae 12809 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12810
12811 if (use_json) {
12812 json_object_string_add(json, "prefixCountsFor", peer->host);
12813 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12814 get_afi_safi_str(afi, safi, true));
d62a17ae 12815 json_object_int_add(json, "pfxCounter",
12816 peer->pcount[afi][safi]);
12817
12818 for (i = 0; i < PCOUNT_MAX; i++)
12819 json_object_int_add(json_loop, pcount_strs[i],
12820 pcounts.count[i]);
12821
12822 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12823
12824 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12825 json_object_string_add(json, "pfxctDriftFor",
12826 peer->host);
12827 json_object_string_add(
12828 json, "recommended",
12829 "Please report this bug, with the above command output");
12830 }
996c9314
LB
12831 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12832 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12833 json_object_free(json);
12834 } else {
12835
12836 if (peer->hostname
892fedb6 12837 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12838 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12839 peer->hostname, peer->host,
5cb5f4d0 12840 get_afi_safi_str(afi, safi, false));
d62a17ae 12841 } else {
12842 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12843 get_afi_safi_str(afi, safi, false));
d62a17ae 12844 }
12845
6cde4b45 12846 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12847 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12848
12849 for (i = 0; i < PCOUNT_MAX; i++)
12850 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12851 pcounts.count[i]);
12852
12853 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12854 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12855 vty_out(vty,
12856 "Please report this bug, with the above command output\n");
12857 }
12858 }
12859
12860 return CMD_SUCCESS;
718e3744 12861}
12862
a636c635
DW
12863DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12864 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12865 "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 12866 SHOW_STR
12867 IP_STR
12868 BGP_STR
8386ac43 12869 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12870 BGP_AFI_HELP_STR
12871 BGP_SAFI_HELP_STR
0b16f239
DS
12872 "Detailed information on TCP and BGP neighbor connections\n"
12873 "Neighbor to display information about\n"
12874 "Neighbor to display information about\n"
91d37724 12875 "Neighbor on BGP configured interface\n"
a636c635 12876 "Display detailed prefix count information\n"
9973d184 12877 JSON_STR)
0b16f239 12878{
d62a17ae 12879 afi_t afi = AFI_IP6;
12880 safi_t safi = SAFI_UNICAST;
12881 struct peer *peer;
12882 int idx = 0;
12883 struct bgp *bgp = NULL;
9f049418
DS
12884 bool uj = use_json(argc, argv);
12885
12886 if (uj)
12887 argc--;
856ca177 12888
d62a17ae 12889 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12890 &bgp, uj);
d62a17ae 12891 if (!idx)
12892 return CMD_WARNING;
0b16f239 12893
d62a17ae 12894 argv_find(argv, argc, "neighbors", &idx);
12895 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12896 if (!peer)
12897 return CMD_WARNING;
bb46e94f 12898
29c8d9da 12899 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12900}
0b16f239 12901
d6902373
PG
12902#ifdef KEEP_OLD_VPN_COMMANDS
12903DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12904 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12905 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12906 SHOW_STR
12907 IP_STR
12908 BGP_STR
d6902373 12909 BGP_VPNVX_HELP_STR
91d37724 12910 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12911 "Detailed information on TCP and BGP neighbor connections\n"
12912 "Neighbor to display information about\n"
12913 "Neighbor to display information about\n"
91d37724 12914 "Neighbor on BGP configured interface\n"
a636c635 12915 "Display detailed prefix count information\n"
9973d184 12916 JSON_STR)
a636c635 12917{
d62a17ae 12918 int idx_peer = 6;
12919 struct peer *peer;
9f049418 12920 bool uj = use_json(argc, argv);
a636c635 12921
d62a17ae 12922 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12923 if (!peer)
12924 return CMD_WARNING;
12925
12926 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12927}
12928
d6902373
PG
12929DEFUN (show_ip_bgp_vpn_all_route_prefix,
12930 show_ip_bgp_vpn_all_route_prefix_cmd,
12931 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12932 SHOW_STR
12933 IP_STR
12934 BGP_STR
d6902373 12935 BGP_VPNVX_HELP_STR
91d37724
QY
12936 "Display information about all VPNv4 NLRIs\n"
12937 "Network in the BGP routing table to display\n"
3a2d747c 12938 "Network in the BGP routing table to display\n"
9973d184 12939 JSON_STR)
91d37724 12940{
d62a17ae 12941 int idx = 0;
12942 char *network = NULL;
12943 struct bgp *bgp = bgp_get_default();
12944 if (!bgp) {
12945 vty_out(vty, "Can't find default instance\n");
12946 return CMD_WARNING;
12947 }
87e34b58 12948
d62a17ae 12949 if (argv_find(argv, argc, "A.B.C.D", &idx))
12950 network = argv[idx]->arg;
12951 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12952 network = argv[idx]->arg;
12953 else {
12954 vty_out(vty, "Unable to figure out Network\n");
12955 return CMD_WARNING;
12956 }
87e34b58 12957
d62a17ae 12958 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12959 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12960}
d6902373 12961#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12962
44c69747
LK
12963DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12964 show_bgp_l2vpn_evpn_route_prefix_cmd,
12965 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12966 SHOW_STR
4c63a661
PG
12967 BGP_STR
12968 L2VPN_HELP_STR
12969 EVPN_HELP_STR
44c69747
LK
12970 "Network in the BGP routing table to display\n"
12971 "Network in the BGP routing table to display\n"
4c63a661
PG
12972 "Network in the BGP routing table to display\n"
12973 "Network in the BGP routing table to display\n"
12974 JSON_STR)
12975{
d62a17ae 12976 int idx = 0;
12977 char *network = NULL;
44c69747 12978 int prefix_check = 0;
a636c635 12979
44c69747
LK
12980 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12981 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12982 network = argv[idx]->arg;
44c69747 12983 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12984 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12985 network = argv[idx]->arg;
44c69747
LK
12986 prefix_check = 1;
12987 } else {
d62a17ae 12988 vty_out(vty, "Unable to figure out Network\n");
12989 return CMD_WARNING;
12990 }
44c69747
LK
12991 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12992 prefix_check, BGP_PATH_SHOW_ALL,
12993 use_json(argc, argv));
d62a17ae 12994}
12995
2f9bc755
DS
12996static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12997 struct bgp_table *table, int *header1,
12998 int *header2, json_object *json,
12999 json_object *json_scode,
13000 json_object *json_ocode, bool wide)
13001{
13002 uint64_t version = table ? table->version : 0;
23d0a753 13003 char buf[BUFSIZ] = {0};
2f9bc755
DS
13004
13005 if (*header1) {
13006 if (json) {
13007 json_object_int_add(json, "bgpTableVersion", version);
13008 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13009 inet_ntop(AF_INET,
13010 &bgp->router_id, buf,
13011 sizeof(buf)));
2f9bc755
DS
13012 json_object_int_add(json, "defaultLocPrf",
13013 bgp->default_local_pref);
13014 json_object_int_add(json, "localAS", bgp->as);
13015 json_object_object_add(json, "bgpStatusCodes",
13016 json_scode);
13017 json_object_object_add(json, "bgpOriginCodes",
13018 json_ocode);
13019 } else {
13020 vty_out(vty,
23d0a753
DA
13021 "BGP table version is %" PRIu64
13022 ", local router ID is %pI4, vrf id ",
13023 version, &bgp->router_id);
2f9bc755
DS
13024 if (bgp->vrf_id == VRF_UNKNOWN)
13025 vty_out(vty, "%s", VRFID_NONE_STR);
13026 else
13027 vty_out(vty, "%u", bgp->vrf_id);
13028 vty_out(vty, "\n");
13029 vty_out(vty, "Default local pref %u, ",
13030 bgp->default_local_pref);
13031 vty_out(vty, "local AS %u\n", bgp->as);
13032 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13033 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13034 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13035 }
13036 *header1 = 0;
13037 }
13038 if (*header2) {
13039 if (!json)
13040 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13041 : BGP_SHOW_HEADER));
13042 *header2 = 0;
13043 }
13044}
13045
d62a17ae 13046static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13047 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
13048 const char *rmap_name, json_object *json,
13049 uint8_t show_flags)
d62a17ae 13050{
13051 struct bgp_table *table;
13052 struct bgp_adj_in *ain;
13053 struct bgp_adj_out *adj;
74a630b6
NT
13054 unsigned long output_count = 0;
13055 unsigned long filtered_count = 0;
9bcb3eef 13056 struct bgp_dest *dest;
d62a17ae 13057 int header1 = 1;
13058 struct bgp *bgp;
13059 int header2 = 1;
13060 struct attr attr;
13061 int ret;
13062 struct update_subgroup *subgrp;
13063 json_object *json_scode = NULL;
13064 json_object *json_ocode = NULL;
13065 json_object *json_ar = NULL;
13066 struct peer_af *paf;
f99def61 13067 bool route_filtered;
96f3485c
MK
13068 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13069 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 13070
13071 if (use_json) {
13072 json_scode = json_object_new_object();
13073 json_ocode = json_object_new_object();
13074 json_ar = json_object_new_object();
13075
13076 json_object_string_add(json_scode, "suppressed", "s");
13077 json_object_string_add(json_scode, "damped", "d");
13078 json_object_string_add(json_scode, "history", "h");
13079 json_object_string_add(json_scode, "valid", "*");
13080 json_object_string_add(json_scode, "best", ">");
13081 json_object_string_add(json_scode, "multipath", "=");
13082 json_object_string_add(json_scode, "internal", "i");
13083 json_object_string_add(json_scode, "ribFailure", "r");
13084 json_object_string_add(json_scode, "stale", "S");
13085 json_object_string_add(json_scode, "removed", "R");
13086
13087 json_object_string_add(json_ocode, "igp", "i");
13088 json_object_string_add(json_ocode, "egp", "e");
13089 json_object_string_add(json_ocode, "incomplete", "?");
13090 }
a636c635 13091
d62a17ae 13092 bgp = peer->bgp;
a636c635 13093
d62a17ae 13094 if (!bgp) {
13095 if (use_json) {
13096 json_object_string_add(json, "alert", "no BGP");
13097 vty_out(vty, "%s\n", json_object_to_json_string(json));
13098 json_object_free(json);
13099 } else
13100 vty_out(vty, "%% No bgp\n");
13101 return;
13102 }
a636c635 13103
c512a642
EDP
13104 /* labeled-unicast routes live in the unicast table */
13105 if (safi == SAFI_LABELED_UNICAST)
13106 table = bgp->rib[afi][SAFI_UNICAST];
13107 else
13108 table = bgp->rib[afi][safi];
d62a17ae 13109
13110 output_count = filtered_count = 0;
13111 subgrp = peer_subgroup(peer, afi, safi);
13112
6392aaa6 13113 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13114 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13115 char buf[BUFSIZ] = {0};
13116
d62a17ae 13117 if (use_json) {
13118 json_object_int_add(json, "bgpTableVersion",
13119 table->version);
13120 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13121 inet_ntop(AF_INET,
13122 &bgp->router_id, buf,
13123 sizeof(buf)));
01eced22
AD
13124 json_object_int_add(json, "defaultLocPrf",
13125 bgp->default_local_pref);
13126 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13127 json_object_object_add(json, "bgpStatusCodes",
13128 json_scode);
13129 json_object_object_add(json, "bgpOriginCodes",
13130 json_ocode);
07d0c4ed
DA
13131 json_object_string_add(
13132 json, "bgpOriginatingDefaultNetwork",
13133 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13134 } else {
23d0a753
DA
13135 vty_out(vty,
13136 "BGP table version is %" PRIu64
13137 ", local router ID is %pI4, vrf id ",
13138 table->version, &bgp->router_id);
9df8b37c
PZ
13139 if (bgp->vrf_id == VRF_UNKNOWN)
13140 vty_out(vty, "%s", VRFID_NONE_STR);
13141 else
13142 vty_out(vty, "%u", bgp->vrf_id);
13143 vty_out(vty, "\n");
01eced22
AD
13144 vty_out(vty, "Default local pref %u, ",
13145 bgp->default_local_pref);
13146 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13147 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13148 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13149 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13150
07d0c4ed
DA
13151 vty_out(vty, "Originating default network %s\n\n",
13152 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13153 }
13154 header1 = 0;
13155 }
a636c635 13156
9bcb3eef 13157 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13158 if (type == bgp_show_adj_route_received
13159 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13160 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13161 if (ain->peer != peer)
ea47320b 13162 continue;
6392aaa6 13163
2f9bc755
DS
13164 show_adj_route_header(
13165 vty, bgp, table, &header1, &header2,
13166 json, json_scode, json_ocode, wide);
6392aaa6 13167
6f4f49b2 13168 attr = *ain->attr;
f99def61
AD
13169 route_filtered = false;
13170
13171 /* Filter prefix using distribute list,
13172 * filter list or prefix list
13173 */
b54892e0 13174 const struct prefix *rn_p =
9bcb3eef 13175 bgp_dest_get_prefix(dest);
b54892e0
DS
13176 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13177 safi))
13178 == FILTER_DENY)
f99def61
AD
13179 route_filtered = true;
13180
13181 /* Filter prefix using route-map */
b54892e0
DS
13182 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13183 safi, rmap_name, NULL,
13184 0, NULL);
6392aaa6 13185
13c8e163
AD
13186 if (type == bgp_show_adj_route_filtered &&
13187 !route_filtered && ret != RMAP_DENY) {
b755861b 13188 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13189 continue;
d62a17ae 13190 }
6392aaa6 13191
13c8e163
AD
13192 if (type == bgp_show_adj_route_received &&
13193 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
13194 filtered_count++;
13195
b54892e0 13196 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13197 use_json, json_ar, wide);
b755861b 13198 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13199 output_count++;
d62a17ae 13200 }
6392aaa6 13201 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13202 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13203 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13204 if (paf->peer != peer || !adj->attr)
924c3f6a 13205 continue;
d62a17ae 13206
2f9bc755
DS
13207 show_adj_route_header(
13208 vty, bgp, table, &header1,
13209 &header2, json, json_scode,
13210 json_ocode, wide);
d62a17ae 13211
b54892e0 13212 const struct prefix *rn_p =
9bcb3eef 13213 bgp_dest_get_prefix(dest);
b54892e0 13214
6f4f49b2 13215 attr = *adj->attr;
b755861b 13216 ret = bgp_output_modifier(
b54892e0 13217 peer, rn_p, &attr, afi, safi,
b755861b 13218 rmap_name);
f46d8e1e 13219
b755861b 13220 if (ret != RMAP_DENY) {
b54892e0
DS
13221 route_vty_out_tmp(
13222 vty, rn_p, &attr, safi,
ae248832
MK
13223 use_json, json_ar,
13224 wide);
b755861b
PM
13225 output_count++;
13226 } else {
13227 filtered_count++;
a2addae8 13228 }
b755861b
PM
13229
13230 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13231 }
f20ce998
DS
13232 } else if (type == bgp_show_adj_route_bestpath) {
13233 struct bgp_path_info *pi;
13234
13235 show_adj_route_header(vty, bgp, table, &header1,
13236 &header2, json, json_scode,
13237 json_ocode, wide);
13238
13239 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13240 pi = pi->next) {
13241 if (pi->peer != peer)
13242 continue;
13243
13244 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13245 continue;
13246
13247 route_vty_out_tmp(vty,
13248 bgp_dest_get_prefix(dest),
13249 pi->attr, safi, use_json,
13250 json_ar, wide);
13251 output_count++;
13252 }
d62a17ae 13253 }
13254 }
d62a17ae 13255
d62a17ae 13256 if (use_json) {
6392aaa6
PM
13257 json_object_object_add(json, "advertisedRoutes", json_ar);
13258 json_object_int_add(json, "totalPrefixCounter", output_count);
13259 json_object_int_add(json, "filteredPrefixCounter",
13260 filtered_count);
13261
996c9314
LB
13262 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13263 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13264
13265 if (!output_count && !filtered_count) {
13266 json_object_free(json_scode);
13267 json_object_free(json_ocode);
13268 }
13269
d62a17ae 13270 json_object_free(json);
6392aaa6
PM
13271 } else if (output_count > 0) {
13272 if (filtered_count > 0)
13273 vty_out(vty,
13274 "\nTotal number of prefixes %ld (%ld filtered)\n",
13275 output_count, filtered_count);
13276 else
13277 vty_out(vty, "\nTotal number of prefixes %ld\n",
13278 output_count);
d62a17ae 13279 }
a636c635 13280}
2a71e9ce 13281
d62a17ae 13282static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13283 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13284 const char *rmap_name, uint8_t show_flags)
0b16f239 13285{
d62a17ae 13286 json_object *json = NULL;
96f3485c 13287 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13288
d62a17ae 13289 if (use_json)
13290 json = json_object_new_object();
0b16f239 13291
d62a17ae 13292 if (!peer || !peer->afc[afi][safi]) {
13293 if (use_json) {
13294 json_object_string_add(
13295 json, "warning",
13296 "No such neighbor or address family");
13297 vty_out(vty, "%s\n", json_object_to_json_string(json));
13298 json_object_free(json);
13299 } else
13300 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13301
d62a17ae 13302 return CMD_WARNING;
13303 }
13304
6392aaa6
PM
13305 if ((type == bgp_show_adj_route_received
13306 || type == bgp_show_adj_route_filtered)
d62a17ae 13307 && !CHECK_FLAG(peer->af_flags[afi][safi],
13308 PEER_FLAG_SOFT_RECONFIG)) {
13309 if (use_json) {
13310 json_object_string_add(
13311 json, "warning",
13312 "Inbound soft reconfiguration not enabled");
13313 vty_out(vty, "%s\n", json_object_to_json_string(json));
13314 json_object_free(json);
13315 } else
13316 vty_out(vty,
13317 "%% Inbound soft reconfiguration not enabled\n");
13318
13319 return CMD_WARNING;
13320 }
0b16f239 13321
96f3485c 13322 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13323
d62a17ae 13324 return CMD_SUCCESS;
a636c635 13325}
50ef26d4 13326
f20ce998
DS
13327DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13328 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13329 "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]",
13330 SHOW_STR
13331 IP_STR
13332 BGP_STR
13333 BGP_INSTANCE_HELP_STR
13334 BGP_AFI_HELP_STR
13335 BGP_SAFI_WITH_LABEL_HELP_STR
13336 "Detailed information on TCP and BGP neighbor connections\n"
13337 "Neighbor to display information about\n"
13338 "Neighbor to display information about\n"
13339 "Neighbor on BGP configured interface\n"
13340 "Display the routes selected by best path\n"
13341 JSON_STR
13342 "Increase table width for longer prefixes\n")
13343{
13344 afi_t afi = AFI_IP6;
13345 safi_t safi = SAFI_UNICAST;
13346 char *rmap_name = NULL;
13347 char *peerstr = NULL;
13348 struct bgp *bgp = NULL;
13349 struct peer *peer;
13350 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13351 int idx = 0;
96f3485c
MK
13352 uint8_t show_flags = 0;
13353
13354 if (uj)
13355 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13356
13357 if (wide)
13358 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13359
13360 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13361 &bgp, uj);
13362
13363 if (!idx)
13364 return CMD_WARNING;
13365
13366 argv_find(argv, argc, "neighbors", &idx);
13367 peerstr = argv[++idx]->arg;
13368
13369 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13370 if (!peer)
13371 return CMD_WARNING;
13372
96f3485c
MK
13373 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13374 show_flags);
f20ce998
DS
13375}
13376
ae248832 13377DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13378 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13379 "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 13380 SHOW_STR
13381 IP_STR
13382 BGP_STR
a636c635 13383 BGP_INSTANCE_HELP_STR
7395a2c9 13384 BGP_AFI_HELP_STR
4dd6177e 13385 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13386 "Display the entries for all address families\n"
718e3744 13387 "Detailed information on TCP and BGP neighbor connections\n"
13388 "Neighbor to display information about\n"
13389 "Neighbor to display information about\n"
91d37724 13390 "Neighbor on BGP configured interface\n"
a636c635 13391 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13392 "Display the received routes from neighbor\n"
13393 "Display the filtered routes received from neighbor\n"
a636c635
DW
13394 "Route-map to modify the attributes\n"
13395 "Name of the route map\n"
ae248832
MK
13396 JSON_STR
13397 "Increase table width for longer prefixes\n")
718e3744 13398{
d62a17ae 13399 afi_t afi = AFI_IP6;
13400 safi_t safi = SAFI_UNICAST;
13401 char *rmap_name = NULL;
13402 char *peerstr = NULL;
d62a17ae 13403 struct bgp *bgp = NULL;
13404 struct peer *peer;
6392aaa6 13405 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13406 int idx = 0;
96f3485c
MK
13407 bool first = true;
13408 uint8_t show_flags = 0;
6392aaa6 13409
96f3485c 13410 if (uj) {
d62a17ae 13411 argc--;
96f3485c
MK
13412 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13413 }
13414
13415 if (all) {
13416 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13417 if (argv_find(argv, argc, "ipv4", &idx))
13418 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13419
13420 if (argv_find(argv, argc, "ipv6", &idx))
13421 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13422 }
13423
13424 if (wide)
13425 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13426
9f049418
DS
13427 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13428 &bgp, uj);
13429 if (!idx)
13430 return CMD_WARNING;
13431
d62a17ae 13432 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13433 argv_find(argv, argc, "neighbors", &idx);
13434 peerstr = argv[++idx]->arg;
8c3deaae 13435
d62a17ae 13436 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13437 if (!peer)
13438 return CMD_WARNING;
856ca177 13439
d62a17ae 13440 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13441 type = bgp_show_adj_route_advertised;
13442 else if (argv_find(argv, argc, "received-routes", &idx))
13443 type = bgp_show_adj_route_received;
13444 else if (argv_find(argv, argc, "filtered-routes", &idx))
13445 type = bgp_show_adj_route_filtered;
13446
d62a17ae 13447 if (argv_find(argv, argc, "route-map", &idx))
13448 rmap_name = argv[++idx]->arg;
95cbbd2a 13449
96f3485c
MK
13450 if (!all)
13451 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13452 show_flags);
13453 if (uj)
13454 vty_out(vty, "{\n");
13455
13456 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13457 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13458 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13459 : AFI_IP6;
13460 FOREACH_SAFI (safi) {
96f3485c
MK
13461 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13462 continue;
13463
13464 if (uj) {
13465 if (first)
13466 first = false;
13467 else
13468 vty_out(vty, ",\n");
13469 vty_out(vty, "\"%s\":",
13470 get_afi_safi_str(afi, safi, true));
13471 } else
13472 vty_out(vty, "\nFor address family: %s\n",
13473 get_afi_safi_str(afi, safi, false));
13474
13475 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13476 show_flags);
13477 }
13478 } else {
13479 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13480 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13481 continue;
13482
13483 if (uj) {
13484 if (first)
13485 first = false;
13486 else
13487 vty_out(vty, ",\n");
13488 vty_out(vty, "\"%s\":",
13489 get_afi_safi_str(afi, safi, true));
13490 } else
13491 vty_out(vty, "\nFor address family: %s\n",
13492 get_afi_safi_str(afi, safi, false));
13493
13494 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13495 show_flags);
13496 }
13497 }
13498 if (uj)
13499 vty_out(vty, "}\n");
13500
13501 return CMD_SUCCESS;
95cbbd2a
ML
13502}
13503
718e3744 13504DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13505 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13506 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13507 SHOW_STR
13508 IP_STR
13509 BGP_STR
8c3deaae
QY
13510 "Address Family\n"
13511 "Address Family\n"
718e3744 13512 "Address Family modifier\n"
13513 "Detailed information on TCP and BGP neighbor connections\n"
13514 "Neighbor to display information about\n"
13515 "Neighbor to display information about\n"
91d37724 13516 "Neighbor on BGP configured interface\n"
718e3744 13517 "Display information received from a BGP neighbor\n"
856ca177 13518 "Display the prefixlist filter\n"
9973d184 13519 JSON_STR)
718e3744 13520{
d62a17ae 13521 afi_t afi = AFI_IP6;
13522 safi_t safi = SAFI_UNICAST;
13523 char *peerstr = NULL;
13524
13525 char name[BUFSIZ];
13526 union sockunion su;
13527 struct peer *peer;
13528 int count, ret;
13529
13530 int idx = 0;
13531
13532 /* show [ip] bgp */
13533 if (argv_find(argv, argc, "ip", &idx))
13534 afi = AFI_IP;
13535 /* [<ipv4|ipv6> [unicast]] */
13536 if (argv_find(argv, argc, "ipv4", &idx))
13537 afi = AFI_IP;
13538 if (argv_find(argv, argc, "ipv6", &idx))
13539 afi = AFI_IP6;
13540 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13541 argv_find(argv, argc, "neighbors", &idx);
13542 peerstr = argv[++idx]->arg;
13543
9f049418 13544 bool uj = use_json(argc, argv);
d62a17ae 13545
13546 ret = str2sockunion(peerstr, &su);
13547 if (ret < 0) {
13548 peer = peer_lookup_by_conf_if(NULL, peerstr);
13549 if (!peer) {
13550 if (uj)
13551 vty_out(vty, "{}\n");
13552 else
13553 vty_out(vty,
13554 "%% Malformed address or name: %s\n",
13555 peerstr);
13556 return CMD_WARNING;
13557 }
13558 } else {
13559 peer = peer_lookup(NULL, &su);
13560 if (!peer) {
13561 if (uj)
13562 vty_out(vty, "{}\n");
13563 else
13564 vty_out(vty, "No peer\n");
13565 return CMD_WARNING;
13566 }
13567 }
718e3744 13568
4ced1a2c 13569 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13570 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13571 if (count) {
13572 if (!uj)
13573 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13574 get_afi_safi_str(afi, safi, false));
d62a17ae 13575 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13576 } else {
13577 if (uj)
13578 vty_out(vty, "{}\n");
13579 else
13580 vty_out(vty, "No functional output\n");
13581 }
718e3744 13582
d62a17ae 13583 return CMD_SUCCESS;
13584}
13585
13586static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13587 afi_t afi, safi_t safi,
9f049418 13588 enum bgp_show_type type, bool use_json)
d62a17ae 13589{
96f3485c
MK
13590 uint8_t show_flags = 0;
13591
13592 if (use_json)
13593 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13594
d62a17ae 13595 if (!peer || !peer->afc[afi][safi]) {
13596 if (use_json) {
13597 json_object *json_no = NULL;
13598 json_no = json_object_new_object();
13599 json_object_string_add(
13600 json_no, "warning",
13601 "No such neighbor or address family");
13602 vty_out(vty, "%s\n",
13603 json_object_to_json_string(json_no));
13604 json_object_free(json_no);
13605 } else
13606 vty_out(vty, "%% No such neighbor or address family\n");
13607 return CMD_WARNING;
13608 }
47fc97cc 13609
7daf25a3
TA
13610 /* labeled-unicast routes live in the unicast table */
13611 if (safi == SAFI_LABELED_UNICAST)
13612 safi = SAFI_UNICAST;
13613
96f3485c 13614 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13615}
13616
dba3c1d3
PG
13617DEFUN (show_ip_bgp_flowspec_routes_detailed,
13618 show_ip_bgp_flowspec_routes_detailed_cmd,
13619 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13620 SHOW_STR
13621 IP_STR
13622 BGP_STR
13623 BGP_INSTANCE_HELP_STR
13624 BGP_AFI_HELP_STR
13625 "SAFI Flowspec\n"
13626 "Detailed information on flowspec entries\n"
13627 JSON_STR)
13628{
13629 afi_t afi = AFI_IP;
13630 safi_t safi = SAFI_UNICAST;
13631 struct bgp *bgp = NULL;
13632 int idx = 0;
9f049418 13633 bool uj = use_json(argc, argv);
96f3485c 13634 uint8_t show_flags = 0;
9f049418 13635
96f3485c 13636 if (uj) {
9f049418 13637 argc--;
96f3485c
MK
13638 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13639 }
dba3c1d3
PG
13640
13641 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13642 &bgp, uj);
dba3c1d3
PG
13643 if (!idx)
13644 return CMD_WARNING;
13645
96f3485c
MK
13646 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13647 show_flags);
dba3c1d3
PG
13648}
13649
718e3744 13650DEFUN (show_ip_bgp_neighbor_routes,
13651 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13652 "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 13653 SHOW_STR
13654 IP_STR
13655 BGP_STR
8386ac43 13656 BGP_INSTANCE_HELP_STR
4f280b15 13657 BGP_AFI_HELP_STR
4dd6177e 13658 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13659 "Detailed information on TCP and BGP neighbor connections\n"
13660 "Neighbor to display information about\n"
13661 "Neighbor to display information about\n"
91d37724 13662 "Neighbor on BGP configured interface\n"
2525cf39 13663 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13664 "Display the dampened routes received from neighbor\n"
13665 "Display routes learned from neighbor\n"
9973d184 13666 JSON_STR)
718e3744 13667{
d62a17ae 13668 char *peerstr = NULL;
13669 struct bgp *bgp = NULL;
13670 afi_t afi = AFI_IP6;
13671 safi_t safi = SAFI_UNICAST;
13672 struct peer *peer;
13673 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13674 int idx = 0;
9f049418
DS
13675 bool uj = use_json(argc, argv);
13676
13677 if (uj)
13678 argc--;
bb46e94f 13679
d62a17ae 13680 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13681 &bgp, uj);
d62a17ae 13682 if (!idx)
13683 return CMD_WARNING;
c493f2d8 13684
d62a17ae 13685 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13686 argv_find(argv, argc, "neighbors", &idx);
13687 peerstr = argv[++idx]->arg;
8c3deaae 13688
d62a17ae 13689 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13690 if (!peer)
d62a17ae 13691 return CMD_WARNING;
bb46e94f 13692
d62a17ae 13693 if (argv_find(argv, argc, "flap-statistics", &idx))
13694 sh_type = bgp_show_type_flap_neighbor;
13695 else if (argv_find(argv, argc, "dampened-routes", &idx))
13696 sh_type = bgp_show_type_damp_neighbor;
13697 else if (argv_find(argv, argc, "routes", &idx))
13698 sh_type = bgp_show_type_neighbor;
2525cf39 13699
d62a17ae 13700 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13701}
6b0655a2 13702
734b349e 13703struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13704
d62a17ae 13705struct bgp_distance {
13706 /* Distance value for the IP source prefix. */
d7c0a89a 13707 uint8_t distance;
718e3744 13708
d62a17ae 13709 /* Name of the access-list to be matched. */
13710 char *access_list;
718e3744 13711};
13712
4f280b15
LB
13713DEFUN (show_bgp_afi_vpn_rd_route,
13714 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13715 "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
13716 SHOW_STR
13717 BGP_STR
13718 BGP_AFI_HELP_STR
13719 "Address Family modifier\n"
13720 "Display information for a route distinguisher\n"
13721 "Route Distinguisher\n"
7395a2c9
DS
13722 "Network in the BGP routing table to display\n"
13723 "Network in the BGP routing table to display\n"
13724 JSON_STR)
4f280b15 13725{
d62a17ae 13726 int ret;
13727 struct prefix_rd prd;
13728 afi_t afi = AFI_MAX;
13729 int idx = 0;
4f280b15 13730
ff6566f3
DS
13731 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13732 vty_out(vty, "%% Malformed Address Family\n");
13733 return CMD_WARNING;
13734 }
13735
d62a17ae 13736 ret = str2prefix_rd(argv[5]->arg, &prd);
13737 if (!ret) {
13738 vty_out(vty, "%% Malformed Route Distinguisher\n");
13739 return CMD_WARNING;
13740 }
ff6566f3 13741
d62a17ae 13742 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13743 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13744}
13745
d62a17ae 13746static struct bgp_distance *bgp_distance_new(void)
718e3744 13747{
d62a17ae 13748 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13749}
13750
d62a17ae 13751static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13752{
d62a17ae 13753 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13754}
13755
37a87b8f
CS
13756int bgp_distance_set(uint8_t distance, const char *ip_str,
13757 const char *access_list_str, afi_t afi, safi_t safi,
13758 char *errmsg, size_t errmsg_len)
718e3744 13759{
d62a17ae 13760 int ret;
d62a17ae 13761 struct prefix p;
9bcb3eef 13762 struct bgp_dest *dest;
d62a17ae 13763 struct bgp_distance *bdistance;
718e3744 13764
d62a17ae 13765 ret = str2prefix(ip_str, &p);
13766 if (ret == 0) {
37a87b8f 13767 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13768 return CMD_WARNING_CONFIG_FAILED;
13769 }
718e3744 13770
d62a17ae 13771 /* Get BGP distance node. */
9bcb3eef
DS
13772 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13773 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13774 if (bdistance)
9bcb3eef 13775 bgp_dest_unlock_node(dest);
ca2e160d 13776 else {
d62a17ae 13777 bdistance = bgp_distance_new();
9bcb3eef 13778 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13779 }
718e3744 13780
d62a17ae 13781 /* Set distance value. */
13782 bdistance->distance = distance;
718e3744 13783
d62a17ae 13784 /* Reset access-list configuration. */
e1b36e13 13785 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13786 if (access_list_str)
13787 bdistance->access_list =
13788 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13789
d62a17ae 13790 return CMD_SUCCESS;
718e3744 13791}
13792
37a87b8f
CS
13793int bgp_distance_unset(uint8_t distance, const char *ip_str,
13794 const char *access_list_str, afi_t afi, safi_t safi,
13795 char *errmsg, size_t errmsg_len)
718e3744 13796{
d62a17ae 13797 int ret;
d62a17ae 13798 struct prefix p;
9bcb3eef 13799 struct bgp_dest *dest;
d62a17ae 13800 struct bgp_distance *bdistance;
718e3744 13801
d62a17ae 13802 ret = str2prefix(ip_str, &p);
13803 if (ret == 0) {
37a87b8f 13804 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13805 return CMD_WARNING_CONFIG_FAILED;
13806 }
718e3744 13807
9bcb3eef
DS
13808 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13809 if (!dest) {
37a87b8f 13810 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13811 return CMD_WARNING_CONFIG_FAILED;
13812 }
718e3744 13813
9bcb3eef 13814 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13815
d62a17ae 13816 if (bdistance->distance != distance) {
37a87b8f
CS
13817 snprintf(errmsg, errmsg_len,
13818 "Distance does not match configured\n");
d62a17ae 13819 return CMD_WARNING_CONFIG_FAILED;
13820 }
718e3744 13821
0a22ddfb 13822 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13823 bgp_distance_free(bdistance);
718e3744 13824
9bcb3eef
DS
13825 bgp_dest_set_bgp_path_info(dest, NULL);
13826 bgp_dest_unlock_node(dest);
13827 bgp_dest_unlock_node(dest);
718e3744 13828
d62a17ae 13829 return CMD_SUCCESS;
718e3744 13830}
13831
718e3744 13832/* Apply BGP information to distance method. */
b8685f9b 13833uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13834 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13835{
9bcb3eef 13836 struct bgp_dest *dest;
801bb996 13837 struct prefix q = {0};
d62a17ae 13838 struct peer *peer;
13839 struct bgp_distance *bdistance;
13840 struct access_list *alist;
13841 struct bgp_static *bgp_static;
13842
13843 if (!bgp)
13844 return 0;
13845
40381db7 13846 peer = pinfo->peer;
d62a17ae 13847
7b7d48e5
DS
13848 if (pinfo->attr->distance)
13849 return pinfo->attr->distance;
13850
801bb996
CS
13851 /* Check source address.
13852 * Note: for aggregate route, peer can have unspec af type.
13853 */
13854 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13855 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
13856 return 0;
13857
9bcb3eef
DS
13858 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13859 if (dest) {
13860 bdistance = bgp_dest_get_bgp_distance_info(dest);
13861 bgp_dest_unlock_node(dest);
d62a17ae 13862
13863 if (bdistance->access_list) {
13864 alist = access_list_lookup(afi, bdistance->access_list);
13865 if (alist
13866 && access_list_apply(alist, p) == FILTER_PERMIT)
13867 return bdistance->distance;
13868 } else
13869 return bdistance->distance;
718e3744 13870 }
718e3744 13871
d62a17ae 13872 /* Backdoor check. */
9bcb3eef
DS
13873 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13874 if (dest) {
13875 bgp_static = bgp_dest_get_bgp_static_info(dest);
13876 bgp_dest_unlock_node(dest);
718e3744 13877
d62a17ae 13878 if (bgp_static->backdoor) {
13879 if (bgp->distance_local[afi][safi])
13880 return bgp->distance_local[afi][safi];
13881 else
13882 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13883 }
718e3744 13884 }
718e3744 13885
d62a17ae 13886 if (peer->sort == BGP_PEER_EBGP) {
13887 if (bgp->distance_ebgp[afi][safi])
13888 return bgp->distance_ebgp[afi][safi];
13889 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 13890 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 13891 if (bgp->distance_ibgp[afi][safi])
13892 return bgp->distance_ibgp[afi][safi];
13893 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
13894 } else {
13895 if (bgp->distance_local[afi][safi])
13896 return bgp->distance_local[afi][safi];
13897 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 13898 }
718e3744 13899}
13900
a612fb77
DA
13901/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13902 * we should tell ZEBRA update the routes for a specific
13903 * AFI/SAFI to reflect changes in RIB.
13904 */
37a87b8f
CS
13905void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13906 safi_t update_safi)
a612fb77
DA
13907{
13908 afi_t afi;
13909 safi_t safi;
13910
13911 FOREACH_AFI_SAFI (afi, safi) {
13912 if (!bgp_fibupd_safi(safi))
13913 continue;
13914
8b54bc30
DA
13915 if (afi != update_afi && safi != update_safi)
13916 continue;
13917
13918 if (BGP_DEBUG(zebra, ZEBRA))
13919 zlog_debug(
13920 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13921 __func__, afi, safi);
13922 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13923 }
13924}
13925
37a87b8f
CS
13926DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13927 "distance bgp (1-255) (1-255) (1-255)",
13928 "Define an administrative distance\n"
13929 "BGP distance\n"
13930 "Distance for routes external to the AS\n"
13931 "Distance for routes internal to the AS\n"
13932 "Distance for local routes\n")
718e3744 13933{
d62a17ae 13934 int idx_number = 2;
13935 int idx_number_2 = 3;
13936 int idx_number_3 = 4;
13937 afi_t afi;
13938 safi_t safi;
37a87b8f 13939 char xpath[XPATH_MAXLEN];
718e3744 13940
d62a17ae 13941 afi = bgp_node_afi(vty);
13942 safi = bgp_node_safi(vty);
718e3744 13943
37a87b8f
CS
13944 snprintf(
13945 xpath, sizeof(xpath),
13946 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13947 yang_afi_safi_value2identity(afi, safi),
13948 bgp_afi_safi_get_container_str(afi, safi));
13949 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13950 snprintf(
13951 xpath, sizeof(xpath),
13952 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13953 yang_afi_safi_value2identity(afi, safi),
13954 bgp_afi_safi_get_container_str(afi, safi));
13955 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13956 argv[idx_number_2]->arg);
13957 snprintf(
13958 xpath, sizeof(xpath),
13959 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13960 yang_afi_safi_value2identity(afi, safi),
13961 bgp_afi_safi_get_container_str(afi, safi));
13962
13963 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13964 argv[idx_number_3]->arg);
13965
13966 return nb_cli_apply_changes(vty, NULL);
13967}
13968
13969DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13970 "no distance bgp [(1-255) (1-255) (1-255)]",
13971 NO_STR
13972 "Define an administrative distance\n"
13973 "BGP distance\n"
13974 "Distance for routes external to the AS\n"
13975 "Distance for routes internal to the AS\n"
13976 "Distance for local routes\n")
13977{
13978 afi_t afi;
13979 safi_t safi;
13980 char xpath[XPATH_MAXLEN];
13981
13982 afi = bgp_node_afi(vty);
13983 safi = bgp_node_safi(vty);
13984
13985 snprintf(
13986 xpath, sizeof(xpath),
13987 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13988 yang_afi_safi_value2identity(afi, safi),
13989 bgp_afi_safi_get_container_str(afi, safi));
13990 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13991 snprintf(
13992 xpath, sizeof(xpath),
13993 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13994 yang_afi_safi_value2identity(afi, safi),
13995 bgp_afi_safi_get_container_str(afi, safi));
13996 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13997 snprintf(
13998 xpath, sizeof(xpath),
13999 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14000 yang_afi_safi_value2identity(afi, safi),
14001 bgp_afi_safi_get_container_str(afi, safi));
14002
14003 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14004
14005 return nb_cli_apply_changes(vty, NULL);
718e3744 14006}
14007
37a87b8f
CS
14008void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14009 struct lyd_node *dnode,
14010 bool show_defaults)
718e3744 14011{
37a87b8f
CS
14012 uint8_t distance_ebgp, distance_ibgp, distance_local;
14013
14014 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14015 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14016 distance_local = yang_dnode_get_uint8(dnode, "./local");
14017
14018 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14019 distance_local);
14020}
14021
8cc7152a
CS
14022DEFPY_YANG(bgp_distance_source,
14023 bgp_distance_source_cmd,
14024 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14025 NO_STR
14026 "Define an administrative distance\n"
8cc7152a 14027 "Distance value\n"
e12affc1
SW
14028 "IPv4 source prefix\n"
14029 "IPv6 source prefix\n"
37a87b8f 14030 "Access list name\n")
718e3744 14031{
37a87b8f
CS
14032 afi_t afi;
14033 safi_t safi;
14034 char xpath[XPATH_MAXLEN];
14035
14036 afi = bgp_node_afi(vty);
14037 safi = bgp_node_safi(vty);
14038
8cc7152a
CS
14039 if (!no) {
14040 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14041 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14042 distance_str);
14043 if (acl)
14044 nb_cli_enqueue_change(vty,
14045 "./access-list-policy-export",
14046 NB_OP_CREATE, acl);
14047 else
14048 nb_cli_enqueue_change(vty,
14049 "./access-list-policy-export",
14050 NB_OP_DESTROY, NULL);
14051 } else {
14052 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14053 }
37a87b8f
CS
14054
14055 snprintf(
14056 xpath, sizeof(xpath),
14057 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14058 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14059 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14060
14061 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14062}
14063
37a87b8f
CS
14064void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14065 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14066{
14067 vty_out(vty, " distance %d %s %s\n",
14068 yang_dnode_get_uint8(dnode, "./distance"),
14069 yang_dnode_get_string(dnode, "./prefix"),
14070 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14071 ? yang_dnode_get_string(dnode,
14072 "./access-list-policy-export")
14073 : "");
14074}
14075
7c98d487
DA
14076DEFPY_YANG(
14077 bgp_dampening, bgp_dampening_cmd,
14078 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14079 NO_STR
14080 "BGP Specific commands\n"
14081 "Enable route-flap dampening\n"
14082 "Half-life time for the penalty\n"
14083 "Value to start reusing a route\n"
14084 "Value to start suppressing a route\n"
14085 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14086{
14087 afi_t afi;
14088 safi_t safi;
14089 char xpath[XPATH_MAXLEN];
718e3744 14090
37a87b8f
CS
14091 afi = bgp_node_afi(vty);
14092 safi = bgp_node_safi(vty);
14093
d9ce5113
CS
14094 if (!no) {
14095 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14096 if (argc == 6) {
14097 nb_cli_enqueue_change(vty, "./reach-decay",
14098 NB_OP_MODIFY, halflife_str);
14099 nb_cli_enqueue_change(vty, "./reuse-above",
14100 NB_OP_MODIFY, reuse_str);
14101 nb_cli_enqueue_change(vty, "./suppress-above",
14102 NB_OP_MODIFY, suppress_str);
14103 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14104 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14105 } if (argc == 3) {
14106 nb_cli_enqueue_change(vty, "./reach-decay",
14107 NB_OP_MODIFY, halflife_str);
14108 }
14109 } else {
14110 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14111 }
7ebe9748 14112
37a87b8f
CS
14113 snprintf(
14114 xpath, sizeof(xpath),
14115 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14116 yang_afi_safi_value2identity(afi, safi),
14117 bgp_afi_safi_get_container_str(afi, safi));
14118
14119 return nb_cli_apply_changes(vty, xpath);
718e3744 14120}
14121
37a87b8f
CS
14122void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14123 struct lyd_node *dnode,
14124 bool show_defaults)
718e3744 14125{
37a87b8f
CS
14126 if (!yang_dnode_get_bool(dnode, "./enable"))
14127 return;
14128
14129 int half = DEFAULT_HALF_LIFE * 60;
14130 int reuse = DEFAULT_REUSE;
14131 int suppress = DEFAULT_SUPPRESS;
14132 int max;
14133
14134 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14135 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14136 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14137 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14138
14139 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14140 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14141 vty_out(vty, " bgp dampening\n");
14142 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14143 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14144 vty_out(vty, " bgp dampening %u\n", half);
14145 else
14146 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14147 suppress, max);
718e3744 14148}
14149
718e3744 14150/* Display specified route of BGP table. */
d62a17ae 14151static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14152 const char *ip_str, afi_t afi, safi_t safi,
14153 struct prefix_rd *prd, int prefix_check)
14154{
14155 int ret;
14156 struct prefix match;
9bcb3eef
DS
14157 struct bgp_dest *dest;
14158 struct bgp_dest *rm;
40381db7
DS
14159 struct bgp_path_info *pi;
14160 struct bgp_path_info *pi_temp;
d62a17ae 14161 struct bgp *bgp;
14162 struct bgp_table *table;
14163
14164 /* BGP structure lookup. */
14165 if (view_name) {
14166 bgp = bgp_lookup_by_name(view_name);
14167 if (bgp == NULL) {
14168 vty_out(vty, "%% Can't find BGP instance %s\n",
14169 view_name);
14170 return CMD_WARNING;
14171 }
14172 } else {
14173 bgp = bgp_get_default();
14174 if (bgp == NULL) {
14175 vty_out(vty, "%% No BGP process is configured\n");
14176 return CMD_WARNING;
14177 }
718e3744 14178 }
718e3744 14179
d62a17ae 14180 /* Check IP address argument. */
14181 ret = str2prefix(ip_str, &match);
14182 if (!ret) {
14183 vty_out(vty, "%% address is malformed\n");
14184 return CMD_WARNING;
14185 }
718e3744 14186
d62a17ae 14187 match.family = afi2family(afi);
14188
14189 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14190 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14191 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14192 dest = bgp_route_next(dest)) {
14193 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14194
9bcb3eef 14195 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14196 continue;
9bcb3eef 14197 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14198 if (!table)
ea47320b
DL
14199 continue;
14200 if ((rm = bgp_node_match(table, &match)) == NULL)
14201 continue;
d62a17ae 14202
9bcb3eef 14203 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14204
ea47320b 14205 if (!prefix_check
b54892e0 14206 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14207 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14208 while (pi) {
14209 if (pi->extra && pi->extra->damp_info) {
14210 pi_temp = pi->next;
ea47320b 14211 bgp_damp_info_free(
40ec3340
DS
14212 &pi->extra->damp_info,
14213 &bgp->damp[afi][safi],
a935f597 14214 1, afi, safi);
40381db7 14215 pi = pi_temp;
ea47320b 14216 } else
40381db7 14217 pi = pi->next;
d62a17ae 14218 }
ea47320b
DL
14219 }
14220
9bcb3eef 14221 bgp_dest_unlock_node(rm);
d62a17ae 14222 }
14223 } else {
9bcb3eef 14224 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14225 != NULL) {
9bcb3eef 14226 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14227
d62a17ae 14228 if (!prefix_check
9bcb3eef
DS
14229 || dest_p->prefixlen == match.prefixlen) {
14230 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14231 while (pi) {
14232 if (pi->extra && pi->extra->damp_info) {
14233 pi_temp = pi->next;
d62a17ae 14234 bgp_damp_info_free(
40ec3340
DS
14235 &pi->extra->damp_info,
14236 &bgp->damp[afi][safi],
a935f597 14237 1, afi, safi);
40381db7 14238 pi = pi_temp;
d62a17ae 14239 } else
40381db7 14240 pi = pi->next;
d62a17ae 14241 }
14242 }
14243
9bcb3eef 14244 bgp_dest_unlock_node(dest);
d62a17ae 14245 }
14246 }
718e3744 14247
d62a17ae 14248 return CMD_SUCCESS;
718e3744 14249}
14250
14251DEFUN (clear_ip_bgp_dampening,
14252 clear_ip_bgp_dampening_cmd,
14253 "clear ip bgp dampening",
14254 CLEAR_STR
14255 IP_STR
14256 BGP_STR
14257 "Clear route flap dampening information\n")
14258{
40ec3340
DS
14259 VTY_DECLVAR_CONTEXT(bgp, bgp);
14260 bgp_damp_info_clean(&bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
14261 SAFI_UNICAST);
d62a17ae 14262 return CMD_SUCCESS;
718e3744 14263}
14264
14265DEFUN (clear_ip_bgp_dampening_prefix,
14266 clear_ip_bgp_dampening_prefix_cmd,
14267 "clear ip bgp dampening A.B.C.D/M",
14268 CLEAR_STR
14269 IP_STR
14270 BGP_STR
14271 "Clear route flap dampening information\n"
0c7b1b01 14272 "IPv4 prefix\n")
718e3744 14273{
d62a17ae 14274 int idx_ipv4_prefixlen = 4;
14275 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14276 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14277}
14278
14279DEFUN (clear_ip_bgp_dampening_address,
14280 clear_ip_bgp_dampening_address_cmd,
14281 "clear ip bgp dampening A.B.C.D",
14282 CLEAR_STR
14283 IP_STR
14284 BGP_STR
14285 "Clear route flap dampening information\n"
14286 "Network to clear damping information\n")
14287{
d62a17ae 14288 int idx_ipv4 = 4;
14289 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14290 SAFI_UNICAST, NULL, 0);
718e3744 14291}
14292
14293DEFUN (clear_ip_bgp_dampening_address_mask,
14294 clear_ip_bgp_dampening_address_mask_cmd,
14295 "clear ip bgp dampening A.B.C.D A.B.C.D",
14296 CLEAR_STR
14297 IP_STR
14298 BGP_STR
14299 "Clear route flap dampening information\n"
14300 "Network to clear damping information\n"
14301 "Network mask\n")
14302{
d62a17ae 14303 int idx_ipv4 = 4;
14304 int idx_ipv4_2 = 5;
14305 int ret;
14306 char prefix_str[BUFSIZ];
718e3744 14307
d62a17ae 14308 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14309 prefix_str);
14310 if (!ret) {
14311 vty_out(vty, "%% Inconsistent address and mask\n");
14312 return CMD_WARNING;
14313 }
718e3744 14314
d62a17ae 14315 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14316 NULL, 0);
718e3744 14317}
6b0655a2 14318
e3b78da8 14319static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14320{
14321 struct vty *vty = arg;
e3b78da8 14322 struct peer *peer = bucket->data;
825d9834
DS
14323 char buf[SU_ADDRSTRLEN];
14324
14325 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14326 sockunion2str(&peer->su, buf, sizeof(buf)));
14327}
14328
2a0e69ae
DS
14329DEFUN (show_bgp_listeners,
14330 show_bgp_listeners_cmd,
14331 "show bgp listeners",
14332 SHOW_STR
14333 BGP_STR
14334 "Display Listen Sockets and who created them\n")
14335{
14336 bgp_dump_listener_info(vty);
14337
14338 return CMD_SUCCESS;
14339}
14340
825d9834
DS
14341DEFUN (show_bgp_peerhash,
14342 show_bgp_peerhash_cmd,
14343 "show bgp peerhash",
14344 SHOW_STR
14345 BGP_STR
14346 "Display information about the BGP peerhash\n")
14347{
14348 struct list *instances = bm->bgp;
14349 struct listnode *node;
14350 struct bgp *bgp;
14351
14352 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14353 vty_out(vty, "BGP: %s\n", bgp->name);
14354 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14355 vty);
14356 }
14357
14358 return CMD_SUCCESS;
14359}
14360
587ff0fd 14361/* also used for encap safi */
2b791107
DL
14362static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14363 afi_t afi, safi_t safi)
d62a17ae 14364{
9bcb3eef
DS
14365 struct bgp_dest *pdest;
14366 struct bgp_dest *dest;
d62a17ae 14367 struct bgp_table *table;
b54892e0
DS
14368 const struct prefix *p;
14369 const struct prefix_rd *prd;
d62a17ae 14370 struct bgp_static *bgp_static;
14371 mpls_label_t label;
d62a17ae 14372 char rdbuf[RD_ADDRSTRLEN];
14373
14374 /* Network configuration. */
9bcb3eef
DS
14375 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14376 pdest = bgp_route_next(pdest)) {
14377 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14378 if (!table)
ea47320b 14379 continue;
d62a17ae 14380
9bcb3eef
DS
14381 for (dest = bgp_table_top(table); dest;
14382 dest = bgp_route_next(dest)) {
14383 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14384 if (bgp_static == NULL)
ea47320b 14385 continue;
d62a17ae 14386
9bcb3eef
DS
14387 p = bgp_dest_get_prefix(dest);
14388 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14389 pdest);
d62a17ae 14390
ea47320b 14391 /* "network" configuration display. */
06b9f471 14392 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14393 label = decode_label(&bgp_static->label);
14394
8228a9a7 14395 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14396 if (safi == SAFI_MPLS_VPN)
14397 vty_out(vty, " label %u", label);
14398
14399 if (bgp_static->rmap.name)
14400 vty_out(vty, " route-map %s",
14401 bgp_static->rmap.name);
e2a86ad9
DS
14402
14403 if (bgp_static->backdoor)
14404 vty_out(vty, " backdoor");
14405
ea47320b
DL
14406 vty_out(vty, "\n");
14407 }
14408 }
d62a17ae 14409}
14410
2b791107
DL
14411static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14412 afi_t afi, safi_t safi)
d62a17ae 14413{
9bcb3eef
DS
14414 struct bgp_dest *pdest;
14415 struct bgp_dest *dest;
d62a17ae 14416 struct bgp_table *table;
b54892e0
DS
14417 const struct prefix *p;
14418 const struct prefix_rd *prd;
d62a17ae 14419 struct bgp_static *bgp_static;
ff44f570 14420 char buf[PREFIX_STRLEN * 2];
d62a17ae 14421 char buf2[SU_ADDRSTRLEN];
14422 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14423 char esi_buf[ESI_BYTES];
d62a17ae 14424
14425 /* Network configuration. */
9bcb3eef
DS
14426 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14427 pdest = bgp_route_next(pdest)) {
14428 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14429 if (!table)
ea47320b 14430 continue;
d62a17ae 14431
9bcb3eef
DS
14432 for (dest = bgp_table_top(table); dest;
14433 dest = bgp_route_next(dest)) {
14434 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14435 if (bgp_static == NULL)
ea47320b 14436 continue;
d62a17ae 14437
ea47320b 14438 char *macrouter = NULL;
d62a17ae 14439
ea47320b
DL
14440 if (bgp_static->router_mac)
14441 macrouter = prefix_mac2str(
14442 bgp_static->router_mac, NULL, 0);
14443 if (bgp_static->eth_s_id)
0a50c248
AK
14444 esi_to_str(bgp_static->eth_s_id,
14445 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14446 p = bgp_dest_get_prefix(dest);
14447 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14448
ea47320b 14449 /* "network" configuration display. */
06b9f471 14450 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14451 if (p->u.prefix_evpn.route_type == 5) {
14452 char local_buf[PREFIX_STRLEN];
3714a385 14453 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14454 struct prefix_evpn *)p)
14455 ? AF_INET
14456 : AF_INET6;
3714a385 14457 inet_ntop(family,
14458 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14459 local_buf, PREFIX_STRLEN);
772270f3
QY
14460 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14461 p->u.prefix_evpn.prefix_addr
14462 .ip_prefix_length);
197cb530
PG
14463 } else {
14464 prefix2str(p, buf, sizeof(buf));
14465 }
ea47320b 14466
a4d82a8a
PZ
14467 if (bgp_static->gatewayIp.family == AF_INET
14468 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14469 inet_ntop(bgp_static->gatewayIp.family,
14470 &bgp_static->gatewayIp.u.prefix, buf2,
14471 sizeof(buf2));
ea47320b 14472 vty_out(vty,
7bcc8dac 14473 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14474 buf, rdbuf,
14475 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14476 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14477 macrouter);
14478
0a22ddfb 14479 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14480 }
14481 }
3da6fcd5
PG
14482}
14483
718e3744 14484/* Configuration of static route announcement and aggregate
14485 information. */
2b791107
DL
14486void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14487 safi_t safi)
d62a17ae 14488{
9bcb3eef 14489 struct bgp_dest *dest;
b54892e0 14490 const struct prefix *p;
d62a17ae 14491 struct bgp_static *bgp_static;
14492 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14493
2b791107
DL
14494 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14495 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14496 return;
14497 }
d62a17ae 14498
2b791107
DL
14499 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14500 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14501 return;
14502 }
d62a17ae 14503
14504 /* Network configuration. */
9bcb3eef
DS
14505 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14506 dest = bgp_route_next(dest)) {
14507 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14508 if (bgp_static == NULL)
ea47320b 14509 continue;
d62a17ae 14510
9bcb3eef 14511 p = bgp_dest_get_prefix(dest);
d62a17ae 14512
8228a9a7 14513 vty_out(vty, " network %pFX", p);
d62a17ae 14514
ea47320b
DL
14515 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14516 vty_out(vty, " label-index %u",
14517 bgp_static->label_index);
d62a17ae 14518
ea47320b
DL
14519 if (bgp_static->rmap.name)
14520 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14521
14522 if (bgp_static->backdoor)
14523 vty_out(vty, " backdoor");
718e3744 14524
ea47320b
DL
14525 vty_out(vty, "\n");
14526 }
14527
d62a17ae 14528 /* Aggregate-address configuration. */
9bcb3eef
DS
14529 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14530 dest = bgp_route_next(dest)) {
14531 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14532 if (bgp_aggregate == NULL)
ea47320b 14533 continue;
d62a17ae 14534
9bcb3eef 14535 p = bgp_dest_get_prefix(dest);
d62a17ae 14536
8228a9a7 14537 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14538
ea47320b
DL
14539 if (bgp_aggregate->as_set)
14540 vty_out(vty, " as-set");
d62a17ae 14541
ea47320b
DL
14542 if (bgp_aggregate->summary_only)
14543 vty_out(vty, " summary-only");
718e3744 14544
20894f50
DA
14545 if (bgp_aggregate->rmap.name)
14546 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14547
229757f1
DA
14548 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14549 vty_out(vty, " origin %s",
14550 bgp_origin2str(bgp_aggregate->origin));
14551
6aabb15d
RZ
14552 if (bgp_aggregate->match_med)
14553 vty_out(vty, " matching-MED-only");
14554
365ab2e7
RZ
14555 if (bgp_aggregate->suppress_map_name)
14556 vty_out(vty, " suppress-map %s",
14557 bgp_aggregate->suppress_map_name);
14558
ea47320b
DL
14559 vty_out(vty, "\n");
14560 }
d62a17ae 14561}
734b349e 14562
2b791107 14563void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14564 safi_t safi)
d62a17ae 14565{
9bcb3eef 14566 struct bgp_dest *dest;
d62a17ae 14567 struct bgp_distance *bdistance;
14568
14569 /* Distance configuration. */
14570 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14571 && bgp->distance_local[afi][safi]
14572 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14573 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14574 || bgp->distance_local[afi][safi]
14575 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14576 vty_out(vty, " distance bgp %d %d %d\n",
14577 bgp->distance_ebgp[afi][safi],
14578 bgp->distance_ibgp[afi][safi],
14579 bgp->distance_local[afi][safi]);
14580 }
734b349e 14581
9bcb3eef
DS
14582 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14583 dest = bgp_route_next(dest)) {
14584 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14585 if (bdistance != NULL)
56ca3b5b 14586 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14587 bdistance->distance, dest,
d62a17ae 14588 bdistance->access_list ? bdistance->access_list
14589 : "");
ca2e160d 14590 }
718e3744 14591}
14592
14593/* Allocate routing table structure and install commands. */
d62a17ae 14594void bgp_route_init(void)
14595{
14596 afi_t afi;
14597 safi_t safi;
14598
14599 /* Init BGP distance table. */
05c7a1cc 14600 FOREACH_AFI_SAFI (afi, safi)
960035b2 14601 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14602
14603 /* IPv4 BGP commands. */
14604 install_element(BGP_NODE, &bgp_table_map_cmd);
14605 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14606 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14607
554b3b10 14608 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14609
14610 /* IPv4 unicast configuration. */
14611 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14612 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14613 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14614
554b3b10 14615 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14616
14617 /* IPv4 multicast configuration. */
14618 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14619 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14620 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14621 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14622
14623 /* IPv4 labeled-unicast configuration. */
fb985e0c 14624 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14625 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14626
d62a17ae 14627 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14628 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14629 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14630 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14631 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14632 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14633 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14634 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14635
14636 install_element(VIEW_NODE,
14637 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14638 install_element(VIEW_NODE,
14639 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14640 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14641 install_element(VIEW_NODE,
14642 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14643#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14644 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14645#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14646 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14647 install_element(VIEW_NODE,
44c69747 14648 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14649
d62a17ae 14650 /* BGP dampening clear commands */
14651 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14652 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14653
d62a17ae 14654 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14655 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14656
14657 /* prefix count */
14658 install_element(ENABLE_NODE,
14659 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14660#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14661 install_element(ENABLE_NODE,
14662 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14663#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14664
d62a17ae 14665 /* New config IPv6 BGP commands. */
14666 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14667 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14668 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14669
554b3b10 14670 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14671
14672 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14673
fb985e0c
DA
14674 /* IPv6 labeled unicast address family. */
14675 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14676 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14677
d62a17ae 14678 install_element(BGP_NODE, &bgp_distance_cmd);
14679 install_element(BGP_NODE, &no_bgp_distance_cmd);
14680 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14681 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14682 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14683 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14684 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14685 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14686 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14687 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14688 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14689 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14690 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14691 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14692 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14693
ef5f4b23 14694 /* BGP dampening */
d9ce5113
CS
14695 install_element(BGP_NODE, &bgp_dampening_cmd);
14696 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14697 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14698 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14699 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14700 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14701 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14702
14703 /* Large Communities */
14704 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14705 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14706
14707 /* show bgp ipv4 flowspec detailed */
14708 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14709
2a0e69ae 14710 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14711 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14712}
14713
14714void bgp_route_finish(void)
14715{
14716 afi_t afi;
14717 safi_t safi;
14718
05c7a1cc
QY
14719 FOREACH_AFI_SAFI (afi, safi) {
14720 bgp_table_unlock(bgp_distance_table[afi][safi]);
14721 bgp_distance_table[afi][safi] = NULL;
14722 }
228da428 14723}