]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #7882 from donaldsharp/keepalive_default
[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))
84c320dc 1839 zlog_debug("%s: community filter check fail", __func__);
3dc339cd 1840 return false;
d62a17ae 1841 }
3f9c7369 1842
d62a17ae 1843 /* If the attribute has originator-id and it is same as remote
1844 peer's id. */
40381db7
DS
1845 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1846 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1847 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1848 zlog_debug(
8228a9a7
DS
1849 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1850 onlypeer->host, p);
3dc339cd 1851 return false;
d62a17ae 1852 }
3f9c7369 1853
d62a17ae 1854 /* ORF prefix-list filter check */
1855 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1856 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1857 || CHECK_FLAG(peer->af_cap[afi][safi],
1858 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1859 if (peer->orf_plist[afi][safi]) {
1860 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1861 == PREFIX_DENY) {
1862 if (bgp_debug_update(NULL, p,
1863 subgrp->update_group, 0))
1864 zlog_debug(
8228a9a7
DS
1865 "%s [Update:SEND] %pFX is filtered via ORF",
1866 peer->host, p);
3dc339cd 1867 return false;
d62a17ae 1868 }
1869 }
1870
1871 /* Output filter check. */
40381db7 1872 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1873 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1874 zlog_debug("%s [Update:SEND] %pFX is filtered",
1875 peer->host, p);
3dc339cd 1876 return false;
d62a17ae 1877 }
3f9c7369 1878
d62a17ae 1879 /* AS path loop check. */
2b31007c
RZ
1880 if (onlypeer && onlypeer->as_path_loop_detection
1881 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1882 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1883 zlog_debug(
3efd0893 1884 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1885 onlypeer->host, onlypeer->as);
3dc339cd 1886 return false;
d62a17ae 1887 }
3f9c7369 1888
d62a17ae 1889 /* If we're a CONFED we need to loop check the CONFED ID too */
1890 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1891 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1892 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1893 zlog_debug(
3efd0893 1894 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1895 peer->host, bgp->confed_id);
3dc339cd 1896 return false;
d62a17ae 1897 }
3f9c7369 1898 }
3f9c7369 1899
d62a17ae 1900 /* Route-Reflect check. */
1901 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1902 reflect = 1;
1903 else
1904 reflect = 0;
1905
1906 /* IBGP reflection check. */
1907 if (reflect && !samepeer_safe) {
1908 /* A route from a Client peer. */
1909 if (CHECK_FLAG(from->af_flags[afi][safi],
1910 PEER_FLAG_REFLECTOR_CLIENT)) {
1911 /* Reflect to all the Non-Client peers and also to the
1912 Client peers other than the originator. Originator
1913 check
1914 is already done. So there is noting to do. */
1915 /* no bgp client-to-client reflection check. */
892fedb6
DA
1916 if (CHECK_FLAG(bgp->flags,
1917 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1918 if (CHECK_FLAG(peer->af_flags[afi][safi],
1919 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1920 return false;
d62a17ae 1921 } else {
1922 /* A route from a Non-client peer. Reflect to all other
1923 clients. */
1924 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1925 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1926 return false;
d62a17ae 1927 }
1928 }
3f9c7369 1929
d62a17ae 1930 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1931 *attr = *piattr;
d62a17ae 1932
1933 /* If local-preference is not set. */
1934 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1935 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1936 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1937 attr->local_pref = bgp->default_local_pref;
3f9c7369 1938 }
3f9c7369 1939
d62a17ae 1940 /* If originator-id is not set and the route is to be reflected,
1941 set the originator id */
1942 if (reflect
1943 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1944 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1945 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1946 }
3f9c7369 1947
d62a17ae 1948 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1949 */
1950 if (peer->sort == BGP_PEER_EBGP
1951 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1952 if (from != bgp->peer_self && !transparent
1953 && !CHECK_FLAG(peer->af_flags[afi][safi],
1954 PEER_FLAG_MED_UNCHANGED))
1955 attr->flag &=
1956 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1957 }
3f9c7369 1958
d62a17ae 1959 /* Since the nexthop attribute can vary per peer, it is not explicitly
1960 * set
1961 * in announce check, only certain flags and length (or number of
1962 * nexthops
1963 * -- for IPv6/MP_REACH) are set here in order to guide the update
1964 * formation
1965 * code in setting the nexthop(s) on a per peer basis in
1966 * reformat_peer().
1967 * Typically, the source nexthop in the attribute is preserved but in
1968 * the
1969 * scenarios where we know it will always be overwritten, we reset the
1970 * nexthop to "0" in an attempt to achieve better Update packing. An
1971 * example of this is when a prefix from each of 2 IBGP peers needs to
1972 * be
1973 * announced to an EBGP peer (and they have the same attributes barring
1974 * their nexthop).
1975 */
1976 if (reflect)
1977 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1978
1979#define NEXTHOP_IS_V6 \
1980 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1981 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1982 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1983 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1984
1985 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1986 * if
1987 * the peer (group) is configured to receive link-local nexthop
1988 * unchanged
c728d027
DA
1989 * and it is available in the prefix OR we're not reflecting the route,
1990 * link-local nexthop address is valid and
d62a17ae 1991 * the peer (group) to whom we're going to announce is on a shared
1992 * network
1993 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1994 * By checking if nexthop LL address is valid we are sure that
1995 * we do not announce LL address as `::`.
d62a17ae 1996 */
1997 if (NEXTHOP_IS_V6) {
1998 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1999 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2000 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2001 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2002 || (!reflect
2003 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2004 && peer->shared_network
d62a17ae 2005 && (from == bgp->peer_self
2006 || peer->sort == BGP_PEER_EBGP))) {
2007 attr->mp_nexthop_len =
2008 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2009 }
3f9c7369 2010
d62a17ae 2011 /* Clear off link-local nexthop in source, whenever it is not
2012 * needed to
2013 * ensure more prefixes share the same attribute for
2014 * announcement.
2015 */
2016 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2017 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2018 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2019 }
3f9c7369 2020
d62a17ae 2021 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2022 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2023
2024 /* Route map & unsuppress-map apply. */
7f7940e6 2025 if (!skip_rmap_check
e73c112e 2026 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2027 struct bgp_path_info rmap_path = {0};
2028 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2029 struct attr dummy_attr = {0};
d62a17ae 2030
e34291b8 2031 /* Fill temp path_info */
9bcb3eef
DS
2032 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2033 pi, peer, attr);
16f7ce2b 2034
d62a17ae 2035 /* don't confuse inbound and outbound setting */
2036 RESET_FLAG(attr->rmap_change_flags);
2037
2038 /*
2039 * The route reflector is not allowed to modify the attributes
2040 * of the reflected IBGP routes unless explicitly allowed.
2041 */
2042 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2043 && !CHECK_FLAG(bgp->flags,
2044 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2045 dummy_attr = *attr;
40381db7 2046 rmap_path.attr = &dummy_attr;
d62a17ae 2047 }
3f9c7369 2048
d62a17ae 2049 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2050
4056a5f6 2051 if (bgp_path_suppressed(pi))
d62a17ae 2052 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2053 &rmap_path);
d62a17ae 2054 else
2055 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2056 &rmap_path);
d62a17ae 2057
2058 peer->rmap_type = 0;
2059
2060 if (ret == RMAP_DENYMATCH) {
778048bf 2061 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2062 zlog_debug(
2063 "%s [Update:SEND] %pFX is filtered by route-map",
2064 peer->host, p);
778048bf 2065
d62a17ae 2066 bgp_attr_flush(attr);
3dc339cd 2067 return false;
d62a17ae 2068 }
3f9c7369 2069 }
3f9c7369 2070
9dac9fc8
DA
2071 /* RFC 8212 to prevent route leaks.
2072 * This specification intends to improve this situation by requiring the
2073 * explicit configuration of both BGP Import and Export Policies for any
2074 * External BGP (EBGP) session such as customers, peers, or
2075 * confederation boundaries for all enabled address families. Through
2076 * codification of the aforementioned requirement, operators will
2077 * benefit from consistent behavior across different BGP
2078 * implementations.
2079 */
1d3fdccf 2080 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2081 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2082 return false;
9dac9fc8 2083
fb29348a
DA
2084 /* draft-ietf-idr-deprecate-as-set-confed-set
2085 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2086 * Eventually, This document (if approved) updates RFC 4271
2087 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2088 * and obsoletes RFC 6472.
2089 */
7f972cd8 2090 if (peer->bgp->reject_as_sets)
fb29348a 2091 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2092 return false;
fb29348a 2093
33d022bc
DA
2094 /* Codification of AS 0 Processing */
2095 if (aspath_check_as_zero(attr->aspath))
e2369003 2096 return false;
33d022bc 2097
637e5ba4 2098 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2099 if (peer->sort == BGP_PEER_IBGP
2100 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2101 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2102 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2103 } else {
2104 bgp_attr_add_gshut_community(attr);
2105 }
2106 }
2107
d62a17ae 2108 /* After route-map has been applied, we check to see if the nexthop to
2109 * be carried in the attribute (that is used for the announcement) can
2110 * be cleared off or not. We do this in all cases where we would be
2111 * setting the nexthop to "ourselves". For IPv6, we only need to
2112 * consider
2113 * the global nexthop here; the link-local nexthop would have been
2114 * cleared
2115 * already, and if not, it is required by the update formation code.
2116 * Also see earlier comments in this function.
2117 */
2118 /*
2119 * If route-map has performed some operation on the nexthop or the peer
2120 * configuration says to pass it unchanged, we cannot reset the nexthop
2121 * here, so only attempt to do it if these aren't true. Note that the
2122 * route-map handler itself might have cleared the nexthop, if for
2123 * example,
2124 * it is configured as 'peer-address'.
2125 */
2126 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2127 piattr->rmap_change_flags)
d62a17ae 2128 && !transparent
2129 && !CHECK_FLAG(peer->af_flags[afi][safi],
2130 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2131 /* We can reset the nexthop, if setting (or forcing) it to
2132 * 'self' */
2133 if (CHECK_FLAG(peer->af_flags[afi][safi],
2134 PEER_FLAG_NEXTHOP_SELF)
2135 || CHECK_FLAG(peer->af_flags[afi][safi],
2136 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2137 if (!reflect
2138 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2139 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2140 subgroup_announce_reset_nhop(
2141 (peer_cap_enhe(peer, afi, safi)
2142 ? AF_INET6
2143 : p->family),
2144 attr);
7b651a32 2145 nh_reset = true;
2146 }
d62a17ae 2147 } else if (peer->sort == BGP_PEER_EBGP) {
2148 /* Can also reset the nexthop if announcing to EBGP, but
2149 * only if
2150 * no peer in the subgroup is on a shared subnet.
2151 * Note: 3rd party nexthop currently implemented for
2152 * IPv4 only.
2153 */
737af885
BS
2154 if ((p->family == AF_INET) &&
2155 (!bgp_subgrp_multiaccess_check_v4(
2156 piattr->nexthop,
7b651a32 2157 subgrp, from))) {
d62a17ae 2158 subgroup_announce_reset_nhop(
2159 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2160 ? AF_INET6
2161 : p->family),
737af885 2162 attr);
7b651a32 2163 nh_reset = true;
2164 }
737af885
BS
2165
2166 if ((p->family == AF_INET6) &&
2167 (!bgp_subgrp_multiaccess_check_v6(
2168 piattr->mp_nexthop_global,
7b651a32 2169 subgrp, from))) {
737af885
BS
2170 subgroup_announce_reset_nhop(
2171 (peer_cap_enhe(peer, afi, safi)
2172 ? AF_INET6
2173 : p->family),
2174 attr);
7b651a32 2175 nh_reset = true;
2176 }
737af885
BS
2177
2178
2179
40381db7 2180 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2181 /*
2182 * This flag is used for leaked vpn-vrf routes
2183 */
2184 int family = p->family;
2185
2186 if (peer_cap_enhe(peer, afi, safi))
2187 family = AF_INET6;
2188
2189 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2190 zlog_debug(
1defdda8 2191 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2192 __func__, family2str(family));
2193 subgroup_announce_reset_nhop(family, attr);
7b651a32 2194 nh_reset = true;
d62a17ae 2195 }
63696f1d 2196 }
960035b2 2197
63696f1d 2198 /* If IPv6/MP and nexthop does not have any override and happens
2199 * to
2200 * be a link-local address, reset it so that we don't pass along
2201 * the
2202 * source's link-local IPv6 address to recipients who may not be
2203 * on
2204 * the same interface.
2205 */
2206 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2207 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2208 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2209 nh_reset = true;
2210 }
d62a17ae 2211 }
3f9c7369 2212
7b651a32 2213 /*
2214 * When the next hop is set to ourselves, if all multipaths have
2215 * link-bandwidth announce the cumulative bandwidth as that makes
2216 * the most sense. However, don't modify if the link-bandwidth has
2217 * been explicitly set by user policy.
2218 */
2219 if (nh_reset &&
f7e1c681 2220 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2221 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2222 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2223 attr->ecommunity = ecommunity_replace_linkbw(
2224 bgp->as, attr->ecommunity, cum_bw);
2225
3dc339cd 2226 return true;
3f9c7369
DS
2227}
2228
f009ff26 2229static int bgp_route_select_timer_expire(struct thread *thread)
2230{
2231 struct afi_safi_info *info;
2232 afi_t afi;
2233 safi_t safi;
2234 struct bgp *bgp;
2235
2236 info = THREAD_ARG(thread);
2237 afi = info->afi;
2238 safi = info->safi;
2239 bgp = info->bgp;
2240
2241 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2242 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2243 safi);
f009ff26 2244
2245 bgp->gr_info[afi][safi].t_route_select = NULL;
2246
2247 XFREE(MTYPE_TMP, info);
2248
2249 /* Best path selection */
2250 return bgp_best_path_select_defer(bgp, afi, safi);
2251}
2252
9bcb3eef 2253void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2254 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2255 struct bgp_path_info_pair *result, afi_t afi,
2256 safi_t safi)
2257{
2258 struct bgp_path_info *new_select;
2259 struct bgp_path_info *old_select;
40381db7
DS
2260 struct bgp_path_info *pi;
2261 struct bgp_path_info *pi1;
2262 struct bgp_path_info *pi2;
2263 struct bgp_path_info *nextpi = NULL;
d62a17ae 2264 int paths_eq, do_mpath, debug;
2265 struct list mp_list;
2266 char pfx_buf[PREFIX2STR_BUFFER];
2267 char path_buf[PATH_ADDPATH_STR_BUFFER];
2268
2269 bgp_mp_list_init(&mp_list);
2270 do_mpath =
2271 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2272
9bcb3eef 2273 debug = bgp_debug_bestpath(dest);
d62a17ae 2274
2275 if (debug)
9bcb3eef 2276 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2277
9bcb3eef 2278 dest->reason = bgp_path_selection_none;
d62a17ae 2279 /* bgp deterministic-med */
2280 new_select = NULL;
892fedb6 2281 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2282
1defdda8 2283 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2284 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2285 pi1 = pi1->next)
9bcb3eef 2286 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2287 BGP_PATH_DMED_SELECTED);
d62a17ae 2288
9bcb3eef 2289 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2290 pi1 = pi1->next) {
40381db7 2291 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2292 continue;
40381db7 2293 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2294 continue;
ea8b2282 2295 if (pi1->peer != bgp->peer_self)
40381db7 2296 if (pi1->peer->status != Established)
d62a17ae 2297 continue;
2298
40381db7
DS
2299 new_select = pi1;
2300 if (pi1->next) {
2301 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2302 if (CHECK_FLAG(pi2->flags,
1defdda8 2303 BGP_PATH_DMED_CHECK))
d62a17ae 2304 continue;
40381db7 2305 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2306 continue;
ea8b2282 2307 if (pi2->peer != bgp->peer_self
d62a17ae 2308 && !CHECK_FLAG(
ea8b2282
DS
2309 pi2->peer->sflags,
2310 PEER_STATUS_NSF_WAIT))
40381db7 2311 if (pi2->peer->status
d62a17ae 2312 != Established)
2313 continue;
2314
121e245d
DS
2315 if (!aspath_cmp_left(pi1->attr->aspath,
2316 pi2->attr->aspath)
2317 && !aspath_cmp_left_confed(
40381db7 2318 pi1->attr->aspath,
121e245d
DS
2319 pi2->attr->aspath))
2320 continue;
d62a17ae 2321
121e245d
DS
2322 if (bgp_path_info_cmp(
2323 bgp, pi2, new_select,
2324 &paths_eq, mpath_cfg, debug,
fdf81fa0 2325 pfx_buf, afi, safi,
9bcb3eef 2326 &dest->reason)) {
121e245d 2327 bgp_path_info_unset_flag(
9bcb3eef 2328 dest, new_select,
121e245d
DS
2329 BGP_PATH_DMED_SELECTED);
2330 new_select = pi2;
d62a17ae 2331 }
121e245d
DS
2332
2333 bgp_path_info_set_flag(
9bcb3eef 2334 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2335 }
2336 }
9bcb3eef 2337 bgp_path_info_set_flag(dest, new_select,
18ee8310 2338 BGP_PATH_DMED_CHECK);
9bcb3eef 2339 bgp_path_info_set_flag(dest, new_select,
18ee8310 2340 BGP_PATH_DMED_SELECTED);
d62a17ae 2341
2342 if (debug) {
18ee8310
DS
2343 bgp_path_info_path_with_addpath_rx_str(
2344 new_select, path_buf);
8228a9a7
DS
2345 zlog_debug(
2346 "%pBD: %s is the bestpath from AS %u",
2347 dest, path_buf,
2348 aspath_get_first_as(
2349 new_select->attr->aspath));
d62a17ae 2350 }
2351 }
2352 }
96450faf 2353
d62a17ae 2354 /* Check old selected route and new selected route. */
2355 old_select = NULL;
2356 new_select = NULL;
9bcb3eef 2357 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2358 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2359 enum bgp_path_selection_reason reason;
2360
40381db7
DS
2361 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2362 old_select = pi;
d62a17ae 2363
40381db7 2364 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2365 /* reap REMOVED routes, if needs be
2366 * selected route must stay for a while longer though
2367 */
40381db7
DS
2368 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2369 && (pi != old_select))
9bcb3eef 2370 bgp_path_info_reap(dest, pi);
d62a17ae 2371
ddb5b488 2372 if (debug)
40381db7
DS
2373 zlog_debug("%s: pi %p in holddown", __func__,
2374 pi);
ddb5b488 2375
d62a17ae 2376 continue;
2377 }
96450faf 2378
40381db7
DS
2379 if (pi->peer && pi->peer != bgp->peer_self
2380 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2381 if (pi->peer->status != Established) {
ddb5b488
PZ
2382
2383 if (debug)
2384 zlog_debug(
40381db7
DS
2385 "%s: pi %p non self peer %s not estab state",
2386 __func__, pi, pi->peer->host);
ddb5b488 2387
d62a17ae 2388 continue;
ddb5b488 2389 }
9fbdd100 2390
892fedb6 2391 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2392 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2393 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2394 if (debug)
40381db7 2395 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2396 continue;
2397 }
9fbdd100 2398
9bcb3eef 2399 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2400
9bcb3eef 2401 reason = dest->reason;
40381db7 2402 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2403 debug, pfx_buf, afi, safi,
2404 &dest->reason)) {
19ea4cec
DS
2405 if (new_select == NULL &&
2406 reason != bgp_path_selection_none)
9bcb3eef 2407 dest->reason = reason;
40381db7 2408 new_select = pi;
d62a17ae 2409 }
2410 }
718e3744 2411
d62a17ae 2412 /* Now that we know which path is the bestpath see if any of the other
2413 * paths
2414 * qualify as multipaths
2415 */
2416 if (debug) {
2417 if (new_select)
18ee8310
DS
2418 bgp_path_info_path_with_addpath_rx_str(new_select,
2419 path_buf);
d62a17ae 2420 else
772270f3 2421 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2422 zlog_debug(
8228a9a7
DS
2423 "%pBD: After path selection, newbest is %s oldbest was %s",
2424 dest, path_buf,
d62a17ae 2425 old_select ? old_select->peer->host : "NONE");
96450faf 2426 }
9fbdd100 2427
d62a17ae 2428 if (do_mpath && new_select) {
9bcb3eef 2429 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2430 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2431
2432 if (debug)
18ee8310 2433 bgp_path_info_path_with_addpath_rx_str(
40381db7 2434 pi, path_buf);
d62a17ae 2435
40381db7 2436 if (pi == new_select) {
d62a17ae 2437 if (debug)
2438 zlog_debug(
8228a9a7
DS
2439 "%pBD: %s is the bestpath, add to the multipath list",
2440 dest, path_buf);
40381db7 2441 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2442 continue;
2443 }
2444
40381db7 2445 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2446 continue;
2447
40381db7
DS
2448 if (pi->peer && pi->peer != bgp->peer_self
2449 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2450 PEER_STATUS_NSF_WAIT))
40381db7 2451 if (pi->peer->status != Established)
d62a17ae 2452 continue;
2453
40381db7 2454 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2455 if (debug)
2456 zlog_debug(
8228a9a7
DS
2457 "%pBD: %s has the same nexthop as the bestpath, skip it",
2458 dest, path_buf);
d62a17ae 2459 continue;
2460 }
2461
40381db7 2462 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2463 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2464 &dest->reason);
d62a17ae 2465
2466 if (paths_eq) {
2467 if (debug)
2468 zlog_debug(
8228a9a7
DS
2469 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2470 dest, path_buf);
40381db7 2471 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2472 }
2473 }
2474 }
fee0f4c6 2475
9bcb3eef 2476 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2477 mpath_cfg);
2478 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2479 bgp_mp_list_clear(&mp_list);
96450faf 2480
9bcb3eef 2481 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2482
d62a17ae 2483 result->old = old_select;
2484 result->new = new_select;
96450faf 2485
d62a17ae 2486 return;
fee0f4c6 2487}
2488
3f9c7369
DS
2489/*
2490 * A new route/change in bestpath of an existing route. Evaluate the path
2491 * for advertisement to the subgroup.
2492 */
3dc339cd
DA
2493void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2494 struct bgp_path_info *selected,
9bcb3eef 2495 struct bgp_dest *dest,
3dc339cd 2496 uint32_t addpath_tx_id)
d62a17ae 2497{
b54892e0 2498 const struct prefix *p;
d62a17ae 2499 struct peer *onlypeer;
2500 struct attr attr;
2501 afi_t afi;
2502 safi_t safi;
a77e2f4b
S
2503 struct bgp *bgp;
2504 bool advertise;
adbac85e 2505
9bcb3eef 2506 p = bgp_dest_get_prefix(dest);
d62a17ae 2507 afi = SUBGRP_AFI(subgrp);
2508 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2509 bgp = SUBGRP_INST(subgrp);
d62a17ae 2510 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2511 : NULL);
2512
2dbe669b
DA
2513 if (BGP_DEBUG(update, UPDATE_OUT))
2514 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2515
d62a17ae 2516 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2517 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2518 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2519 return;
d62a17ae 2520
2521 memset(&attr, 0, sizeof(struct attr));
2522 /* It's initialized in bgp_announce_check() */
2523
a77e2f4b
S
2524 /* Announcement to the subgroup. If the route is filtered withdraw it.
2525 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2526 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2527 * route
d62a17ae 2528 */
a77e2f4b
S
2529 advertise = bgp_check_advertise(bgp, dest);
2530
d62a17ae 2531 if (selected) {
7f7940e6 2532 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2533 false)) {
2534 /* Route is selected, if the route is already installed
2535 * in FIB, then it is advertised
2536 */
2537 if (advertise)
2538 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2539 selected);
2540 } else
9bcb3eef 2541 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2542 addpath_tx_id);
d62a17ae 2543 }
2544
2545 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2546 else {
9bcb3eef 2547 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2548 }
200df115 2549}
fee0f4c6 2550
3064bf43 2551/*
e1072051 2552 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2553 * This is called at the end of route processing.
3064bf43 2554 */
9bcb3eef 2555void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2556{
40381db7 2557 struct bgp_path_info *pi;
3064bf43 2558
9bcb3eef 2559 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2560 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2561 continue;
40381db7
DS
2562 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2563 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2564 }
3064bf43 2565}
2566
2567/*
2568 * Has the route changed from the RIB's perspective? This is invoked only
2569 * if the route selection returns the same best route as earlier - to
2570 * determine if we need to update zebra or not.
2571 */
9bcb3eef 2572bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2573{
4b7e6066 2574 struct bgp_path_info *mpinfo;
d62a17ae 2575
2bb9eff4
DS
2576 /* If this is multipath, check all selected paths for any nexthop
2577 * change or attribute change. Some attribute changes (e.g., community)
2578 * aren't of relevance to the RIB, but we'll update zebra to ensure
2579 * we handle the case of BGP nexthop change. This is the behavior
2580 * when the best path has an attribute change anyway.
d62a17ae 2581 */
1defdda8 2582 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2583 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2584 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2585 return true;
d62a17ae 2586
2bb9eff4
DS
2587 /*
2588 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2589 */
18ee8310
DS
2590 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2591 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2592 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2593 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2594 return true;
d62a17ae 2595 }
3064bf43 2596
d62a17ae 2597 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2598 return false;
3064bf43 2599}
2600
d62a17ae 2601struct bgp_process_queue {
2602 struct bgp *bgp;
9bcb3eef 2603 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2604#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2605 unsigned int flags;
2606 unsigned int queued;
200df115 2607};
2608
3b0c17e1 2609static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2610 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2611 struct bgp_path_info *new_select,
2612 struct bgp_path_info *old_select)
2613{
9bcb3eef 2614 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2615
2616 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2617 return;
2618
2619 if (advertise_type5_routes(bgp, afi) && new_select
2620 && is_route_injectable_into_evpn(new_select)) {
2621
2622 /* apply the route-map */
2623 if (bgp->adv_cmd_rmap[afi][safi].map) {
2624 route_map_result_t ret;
2625 struct bgp_path_info rmap_path;
2626 struct bgp_path_info_extra rmap_path_extra;
2627 struct attr dummy_attr;
2628
2629 dummy_attr = *new_select->attr;
2630
2631 /* Fill temp path_info */
9bcb3eef 2632 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2633 new_select, new_select->peer,
2634 &dummy_attr);
2635
2636 RESET_FLAG(dummy_attr.rmap_change_flags);
2637
2638 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2639 p, &rmap_path);
3b0c17e1 2640
2641 if (ret == RMAP_DENYMATCH) {
2642 bgp_attr_flush(&dummy_attr);
2643 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2644 safi);
2645 } else
2646 bgp_evpn_advertise_type5_route(
2647 bgp, p, &dummy_attr, afi, safi);
2648 } else {
2649 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2650 afi, safi);
2651 }
2652 } else if (advertise_type5_routes(bgp, afi) && old_select
2653 && is_route_injectable_into_evpn(old_select))
2654 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2655}
2656
3103e8d2
DS
2657/*
2658 * old_select = The old best path
2659 * new_select = the new best path
2660 *
2661 * if (!old_select && new_select)
2662 * We are sending new information on.
2663 *
2664 * if (old_select && new_select) {
2665 * if (new_select != old_select)
2666 * We have a new best path send a change
2667 * else
2668 * We've received a update with new attributes that needs
2669 * to be passed on.
2670 * }
2671 *
2672 * if (old_select && !new_select)
2673 * We have no eligible route that we can announce or the rn
2674 * is being removed.
2675 */
9bcb3eef 2676static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2677 afi_t afi, safi_t safi)
d62a17ae 2678{
4b7e6066
DS
2679 struct bgp_path_info *new_select;
2680 struct bgp_path_info *old_select;
2681 struct bgp_path_info_pair old_and_new;
ddb5b488 2682 int debug = 0;
d62a17ae 2683
892fedb6 2684 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2685 if (dest)
2686 debug = bgp_debug_bestpath(dest);
b54892e0 2687 if (debug)
f4c713ae 2688 zlog_debug(
56ca3b5b 2689 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2690 __func__, dest);
f4c713ae
LB
2691 return;
2692 }
d62a17ae 2693 /* Is it end of initial update? (after startup) */
9bcb3eef 2694 if (!dest) {
d62a17ae 2695 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2696 sizeof(bgp->update_delay_zebra_resume_time));
2697
2698 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2699 FOREACH_AFI_SAFI (afi, safi) {
2700 if (bgp_fibupd_safi(safi))
2701 bgp_zebra_announce_table(bgp, afi, safi);
2702 }
d62a17ae 2703 bgp->main_peers_update_hold = 0;
2704
2705 bgp_start_routeadv(bgp);
aac24838 2706 return;
d62a17ae 2707 }
cb1faec9 2708
9bcb3eef 2709 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2710
9bcb3eef 2711 debug = bgp_debug_bestpath(dest);
b54892e0 2712 if (debug)
56ca3b5b 2713 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2714 afi2str(afi), safi2str(safi));
ddb5b488 2715
f009ff26 2716 /* The best path calculation for the route is deferred if
2717 * BGP_NODE_SELECT_DEFER is set
2718 */
9bcb3eef 2719 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2720 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2721 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2722 return;
2723 }
2724
d62a17ae 2725 /* Best path selection. */
9bcb3eef 2726 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2727 afi, safi);
2728 old_select = old_and_new.old;
2729 new_select = old_and_new.new;
2730
2731 /* Do we need to allocate or free labels?
2732 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2733 * necessary to do this upon changes to best path. Exceptions:
2734 * - label index has changed -> recalculate resulting label
2735 * - path_info sub_type changed -> switch to/from implicit-null
2736 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2737 */
318cac96 2738 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2739 if (new_select) {
2740 if (!old_select
2741 || bgp_label_index_differs(new_select, old_select)
57592a53 2742 || new_select->sub_type != old_select->sub_type
9bcb3eef 2743 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2744 /* Enforced penultimate hop popping:
2745 * implicit-null for local routes, aggregate
2746 * and redistributed routes
2747 */
d62a17ae 2748 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2749 || new_select->sub_type
2750 == BGP_ROUTE_AGGREGATE
2751 || new_select->sub_type
2752 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2753 if (CHECK_FLAG(
9bcb3eef 2754 dest->flags,
992dd67e
PR
2755 BGP_NODE_REGISTERED_FOR_LABEL)
2756 || CHECK_FLAG(
2757 dest->flags,
2758 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2759 bgp_unregister_for_label(dest);
70e98a7f 2760 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2761 &dest->local_label);
2762 bgp_set_valid_label(&dest->local_label);
d62a17ae 2763 } else
9bcb3eef
DS
2764 bgp_register_for_label(dest,
2765 new_select);
d62a17ae 2766 }
9bcb3eef 2767 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2768 BGP_NODE_REGISTERED_FOR_LABEL)
2769 || CHECK_FLAG(dest->flags,
2770 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2771 bgp_unregister_for_label(dest);
318cac96 2772 }
992dd67e
PR
2773 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2774 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2775 bgp_unregister_for_label(dest);
d62a17ae 2776 }
cd1964ff 2777
b54892e0 2778 if (debug)
ddb5b488 2779 zlog_debug(
56ca3b5b 2780 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2781 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2782 old_select, new_select);
ddb5b488 2783
d62a17ae 2784 /* If best route remains the same and this is not due to user-initiated
2785 * clear, see exactly what needs to be done.
2786 */
d62a17ae 2787 if (old_select && old_select == new_select
9bcb3eef 2788 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2789 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2790 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2791 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2792#ifdef ENABLE_BGP_VNC
d62a17ae 2793 vnc_import_bgp_add_route(bgp, p, old_select);
2794 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2795#endif
bb744275 2796 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2797 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2798
2799 if (new_select->type == ZEBRA_ROUTE_BGP
2800 && (new_select->sub_type == BGP_ROUTE_NORMAL
2801 || new_select->sub_type
2802 == BGP_ROUTE_IMPORTED))
2803
9bcb3eef 2804 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2805 bgp, afi, safi);
2806 }
d62a17ae 2807 }
d62a17ae 2808
2809 /* If there is a change of interest to peers, reannounce the
2810 * route. */
1defdda8 2811 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2812 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2813 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2814 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2815
2816 /* unicast routes must also be annouced to
2817 * labeled-unicast update-groups */
2818 if (safi == SAFI_UNICAST)
2819 group_announce_route(bgp, afi,
9bcb3eef 2820 SAFI_LABELED_UNICAST, dest,
d62a17ae 2821 new_select);
2822
1defdda8 2823 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2824 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2825 }
fee0f4c6 2826
3b0c17e1 2827 /* advertise/withdraw type-5 routes */
2828 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2829 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2830 bgp_process_evpn_route_injection(
9bcb3eef 2831 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2832
b1875e65 2833 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2834 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2835 bgp_zebra_clear_route_change_flags(dest);
2836 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2837 return;
d62a17ae 2838 }
8ad7271d 2839
d62a17ae 2840 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2841 */
9bcb3eef 2842 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2843
2844 /* bestpath has changed; bump version */
2845 if (old_select || new_select) {
9bcb3eef 2846 bgp_bump_version(dest);
d62a17ae 2847
2848 if (!bgp->t_rmap_def_originate_eval) {
2849 bgp_lock(bgp);
2850 thread_add_timer(
2851 bm->master,
2852 update_group_refresh_default_originate_route_map,
2853 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2854 &bgp->t_rmap_def_originate_eval);
2855 }
2856 }
3f9c7369 2857
d62a17ae 2858 if (old_select)
9bcb3eef 2859 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2860 if (new_select) {
ddb5b488
PZ
2861 if (debug)
2862 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2863 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2864 bgp_path_info_unset_flag(dest, new_select,
2865 BGP_PATH_ATTR_CHANGED);
1defdda8 2866 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2867 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2868 }
338b3424 2869
49e5a4a0 2870#ifdef ENABLE_BGP_VNC
d62a17ae 2871 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2872 if (old_select != new_select) {
2873 if (old_select) {
2874 vnc_import_bgp_exterior_del_route(bgp, p,
2875 old_select);
2876 vnc_import_bgp_del_route(bgp, p, old_select);
2877 }
2878 if (new_select) {
2879 vnc_import_bgp_exterior_add_route(bgp, p,
2880 new_select);
2881 vnc_import_bgp_add_route(bgp, p, new_select);
2882 }
2883 }
2884 }
65efcfce
LB
2885#endif
2886
9bcb3eef 2887 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2888
2889 /* unicast routes must also be annouced to labeled-unicast update-groups
2890 */
2891 if (safi == SAFI_UNICAST)
9bcb3eef 2892 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2893 new_select);
2894
2895 /* FIB update. */
2896 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2897 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2898 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2899 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2900 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2901 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2902
2903 /* if this is an evpn imported type-5 prefix,
2904 * we need to withdraw the route first to clear
2905 * the nh neigh and the RMAC entry.
2906 */
2907 if (old_select &&
2908 is_route_parent_evpn(old_select))
2909 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2910
9bcb3eef 2911 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2912 } else {
d62a17ae 2913 /* Withdraw the route from the kernel. */
2914 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2915 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2916 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2917 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2918
568e10ca 2919 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2920 }
718e3744 2921 }
3064bf43 2922
9bcb3eef 2923 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2924 old_select);
5424b7ba 2925
d62a17ae 2926 /* Clear any route change flags. */
9bcb3eef 2927 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2928
18ee8310 2929 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2930 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2931 bgp_path_info_reap(dest, old_select);
d62a17ae 2932
9bcb3eef 2933 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2934 return;
718e3744 2935}
2936
f009ff26 2937/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2938int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2939{
9bcb3eef 2940 struct bgp_dest *dest;
f009ff26 2941 int cnt = 0;
2942 struct afi_safi_info *thread_info;
f009ff26 2943
56c226e7
DS
2944 if (bgp->gr_info[afi][safi].t_route_select) {
2945 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2946
2947 thread_info = THREAD_ARG(t);
2948 XFREE(MTYPE_TMP, thread_info);
f009ff26 2949 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2950 }
f009ff26 2951
2952 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2953 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2954 get_afi_safi_str(afi, safi, false),
26742171 2955 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2956 }
2957
2958 /* Process the route list */
6338d242
DS
2959 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2960 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2961 dest = bgp_route_next(dest)) {
2962 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2963 continue;
2964
2965 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2966 bgp->gr_info[afi][safi].gr_deferred--;
2967 bgp_process_main_one(bgp, dest, afi, safi);
2968 cnt++;
2969 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2970 bgp_dest_unlock_node(dest);
2971 break;
f009ff26 2972 }
f009ff26 2973 }
2974
9e3b51a7 2975 /* Send EOR message when all routes are processed */
6338d242 2976 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2977 bgp_send_delayed_eor(bgp);
8c48b3b6 2978 /* Send route processing complete message to RIB */
2979 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2980 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2981 return 0;
9e3b51a7 2982 }
f009ff26 2983
2984 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2985
2986 thread_info->afi = afi;
2987 thread_info->safi = safi;
2988 thread_info->bgp = bgp;
2989
2990 /* If there are more routes to be processed, start the
2991 * selection timer
2992 */
2993 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2994 BGP_ROUTE_SELECT_DELAY,
2995 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2996 return 0;
2997}
2998
aac24838 2999static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3000{
aac24838
JB
3001 struct bgp_process_queue *pqnode = data;
3002 struct bgp *bgp = pqnode->bgp;
d62a17ae 3003 struct bgp_table *table;
9bcb3eef 3004 struct bgp_dest *dest;
aac24838
JB
3005
3006 /* eoiu marker */
3007 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3008 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3009 /* should always have dedicated wq call */
3010 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3011 return WQ_SUCCESS;
3012 }
3013
ac021f40 3014 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3015 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3016 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3017 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3018 table = bgp_dest_table(dest);
3019 /* note, new DESTs may be added as part of processing */
3020 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3021
9bcb3eef 3022 bgp_dest_unlock_node(dest);
d62a17ae 3023 bgp_table_unlock(table);
3024 }
aac24838
JB
3025
3026 return WQ_SUCCESS;
3027}
3028
3029static void bgp_processq_del(struct work_queue *wq, void *data)
3030{
3031 struct bgp_process_queue *pqnode = data;
3032
3033 bgp_unlock(pqnode->bgp);
3034
3035 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3036}
3037
b6c386bb 3038void bgp_process_queue_init(struct bgp *bgp)
200df115 3039{
b6c386bb
DS
3040 if (!bgp->process_queue) {
3041 char name[BUFSIZ];
3042
3043 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3044 bgp->process_queue = work_queue_new(bm->master, name);
3045 }
3046
3047 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3048 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3049 bgp->process_queue->spec.max_retries = 0;
3050 bgp->process_queue->spec.hold = 50;
d62a17ae 3051 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3052 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3053}
3054
cfe8d15a 3055static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3056{
3057 struct bgp_process_queue *pqnode;
3058
a4d82a8a
PZ
3059 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3060 sizeof(struct bgp_process_queue));
aac24838
JB
3061
3062 /* unlocked in bgp_processq_del */
3063 pqnode->bgp = bgp_lock(bgp);
3064 STAILQ_INIT(&pqnode->pqueue);
3065
aac24838
JB
3066 return pqnode;
3067}
3068
9bcb3eef 3069void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3070{
aac24838 3071#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3072 struct work_queue *wq = bgp->process_queue;
d62a17ae 3073 struct bgp_process_queue *pqnode;
cfe8d15a 3074 int pqnode_reuse = 0;
495f0b13 3075
d62a17ae 3076 /* already scheduled for processing? */
9bcb3eef 3077 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3078 return;
2e02b9b2 3079
f009ff26 3080 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3081 * the workqueue
3082 */
9bcb3eef 3083 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3084 if (BGP_DEBUG(update, UPDATE_OUT))
3085 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3086 dest);
f009ff26 3087 return;
3088 }
3089
aac24838 3090 if (wq == NULL)
d62a17ae 3091 return;
3092
aac24838 3093 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3094 limit only if is from the same BGP view and it's not an EOIU marker
3095 */
aac24838
JB
3096 if (work_queue_item_count(wq)) {
3097 struct work_queue_item *item = work_queue_last_item(wq);
3098 pqnode = item->data;
228da428 3099
a4d82a8a
PZ
3100 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3101 || pqnode->bgp != bgp
3102 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3103 pqnode = bgp_processq_alloc(bgp);
3104 else
3105 pqnode_reuse = 1;
aac24838 3106 } else
cfe8d15a 3107 pqnode = bgp_processq_alloc(bgp);
aac24838 3108 /* all unlocked in bgp_process_wq */
9bcb3eef 3109 bgp_table_lock(bgp_dest_table(dest));
aac24838 3110
9bcb3eef
DS
3111 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3112 bgp_dest_lock_node(dest);
aac24838 3113
60466a63 3114 /* can't be enqueued twice */
9bcb3eef
DS
3115 assert(STAILQ_NEXT(dest, pq) == NULL);
3116 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3117 pqnode->queued++;
3118
cfe8d15a
LB
3119 if (!pqnode_reuse)
3120 work_queue_add(wq, pqnode);
3121
d62a17ae 3122 return;
fee0f4c6 3123}
0a486e5f 3124
d62a17ae 3125void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3126{
d62a17ae 3127 struct bgp_process_queue *pqnode;
cb1faec9 3128
b6c386bb 3129 if (bgp->process_queue == NULL)
d62a17ae 3130 return;
2e02b9b2 3131
cfe8d15a 3132 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3133
aac24838 3134 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3135 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3136}
3137
d62a17ae 3138static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3139{
d62a17ae 3140 struct peer *peer;
0a486e5f 3141
d62a17ae 3142 peer = THREAD_ARG(thread);
3143 peer->t_pmax_restart = NULL;
0a486e5f 3144
d62a17ae 3145 if (bgp_debug_neighbor_events(peer))
3146 zlog_debug(
3147 "%s Maximum-prefix restart timer expired, restore peering",
3148 peer->host);
0a486e5f 3149
a9bafa95 3150 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3151 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3152
d62a17ae 3153 return 0;
0a486e5f 3154}
3155
9cbd06e0
DA
3156static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3157 safi_t safi)
3158{
3159 uint32_t count = 0;
f41b0459 3160 bool filtered = false;
9cbd06e0
DA
3161 struct bgp_dest *dest;
3162 struct bgp_adj_in *ain;
40bb2ccf 3163 struct attr attr = {};
9cbd06e0
DA
3164 struct bgp_table *table = peer->bgp->rib[afi][safi];
3165
3166 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3167 for (ain = dest->adj_in; ain; ain = ain->next) {
3168 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3169
3170 attr = *ain->attr;
9cbd06e0
DA
3171
3172 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3173 == FILTER_DENY)
f41b0459
DA
3174 filtered = true;
3175
3176 if (bgp_input_modifier(
3177 peer, rn_p, &attr, afi, safi,
3178 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3179 NULL, 0, NULL)
3180 == RMAP_DENY)
3181 filtered = true;
3182
3183 if (filtered)
9cbd06e0 3184 count++;
f41b0459
DA
3185
3186 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3187 }
3188 }
3189
3190 return count;
3191}
3192
3dc339cd
DA
3193bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3194 int always)
718e3744 3195{
d62a17ae 3196 iana_afi_t pkt_afi;
5c525538 3197 iana_safi_t pkt_safi;
9cbd06e0
DA
3198 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3199 PEER_FLAG_MAX_PREFIX_FORCE))
3200 ? bgp_filtered_routes_count(peer, afi, safi)
3201 + peer->pcount[afi][safi]
3202 : peer->pcount[afi][safi];
9cabb64b 3203
d62a17ae 3204 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3205 return false;
e0701b79 3206
9cbd06e0 3207 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3208 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3209 PEER_STATUS_PREFIX_LIMIT)
3210 && !always)
3dc339cd 3211 return false;
e0701b79 3212
d62a17ae 3213 zlog_info(
6cde4b45 3214 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3215 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3216 peer->pmax[afi][safi]);
d62a17ae 3217 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3218
3219 if (CHECK_FLAG(peer->af_flags[afi][safi],
3220 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3221 return false;
d62a17ae 3222
3223 /* Convert AFI, SAFI to values for packet. */
3224 pkt_afi = afi_int2iana(afi);
3225 pkt_safi = safi_int2iana(safi);
3226 {
d7c0a89a 3227 uint8_t ndata[7];
d62a17ae 3228
3229 ndata[0] = (pkt_afi >> 8);
3230 ndata[1] = pkt_afi;
3231 ndata[2] = pkt_safi;
3232 ndata[3] = (peer->pmax[afi][safi] >> 24);
3233 ndata[4] = (peer->pmax[afi][safi] >> 16);
3234 ndata[5] = (peer->pmax[afi][safi] >> 8);
3235 ndata[6] = (peer->pmax[afi][safi]);
3236
3237 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3238 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3239 BGP_NOTIFY_CEASE_MAX_PREFIX,
3240 ndata, 7);
3241 }
3242
3243 /* Dynamic peers will just close their connection. */
3244 if (peer_dynamic_neighbor(peer))
3dc339cd 3245 return true;
d62a17ae 3246
3247 /* restart timer start */
3248 if (peer->pmax_restart[afi][safi]) {
3249 peer->v_pmax_restart =
3250 peer->pmax_restart[afi][safi] * 60;
3251
3252 if (bgp_debug_neighbor_events(peer))
3253 zlog_debug(
3254 "%s Maximum-prefix restart timer started for %d secs",
3255 peer->host, peer->v_pmax_restart);
3256
3257 BGP_TIMER_ON(peer->t_pmax_restart,
3258 bgp_maximum_prefix_restart_timer,
3259 peer->v_pmax_restart);
3260 }
3261
3dc339cd 3262 return true;
d62a17ae 3263 } else
3264 UNSET_FLAG(peer->af_sflags[afi][safi],
3265 PEER_STATUS_PREFIX_LIMIT);
3266
b1823b69
DS
3267 if (pcount
3268 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3269 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3270 PEER_STATUS_PREFIX_THRESHOLD)
3271 && !always)
3dc339cd 3272 return false;
d62a17ae 3273
3274 zlog_info(
6cde4b45 3275 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3276 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3277 peer->pmax[afi][safi]);
d62a17ae 3278 SET_FLAG(peer->af_sflags[afi][safi],
3279 PEER_STATUS_PREFIX_THRESHOLD);
3280 } else
3281 UNSET_FLAG(peer->af_sflags[afi][safi],
3282 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3283 return false;
718e3744 3284}
3285
b40d939b 3286/* Unconditionally remove the route from the RIB, without taking
3287 * damping into consideration (eg, because the session went down)
3288 */
9bcb3eef 3289void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3290 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3291{
f009ff26 3292
3293 struct bgp *bgp = NULL;
3294 bool delete_route = false;
3295
9bcb3eef
DS
3296 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3297 safi);
d62a17ae 3298
f009ff26 3299 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3300 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3301
f009ff26 3302 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3303 * flag
3304 */
3305 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3306 delete_route = true;
9bcb3eef 3307 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3308 delete_route = true;
f009ff26 3309 if (delete_route) {
9bcb3eef
DS
3310 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3311 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3312 bgp = pi->peer->bgp;
26742171 3313 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3314 }
3315 }
3316 }
4a11bf2c 3317
9bcb3eef
DS
3318 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3319 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3320}
3321
9bcb3eef 3322static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3323 struct peer *peer, afi_t afi, safi_t safi,
3324 struct prefix_rd *prd)
3325{
9bcb3eef 3326 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3327
d62a17ae 3328 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3329 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3330 */
40ec3340
DS
3331 if (peer->sort == BGP_PEER_EBGP) {
3332 if (get_active_bdc_from_pi(pi, afi, safi)) {
3333 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3334 == BGP_DAMP_SUPPRESSED) {
3335 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3336 safi);
3337 return;
3338 }
d62a17ae 3339 }
40ec3340 3340 }
d62a17ae 3341
49e5a4a0 3342#ifdef ENABLE_BGP_VNC
d62a17ae 3343 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3344 struct bgp_dest *pdest = NULL;
d62a17ae 3345 struct bgp_table *table = NULL;
3346
9bcb3eef
DS
3347 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3348 (struct prefix *)prd);
3349 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3350 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3351
3352 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3353 peer->bgp, prd, table, p, pi);
d62a17ae 3354 }
9bcb3eef 3355 bgp_dest_unlock_node(pdest);
d62a17ae 3356 }
3357 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3358 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3359
b54892e0
DS
3360 vnc_import_bgp_del_route(peer->bgp, p, pi);
3361 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3362 }
65efcfce 3363 }
d62a17ae 3364#endif
128ea8ab 3365
d62a17ae 3366 /* If this is an EVPN route, process for un-import. */
3367 if (safi == SAFI_EVPN)
b54892e0 3368 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3369
9bcb3eef 3370 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3371}
3372
4b7e6066
DS
3373struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3374 struct peer *peer, struct attr *attr,
9bcb3eef 3375 struct bgp_dest *dest)
fb018d25 3376{
4b7e6066 3377 struct bgp_path_info *new;
fb018d25 3378
d62a17ae 3379 /* Make new BGP info. */
4b7e6066 3380 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3381 new->type = type;
3382 new->instance = instance;
3383 new->sub_type = sub_type;
3384 new->peer = peer;
3385 new->attr = attr;
3386 new->uptime = bgp_clock();
9bcb3eef 3387 new->net = dest;
d62a17ae 3388 return new;
fb018d25
DS
3389}
3390
d62a17ae 3391static void overlay_index_update(struct attr *attr,
d62a17ae 3392 union gw_addr *gw_ip)
684a7227 3393{
d62a17ae 3394 if (!attr)
3395 return;
d62a17ae 3396 if (gw_ip == NULL) {
6c924775
DS
3397 struct bgp_route_evpn eo;
3398
3399 memset(&eo, 0, sizeof(eo));
3400 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3401 } else {
6c924775
DS
3402 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3403
3404 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3405 }
684a7227
PG
3406}
3407
40381db7 3408static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3409 union gw_addr *gw_ip)
3410{
6c924775
DS
3411 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3412 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3413 union {
0a50c248 3414 esi_t esi;
11ebf4ed
DS
3415 union gw_addr ip;
3416 } temp;
d62a17ae 3417
3418 if (afi != AFI_L2VPN)
3419 return true;
11ebf4ed 3420
6c924775 3421 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3422
3423 if (gw_ip == NULL) {
3424 memset(&temp, 0, sizeof(temp));
40381db7 3425 path_gw_ip_remote = &temp.ip;
11ebf4ed 3426 } else
40381db7 3427 path_gw_ip_remote = gw_ip;
11ebf4ed 3428
6c924775 3429 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3430}
3431
c265ee22 3432/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3433bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3434 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3435 struct bgp_dest *dest)
d62a17ae 3436{
2dbe3fa9 3437 bool ret = false;
b099a5c8
DA
3438 bool is_bgp_static_route =
3439 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3440 : false;
d62a17ae 3441
e8442016
DS
3442 /*
3443 * Only validated for unicast and multicast currently.
3444 * Also valid for EVPN where the nexthop is an IP address.
3445 * If we are a bgp static route being checked then there is
3446 * no need to check to see if the nexthop is martian as
3447 * that it should be ok.
3448 */
3449 if (is_bgp_static_route ||
3450 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3451 return false;
d62a17ae 3452
3453 /* If NEXT_HOP is present, validate it. */
3454 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3455 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3456 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3457 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3458 return true;
d62a17ae 3459 }
c265ee22 3460
d62a17ae 3461 /* If MP_NEXTHOP is present, validate it. */
3462 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3463 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3464 * it is not an IPv6 link-local address.
0355b41d
DA
3465 *
3466 * If we receive an UPDATE with nexthop length set to 32 bytes
3467 * we shouldn't discard an UPDATE if it's set to (::).
3468 * The link-local (2st) is validated along the code path later.
d62a17ae 3469 */
3470 if (attr->mp_nexthop_len) {
3471 switch (attr->mp_nexthop_len) {
3472 case BGP_ATTR_NHLEN_IPV4:
3473 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3474 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3475 || IPV4_CLASS_DE(
3476 ntohl(attr->mp_nexthop_global_in.s_addr))
3477 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3478 dest));
d62a17ae 3479 break;
3480
3481 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3482 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3483 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3484 &attr->mp_nexthop_global)
d62a17ae 3485 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3486 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3487 &attr->mp_nexthop_global)
3488 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3489 dest));
d62a17ae 3490 break;
0355b41d
DA
3491 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3492 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3493 || IN6_IS_ADDR_MULTICAST(
3494 &attr->mp_nexthop_global)
3495 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3496 dest));
0355b41d 3497 break;
d62a17ae 3498
3499 default:
3dc339cd 3500 ret = true;
d62a17ae 3501 break;
3502 }
3503 }
c265ee22 3504
d62a17ae 3505 return ret;
3506}
3507
5a1ae2c2 3508int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3509 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3510 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3511 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3512 struct bgp_route_evpn *evpn)
d62a17ae 3513{
3514 int ret;
3515 int aspath_loop_count = 0;
9bcb3eef 3516 struct bgp_dest *dest;
d62a17ae 3517 struct bgp *bgp;
3518 struct attr new_attr;
3519 struct attr *attr_new;
40381db7 3520 struct bgp_path_info *pi;
4b7e6066
DS
3521 struct bgp_path_info *new;
3522 struct bgp_path_info_extra *extra;
d62a17ae 3523 const char *reason;
3524 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3525 int connected = 0;
3526 int do_loop_check = 1;
3527 int has_valid_label = 0;
7c312383 3528 afi_t nh_afi;
949b0f24 3529 uint8_t pi_type = 0;
3530 uint8_t pi_sub_type = 0;
3531
c7bb4f00 3532 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3533 char pfxprint[PREFIX2STR_BUFFER];
3534
3535 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3536 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3537 afi, safi, attr);
6401252f
QY
3538 }
3539
49e5a4a0 3540#ifdef ENABLE_BGP_VNC
d62a17ae 3541 int vnc_implicit_withdraw = 0;
65efcfce 3542#endif
d62a17ae 3543 int same_attr = 0;
718e3744 3544
d62a17ae 3545 memset(&new_attr, 0, sizeof(struct attr));
3546 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3547 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3548
d62a17ae 3549 bgp = peer->bgp;
9bcb3eef 3550 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3551 /* TODO: Check to see if we can get rid of "is_valid_label" */
3552 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3553 has_valid_label = (num_labels > 0) ? 1 : 0;
3554 else
3555 has_valid_label = bgp_is_valid_label(label);
718e3744 3556
28f66de2
MS
3557 if (has_valid_label)
3558 assert(label != NULL);
3559
a77e2f4b
S
3560 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3561 * condition :
3562 * Suppress fib is enabled
3563 * BGP_OPT_NO_FIB is not enabled
3564 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3565 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3566 */
3567 if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
3568 (sub_type == BGP_ROUTE_NORMAL) &&
3569 (!bgp_option_check(BGP_OPT_NO_FIB)) &&
3570 (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3571 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3572
d62a17ae 3573 /* When peer's soft reconfiguration enabled. Record input packet in
3574 Adj-RIBs-In. */
3575 if (!soft_reconfig
3576 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3577 && peer != bgp->peer_self)
9bcb3eef 3578 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3579
3580 /* Check previously received route. */
9bcb3eef 3581 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3582 if (pi->peer == peer && pi->type == type
3583 && pi->sub_type == sub_type
3584 && pi->addpath_rx_id == addpath_id)
d62a17ae 3585 break;
3586
3587 /* AS path local-as loop check. */
3588 if (peer->change_local_as) {
c4368918
DW
3589 if (peer->allowas_in[afi][safi])
3590 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3591 else if (!CHECK_FLAG(peer->flags,
3592 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3593 aspath_loop_count = 1;
3594
3595 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3596 > aspath_loop_count) {
b4d46cc9 3597 peer->stat_pfx_aspath_loop++;
9bcb3eef 3598 reason = "as-path contains our own AS A;";
d62a17ae 3599 goto filtered;
3600 }
718e3744 3601 }
718e3744 3602
d62a17ae 3603 /* If the peer is configured for "allowas-in origin" and the last ASN in
3604 * the
3605 * as-path is our ASN then we do not need to call aspath_loop_check
3606 */
3607 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3608 if (aspath_get_last_as(attr->aspath) == bgp->as)
3609 do_loop_check = 0;
3610
3611 /* AS path loop check. */
3612 if (do_loop_check) {
3613 if (aspath_loop_check(attr->aspath, bgp->as)
3614 > peer->allowas_in[afi][safi]
3615 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3616 && aspath_loop_check(attr->aspath, bgp->confed_id)
3617 > peer->allowas_in[afi][safi])) {
b4d46cc9 3618 peer->stat_pfx_aspath_loop++;
d62a17ae 3619 reason = "as-path contains our own AS;";
3620 goto filtered;
3621 }
3622 }
aac9ef6c 3623
d62a17ae 3624 /* Route reflector originator ID check. */
3625 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3626 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3627 peer->stat_pfx_originator_loop++;
d62a17ae 3628 reason = "originator is us;";
3629 goto filtered;
3630 }
718e3744 3631
d62a17ae 3632 /* Route reflector cluster ID check. */
3633 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3634 peer->stat_pfx_cluster_loop++;
d62a17ae 3635 reason = "reflected from the same cluster;";
3636 goto filtered;
3637 }
718e3744 3638
d62a17ae 3639 /* Apply incoming filter. */
3640 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3641 peer->stat_pfx_filter++;
d62a17ae 3642 reason = "filter;";
3643 goto filtered;
3644 }
718e3744 3645
a8b72dc6
DA
3646 /* RFC 8212 to prevent route leaks.
3647 * This specification intends to improve this situation by requiring the
3648 * explicit configuration of both BGP Import and Export Policies for any
3649 * External BGP (EBGP) session such as customers, peers, or
3650 * confederation boundaries for all enabled address families. Through
3651 * codification of the aforementioned requirement, operators will
3652 * benefit from consistent behavior across different BGP
3653 * implementations.
3654 */
1d3fdccf 3655 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3656 if (!bgp_inbound_policy_exists(peer,
3657 &peer->filter[afi][safi])) {
3658 reason = "inbound policy missing";
3659 goto filtered;
3660 }
3661
fb29348a
DA
3662 /* draft-ietf-idr-deprecate-as-set-confed-set
3663 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3664 * Eventually, This document (if approved) updates RFC 4271
3665 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3666 * and obsoletes RFC 6472.
3667 */
7f972cd8 3668 if (peer->bgp->reject_as_sets)
fb29348a
DA
3669 if (aspath_check_as_sets(attr->aspath)) {
3670 reason =
3671 "as-path contains AS_SET or AS_CONFED_SET type;";
3672 goto filtered;
3673 }
3674
6f4f49b2 3675 new_attr = *attr;
d62a17ae 3676
3677 /* Apply incoming route-map.
3678 * NB: new_attr may now contain newly allocated values from route-map
3679 * "set"
3680 * commands, so we need bgp_attr_flush in the error paths, until we
3681 * intern
3682 * the attr (which takes over the memory references) */
9bcb3eef
DS
3683 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3684 num_labels, dest)
3685 == RMAP_DENY) {
b4d46cc9 3686 peer->stat_pfx_filter++;
d62a17ae 3687 reason = "route-map;";
3688 bgp_attr_flush(&new_attr);
3689 goto filtered;
3690 }
718e3744 3691
05864da7 3692 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3693 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3694 /* remove from RIB previous entry */
3695 bgp_zebra_withdraw(p, pi, bgp, safi);
3696 }
3697
7f323236
DW
3698 if (peer->sort == BGP_PEER_EBGP) {
3699
a4d82a8a
PZ
3700 /* If we receive the graceful-shutdown community from an eBGP
3701 * peer we must lower local-preference */
3702 if (new_attr.community
3703 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3704 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3705 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3706
a4d82a8a
PZ
3707 /* If graceful-shutdown is configured then add the GSHUT
3708 * community to all paths received from eBGP peers */
637e5ba4 3709 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3710 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3711 }
3712
949b0f24 3713 if (pi) {
3714 pi_type = pi->type;
3715 pi_sub_type = pi->sub_type;
3716 }
3717
d62a17ae 3718 /* next hop check. */
a4d82a8a 3719 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3720 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3721 &new_attr, dest)) {
b4d46cc9 3722 peer->stat_pfx_nh_invalid++;
d62a17ae 3723 reason = "martian or self next-hop;";
3724 bgp_attr_flush(&new_attr);
3725 goto filtered;
3726 }
718e3744 3727
5c14a191 3728 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3729 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3730 reason = "self mac;";
3731 goto filtered;
3732 }
3733
1e9be514
QY
3734 /* Update Overlay Index */
3735 if (afi == AFI_L2VPN) {
3736 overlay_index_update(&new_attr,
3737 evpn == NULL ? NULL : &evpn->gw_ip);
3738 }
3739
d62a17ae 3740 attr_new = bgp_attr_intern(&new_attr);
3741
9cbd06e0
DA
3742 /* If maximum prefix count is configured and current prefix
3743 * count exeed it.
3744 */
3745 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3746 return -1;
3747
d62a17ae 3748 /* If the update is implicit withdraw. */
40381db7
DS
3749 if (pi) {
3750 pi->uptime = bgp_clock();
3751 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3752
9bcb3eef 3753 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3754
d62a17ae 3755 /* Same attribute comes in. */
40381db7
DS
3756 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3757 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3758 && (!has_valid_label
40381db7 3759 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3760 num_labels * sizeof(mpls_label_t))
d62a17ae 3761 == 0)
3762 && (overlay_index_equal(
0a50c248 3763 afi, pi,
d62a17ae 3764 evpn == NULL ? NULL : &evpn->gw_ip))) {
40ec3340 3765 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3766 && peer->sort == BGP_PEER_EBGP
40381db7 3767 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3768 if (bgp_debug_update(peer, p, NULL, 1)) {
3769 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3770 afi, safi, prd, p, label,
3771 num_labels, addpath_id ? 1 : 0,
3772 addpath_id, pfx_buf,
3773 sizeof(pfx_buf));
d62a17ae 3774 zlog_debug("%s rcvd %s", peer->host,
3775 pfx_buf);
3776 }
3777
9bcb3eef 3778 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3779 != BGP_DAMP_SUPPRESSED) {
40381db7 3780 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3781 safi);
9bcb3eef 3782 bgp_process(bgp, dest, afi, safi);
d62a17ae 3783 }
3784 } else /* Duplicate - odd */
3785 {
3786 if (bgp_debug_update(peer, p, NULL, 1)) {
3787 if (!peer->rcvd_attr_printed) {
3788 zlog_debug(
3789 "%s rcvd UPDATE w/ attr: %s",
3790 peer->host,
3791 peer->rcvd_attr_str);
3792 peer->rcvd_attr_printed = 1;
3793 }
3794
3795 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3796 afi, safi, prd, p, label,
3797 num_labels, addpath_id ? 1 : 0,
3798 addpath_id, pfx_buf,
3799 sizeof(pfx_buf));
d62a17ae 3800 zlog_debug(
3801 "%s rcvd %s...duplicate ignored",
3802 peer->host, pfx_buf);
3803 }
3804
3805 /* graceful restart STALE flag unset. */
40381db7 3806 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3807 bgp_path_info_unset_flag(
9bcb3eef
DS
3808 dest, pi, BGP_PATH_STALE);
3809 bgp_dest_set_defer_flag(dest, false);
3810 bgp_process(bgp, dest, afi, safi);
d62a17ae 3811 }
3812 }
3813
9bcb3eef 3814 bgp_dest_unlock_node(dest);
d62a17ae 3815 bgp_attr_unintern(&attr_new);
3816
3817 return 0;
3818 }
718e3744 3819
d62a17ae 3820 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3821 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3822 if (bgp_debug_update(peer, p, NULL, 1)) {
3823 bgp_debug_rdpfxpath2str(
a4d82a8a 3824 afi, safi, prd, p, label, num_labels,
d62a17ae 3825 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3826 sizeof(pfx_buf));
3827 zlog_debug(
3828 "%s rcvd %s, flapped quicker than processing",
3829 peer->host, pfx_buf);
3830 }
3831
9bcb3eef 3832 bgp_path_info_restore(dest, pi);
d62a17ae 3833 }
718e3744 3834
d62a17ae 3835 /* Received Logging. */
3836 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3837 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3838 num_labels, addpath_id ? 1 : 0,
3839 addpath_id, pfx_buf,
3840 sizeof(pfx_buf));
d62a17ae 3841 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3842 }
718e3744 3843
d62a17ae 3844 /* graceful restart STALE flag unset. */
f009ff26 3845 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3846 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3847 bgp_dest_set_defer_flag(dest, false);
f009ff26 3848 }
d62a17ae 3849
3850 /* The attribute is changed. */
9bcb3eef 3851 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3852
3853 /* implicit withdraw, decrement aggregate and pcount here.
3854 * only if update is accepted, they'll increment below.
3855 */
40381db7 3856 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3857
3858 /* Update bgp route dampening information. */
40ec3340 3859 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3860 && peer->sort == BGP_PEER_EBGP) {
3861 /* This is implicit withdraw so we should update
40ec3340
DS
3862 * dampening information.
3863 */
40381db7 3864 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3865 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3866 }
49e5a4a0 3867#ifdef ENABLE_BGP_VNC
d62a17ae 3868 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3869 struct bgp_dest *pdest = NULL;
d62a17ae 3870 struct bgp_table *table = NULL;
3871
9bcb3eef
DS
3872 pdest = bgp_node_get(bgp->rib[afi][safi],
3873 (struct prefix *)prd);
3874 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3875 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3876
3877 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3878 bgp, prd, table, p, pi);
d62a17ae 3879 }
9bcb3eef 3880 bgp_dest_unlock_node(pdest);
d62a17ae 3881 }
3882 if ((afi == AFI_IP || afi == AFI_IP6)
3883 && (safi == SAFI_UNICAST)) {
40381db7 3884 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3885 /*
3886 * Implicit withdraw case.
3887 */
3888 ++vnc_implicit_withdraw;
40381db7
DS
3889 vnc_import_bgp_del_route(bgp, p, pi);
3890 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3891 }
3892 }
65efcfce 3893#endif
128ea8ab 3894
d62a17ae 3895 /* Special handling for EVPN update of an existing route. If the
3896 * extended community attribute has changed, we need to
3897 * un-import
3898 * the route using its existing extended community. It will be
3899 * subsequently processed for import with the new extended
3900 * community.
3901 */
6f8c9c11
PR
3902 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3903 && !same_attr) {
40381db7 3904 if ((pi->attr->flag
d62a17ae 3905 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3906 && (attr_new->flag
3907 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3908 int cmp;
3909
40381db7 3910 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3911 attr_new->ecommunity);
3912 if (!cmp) {
3913 if (bgp_debug_update(peer, p, NULL, 1))
3914 zlog_debug(
3915 "Change in EXT-COMM, existing %s new %s",
3916 ecommunity_str(
40381db7 3917 pi->attr->ecommunity),
d62a17ae 3918 ecommunity_str(
3919 attr_new->ecommunity));
6f8c9c11
PR
3920 if (safi == SAFI_EVPN)
3921 bgp_evpn_unimport_route(
3922 bgp, afi, safi, p, pi);
3923 else /* SAFI_MPLS_VPN */
3924 vpn_leak_to_vrf_withdraw(bgp,
3925 pi);
d62a17ae 3926 }
3927 }
3928 }
718e3744 3929
d62a17ae 3930 /* Update to new attribute. */
40381db7
DS
3931 bgp_attr_unintern(&pi->attr);
3932 pi->attr = attr_new;
d62a17ae 3933
3934 /* Update MPLS label */
3935 if (has_valid_label) {
40381db7 3936 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3937 if (extra->label != label) {
3938 memcpy(&extra->label, label,
dbd587da 3939 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3940 extra->num_labels = num_labels;
3941 }
b57ba6d2
MK
3942 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3943 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3944 }
718e3744 3945
e496b420
HS
3946 /* Update SRv6 SID */
3947 if (attr->srv6_l3vpn) {
3948 extra = bgp_path_info_extra_get(pi);
3949 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3950 sid_copy(&extra->sid[0],
3951 &attr->srv6_l3vpn->sid);
3952 extra->num_sids = 1;
3953 }
3954 } else if (attr->srv6_vpn) {
3955 extra = bgp_path_info_extra_get(pi);
3956 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3957 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3958 extra->num_sids = 1;
3959 }
3960 }
3961
49e5a4a0 3962#ifdef ENABLE_BGP_VNC
d62a17ae 3963 if ((afi == AFI_IP || afi == AFI_IP6)
3964 && (safi == SAFI_UNICAST)) {
3965 if (vnc_implicit_withdraw) {
3966 /*
3967 * Add back the route with its new attributes
3968 * (e.g., nexthop).
3969 * The route is still selected, until the route
3970 * selection
3971 * queued by bgp_process actually runs. We have
3972 * to make this
3973 * update to the VNC side immediately to avoid
3974 * racing against
3975 * configuration changes (e.g., route-map
3976 * changes) which
3977 * trigger re-importation of the entire RIB.
3978 */
40381db7
DS
3979 vnc_import_bgp_add_route(bgp, p, pi);
3980 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3981 }
3982 }
65efcfce
LB
3983#endif
3984
d62a17ae 3985 /* Update bgp route dampening information. */
40ec3340 3986 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3987 && peer->sort == BGP_PEER_EBGP) {
3988 /* Now we do normal update dampening. */
9bcb3eef 3989 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3990 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3991 bgp_dest_unlock_node(dest);
d62a17ae 3992 return 0;
3993 }
3994 }
128ea8ab 3995
d62a17ae 3996 /* Nexthop reachability check - for unicast and
3997 * labeled-unicast.. */
7c312383
AD
3998 if (((afi == AFI_IP || afi == AFI_IP6)
3999 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4000 || (safi == SAFI_EVPN &&
4001 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4002 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4003 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4004 && !CHECK_FLAG(peer->flags,
4005 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4006 && !CHECK_FLAG(bgp->flags,
4007 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4008 connected = 1;
4009 else
4010 connected = 0;
4011
960035b2
PZ
4012 struct bgp *bgp_nexthop = bgp;
4013
40381db7
DS
4014 if (pi->extra && pi->extra->bgp_orig)
4015 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4016
7c312383
AD
4017 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4018
4019 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4020 pi, NULL, connected)
a4d82a8a 4021 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4022 bgp_path_info_set_flag(dest, pi,
4023 BGP_PATH_VALID);
d62a17ae 4024 else {
4025 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4026 zlog_debug("%s(%pI4): NH unresolved",
4027 __func__,
4028 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4029 }
9bcb3eef 4030 bgp_path_info_unset_flag(dest, pi,
18ee8310 4031 BGP_PATH_VALID);
d62a17ae 4032 }
4033 } else
9bcb3eef 4034 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4035
49e5a4a0 4036#ifdef ENABLE_BGP_VNC
d62a17ae 4037 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4038 struct bgp_dest *pdest = NULL;
d62a17ae 4039 struct bgp_table *table = NULL;
4040
9bcb3eef
DS
4041 pdest = bgp_node_get(bgp->rib[afi][safi],
4042 (struct prefix *)prd);
4043 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4044 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4045
4046 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4047 bgp, prd, table, p, pi);
d62a17ae 4048 }
9bcb3eef 4049 bgp_dest_unlock_node(pdest);
d62a17ae 4050 }
4051#endif
718e3744 4052
d62a17ae 4053 /* If this is an EVPN route and some attribute has changed,
4054 * process
4055 * route for import. If the extended community has changed, we
4056 * would
4057 * have done the un-import earlier and the import would result
4058 * in the
4059 * route getting injected into appropriate L2 VNIs. If it is
4060 * just
4061 * some other attribute change, the import will result in
4062 * updating
4063 * the attributes for the route in the VNI(s).
4064 */
7c312383
AD
4065 if (safi == SAFI_EVPN && !same_attr &&
4066 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4067 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4068
4069 /* Process change. */
40381db7 4070 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4071
9bcb3eef
DS
4072 bgp_process(bgp, dest, afi, safi);
4073 bgp_dest_unlock_node(dest);
558d1fec 4074
ddb5b488
PZ
4075 if (SAFI_UNICAST == safi
4076 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4077 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4078
40381db7 4079 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4080 }
4081 if ((SAFI_MPLS_VPN == safi)
4082 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4083
40381db7 4084 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4085 }
4086
49e5a4a0 4087#ifdef ENABLE_BGP_VNC
d62a17ae 4088 if (SAFI_MPLS_VPN == safi) {
4089 mpls_label_t label_decoded = decode_label(label);
28070ee3 4090
d62a17ae 4091 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4092 type, sub_type, &label_decoded);
4093 }
4094 if (SAFI_ENCAP == safi) {
4095 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4096 type, sub_type, NULL);
4097 }
28070ee3
PZ
4098#endif
4099
d62a17ae 4100 return 0;
4101 } // End of implicit withdraw
718e3744 4102
d62a17ae 4103 /* Received Logging. */
4104 if (bgp_debug_update(peer, p, NULL, 1)) {
4105 if (!peer->rcvd_attr_printed) {
4106 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4107 peer->rcvd_attr_str);
4108 peer->rcvd_attr_printed = 1;
4109 }
718e3744 4110
a4d82a8a 4111 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4112 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4113 sizeof(pfx_buf));
4114 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4115 }
718e3744 4116
d62a17ae 4117 /* Make new BGP info. */
9bcb3eef 4118 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4119
d62a17ae 4120 /* Update MPLS label */
4121 if (has_valid_label) {
18ee8310 4122 extra = bgp_path_info_extra_get(new);
8ba71050 4123 if (extra->label != label) {
dbd587da
QY
4124 memcpy(&extra->label, label,
4125 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4126 extra->num_labels = num_labels;
4127 }
b57ba6d2
MK
4128 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4129 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4130 }
718e3744 4131
e496b420
HS
4132 /* Update SRv6 SID */
4133 if (safi == SAFI_MPLS_VPN) {
4134 extra = bgp_path_info_extra_get(new);
4135 if (attr->srv6_l3vpn) {
4136 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4137 extra->num_sids = 1;
4138 } else if (attr->srv6_vpn) {
4139 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4140 extra->num_sids = 1;
4141 }
4142 }
4143
d62a17ae 4144 /* Update Overlay Index */
4145 if (afi == AFI_L2VPN) {
4146 overlay_index_update(new->attr,
d62a17ae 4147 evpn == NULL ? NULL : &evpn->gw_ip);
4148 }
4149 /* Nexthop reachability check. */
7c312383
AD
4150 if (((afi == AFI_IP || afi == AFI_IP6)
4151 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4152 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4153 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4154 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4155 && !CHECK_FLAG(peer->flags,
4156 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4157 && !CHECK_FLAG(bgp->flags,
4158 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4159 connected = 1;
4160 else
4161 connected = 0;
4162
7c312383
AD
4163 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4164
4165 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
4166 connected)
a4d82a8a 4167 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4168 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4169 else {
4170 if (BGP_DEBUG(nht, NHT)) {
4171 char buf1[INET6_ADDRSTRLEN];
4172 inet_ntop(AF_INET,
4173 (const void *)&attr_new->nexthop,
4174 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4175 zlog_debug("%s(%s): NH unresolved", __func__,
4176 buf1);
d62a17ae 4177 }
9bcb3eef 4178 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4179 }
4180 } else
9bcb3eef 4181 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4182
d62a17ae 4183 /* Addpath ID */
4184 new->addpath_rx_id = addpath_id;
4185
4186 /* Increment prefix */
4187 bgp_aggregate_increment(bgp, p, new, afi, safi);
4188
4189 /* Register new BGP information. */
9bcb3eef 4190 bgp_path_info_add(dest, new);
d62a17ae 4191
4192 /* route_node_get lock */
9bcb3eef 4193 bgp_dest_unlock_node(dest);
558d1fec 4194
49e5a4a0 4195#ifdef ENABLE_BGP_VNC
d62a17ae 4196 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4197 struct bgp_dest *pdest = NULL;
d62a17ae 4198 struct bgp_table *table = NULL;
4199
9bcb3eef
DS
4200 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4201 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4202 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4203
4204 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4205 bgp, prd, table, p, new);
4206 }
9bcb3eef 4207 bgp_dest_unlock_node(pdest);
d62a17ae 4208 }
65efcfce
LB
4209#endif
4210
d62a17ae 4211 /* If this is an EVPN route, process for import. */
7c312383 4212 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4213 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4214
9bcb3eef 4215 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4216
d62a17ae 4217 /* Process change. */
9bcb3eef 4218 bgp_process(bgp, dest, afi, safi);
718e3744 4219
ddb5b488
PZ
4220 if (SAFI_UNICAST == safi
4221 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4222 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4223 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4224 }
4225 if ((SAFI_MPLS_VPN == safi)
4226 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4227
4228 vpn_leak_to_vrf_update(bgp, new);
4229 }
49e5a4a0 4230#ifdef ENABLE_BGP_VNC
d62a17ae 4231 if (SAFI_MPLS_VPN == safi) {
4232 mpls_label_t label_decoded = decode_label(label);
28070ee3 4233
d62a17ae 4234 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4235 sub_type, &label_decoded);
4236 }
4237 if (SAFI_ENCAP == safi) {
4238 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4239 sub_type, NULL);
4240 }
28070ee3
PZ
4241#endif
4242
d62a17ae 4243 return 0;
718e3744 4244
d62a17ae 4245/* This BGP update is filtered. Log the reason then update BGP
4246 entry. */
4247filtered:
9bcb3eef 4248 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4249
d62a17ae 4250 if (bgp_debug_update(peer, p, NULL, 1)) {
4251 if (!peer->rcvd_attr_printed) {
4252 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4253 peer->rcvd_attr_str);
4254 peer->rcvd_attr_printed = 1;
4255 }
718e3744 4256
a4d82a8a 4257 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4258 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4259 sizeof(pfx_buf));
4260 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4261 peer->host, pfx_buf, reason);
4262 }
128ea8ab 4263
40381db7 4264 if (pi) {
d62a17ae 4265 /* If this is an EVPN route, un-import it as it is now filtered.
4266 */
4267 if (safi == SAFI_EVPN)
40381db7 4268 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4269
ddb5b488
PZ
4270 if (SAFI_UNICAST == safi
4271 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4272 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4273
40381db7 4274 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4275 }
4276 if ((SAFI_MPLS_VPN == safi)
4277 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4278
40381db7 4279 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4280 }
4281
9bcb3eef 4282 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4283 }
4284
9bcb3eef 4285 bgp_dest_unlock_node(dest);
558d1fec 4286
49e5a4a0 4287#ifdef ENABLE_BGP_VNC
d62a17ae 4288 /*
4289 * Filtered update is treated as an implicit withdrawal (see
4290 * bgp_rib_remove()
4291 * a few lines above)
4292 */
4293 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4294 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4295 0);
4296 }
97736e32
PZ
4297#endif
4298
d62a17ae 4299 return 0;
718e3744 4300}
4301
26a3ffd6 4302int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4303 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4304 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4305 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4306{
d62a17ae 4307 struct bgp *bgp;
4308 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4309 struct bgp_dest *dest;
40381db7 4310 struct bgp_path_info *pi;
718e3744 4311
49e5a4a0 4312#ifdef ENABLE_BGP_VNC
d62a17ae 4313 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4314 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4315 0);
4316 }
28070ee3
PZ
4317#endif
4318
d62a17ae 4319 bgp = peer->bgp;
4320
4321 /* Lookup node. */
9bcb3eef 4322 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4323
4324 /* If peer is soft reconfiguration enabled. Record input packet for
4325 * further calculation.
4326 *
4327 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4328 * routes that are filtered. This tanks out Quagga RS pretty badly due
4329 * to
4330 * the iteration over all RS clients.
4331 * Since we need to remove the entry from adj_in anyway, do that first
4332 * and
4333 * if there was no entry, we don't need to do anything more.
4334 */
4335 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4336 && peer != bgp->peer_self)
9bcb3eef 4337 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4338 peer->stat_pfx_dup_withdraw++;
4339
d62a17ae 4340 if (bgp_debug_update(peer, p, NULL, 1)) {
4341 bgp_debug_rdpfxpath2str(
a4d82a8a 4342 afi, safi, prd, p, label, num_labels,
d62a17ae 4343 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4344 sizeof(pfx_buf));
4345 zlog_debug(
4346 "%s withdrawing route %s not in adj-in",
4347 peer->host, pfx_buf);
4348 }
9bcb3eef 4349 bgp_dest_unlock_node(dest);
d62a17ae 4350 return 0;
4351 }
cd808e74 4352
d62a17ae 4353 /* Lookup withdrawn route. */
9bcb3eef 4354 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4355 if (pi->peer == peer && pi->type == type
4356 && pi->sub_type == sub_type
4357 && pi->addpath_rx_id == addpath_id)
d62a17ae 4358 break;
4359
4360 /* Logging. */
4361 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4362 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4363 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4364 sizeof(pfx_buf));
4365 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4366 pfx_buf);
4367 }
718e3744 4368
d62a17ae 4369 /* Withdraw specified route from routing table. */
40381db7 4370 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4371 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4372 if (SAFI_UNICAST == safi
4373 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4374 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4375 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4376 }
4377 if ((SAFI_MPLS_VPN == safi)
4378 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4379
40381db7 4380 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4381 }
4382 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4383 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4384 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4385 sizeof(pfx_buf));
4386 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4387 }
718e3744 4388
d62a17ae 4389 /* Unlock bgp_node_get() lock. */
9bcb3eef 4390 bgp_dest_unlock_node(dest);
d62a17ae 4391
4392 return 0;
718e3744 4393}
6b0655a2 4394
d62a17ae 4395void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4396 int withdraw)
718e3744 4397{
d62a17ae 4398 struct update_subgroup *subgrp;
4399 subgrp = peer_subgroup(peer, afi, safi);
4400 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4401}
6182d65b 4402
718e3744 4403
3f9c7369
DS
4404/*
4405 * bgp_stop_announce_route_timer
4406 */
d62a17ae 4407void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4408{
d62a17ae 4409 if (!paf->t_announce_route)
4410 return;
4411
50478845 4412 thread_cancel(&paf->t_announce_route);
718e3744 4413}
6b0655a2 4414
3f9c7369
DS
4415/*
4416 * bgp_announce_route_timer_expired
4417 *
4418 * Callback that is invoked when the route announcement timer for a
4419 * peer_af expires.
4420 */
d62a17ae 4421static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4422{
d62a17ae 4423 struct peer_af *paf;
4424 struct peer *peer;
558d1fec 4425
d62a17ae 4426 paf = THREAD_ARG(t);
4427 peer = paf->peer;
718e3744 4428
d62a17ae 4429 if (peer->status != Established)
4430 return 0;
3f9c7369 4431
d62a17ae 4432 if (!peer->afc_nego[paf->afi][paf->safi])
4433 return 0;
3f9c7369 4434
d62a17ae 4435 peer_af_announce_route(paf, 1);
c5aec50b
MK
4436
4437 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4438 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4439
d62a17ae 4440 return 0;
718e3744 4441}
4442
3f9c7369
DS
4443/*
4444 * bgp_announce_route
4445 *
4446 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4447 */
d62a17ae 4448void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4449{
4450 struct peer_af *paf;
4451 struct update_subgroup *subgrp;
4452
4453 paf = peer_af_find(peer, afi, safi);
4454 if (!paf)
4455 return;
4456 subgrp = PAF_SUBGRP(paf);
4457
4458 /*
4459 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4460 * or a refresh has already been triggered.
4461 */
4462 if (!subgrp || paf->t_announce_route)
4463 return;
4464
4465 /*
4466 * Start a timer to stagger/delay the announce. This serves
4467 * two purposes - announcement can potentially be combined for
4468 * multiple peers and the announcement doesn't happen in the
4469 * vty context.
4470 */
4471 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4472 (subgrp->peer_count == 1)
4473 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4474 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4475 &paf->t_announce_route);
3f9c7369
DS
4476}
4477
4478/*
4479 * Announce routes from all AF tables to a peer.
4480 *
4481 * This should ONLY be called when there is a need to refresh the
4482 * routes to the peer based on a policy change for this peer alone
4483 * or a route refresh request received from the peer.
4484 * The operation will result in splitting the peer from its existing
4485 * subgroups and putting it in new subgroups.
4486 */
d62a17ae 4487void bgp_announce_route_all(struct peer *peer)
718e3744 4488{
d62a17ae 4489 afi_t afi;
4490 safi_t safi;
4491
05c7a1cc
QY
4492 FOREACH_AFI_SAFI (afi, safi)
4493 bgp_announce_route(peer, afi, safi);
718e3744 4494}
6b0655a2 4495
d62a17ae 4496static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4497 struct bgp_table *table,
4498 struct prefix_rd *prd)
718e3744 4499{
d62a17ae 4500 int ret;
9bcb3eef 4501 struct bgp_dest *dest;
d62a17ae 4502 struct bgp_adj_in *ain;
718e3744 4503
d62a17ae 4504 if (!table)
4505 table = peer->bgp->rib[afi][safi];
718e3744 4506
9bcb3eef
DS
4507 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4508 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4509 if (ain->peer != peer)
4510 continue;
8692c506 4511
d7d15889 4512 struct bgp_path_info *pi;
d7c0a89a 4513 uint32_t num_labels = 0;
b57ba6d2 4514 mpls_label_t *label_pnt = NULL;
8cb687c2 4515 struct bgp_route_evpn evpn;
b57ba6d2 4516
9bcb3eef 4517 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4518 pi = pi->next)
4519 if (pi->peer == peer)
4520 break;
4521
40381db7
DS
4522 if (pi && pi->extra)
4523 num_labels = pi->extra->num_labels;
b57ba6d2 4524 if (num_labels)
40381db7 4525 label_pnt = &pi->extra->label[0];
8cb687c2 4526 if (pi)
6c924775
DS
4527 memcpy(&evpn,
4528 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4529 sizeof(evpn));
4530 else
4531 memset(&evpn, 0, sizeof(evpn));
8692c506 4532
9bcb3eef
DS
4533 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4534 ain->addpath_rx_id, ain->attr, afi,
4535 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4536 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4537 num_labels, 1, &evpn);
ea47320b
DL
4538
4539 if (ret < 0) {
9bcb3eef 4540 bgp_dest_unlock_node(dest);
ea47320b 4541 return;
d62a17ae 4542 }
4543 }
718e3744 4544}
4545
d62a17ae 4546void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4547{
9bcb3eef 4548 struct bgp_dest *dest;
d62a17ae 4549 struct bgp_table *table;
718e3744 4550
d62a17ae 4551 if (peer->status != Established)
4552 return;
718e3744 4553
d62a17ae 4554 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4555 && (safi != SAFI_EVPN))
4556 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4557 else
9bcb3eef
DS
4558 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4559 dest = bgp_route_next(dest)) {
4560 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4561
b54892e0
DS
4562 if (table == NULL)
4563 continue;
8692c506 4564
9bcb3eef 4565 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4566 struct prefix_rd prd;
4567
4568 prd.family = AF_UNSPEC;
4569 prd.prefixlen = 64;
4570 memcpy(&prd.val, p->u.val, 8);
4571
4572 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4573 }
718e3744 4574}
6b0655a2 4575
228da428 4576
d62a17ae 4577struct bgp_clear_node_queue {
9bcb3eef 4578 struct bgp_dest *dest;
228da428
CC
4579};
4580
d62a17ae 4581static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4582{
d62a17ae 4583 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4584 struct bgp_dest *dest = cnq->dest;
d62a17ae 4585 struct peer *peer = wq->spec.data;
40381db7 4586 struct bgp_path_info *pi;
3103e8d2 4587 struct bgp *bgp;
9bcb3eef
DS
4588 afi_t afi = bgp_dest_table(dest)->afi;
4589 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4590
9bcb3eef 4591 assert(dest && peer);
3103e8d2 4592 bgp = peer->bgp;
d62a17ae 4593
4594 /* It is possible that we have multiple paths for a prefix from a peer
4595 * if that peer is using AddPath.
4596 */
9bcb3eef 4597 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4598 if (pi->peer != peer)
ea47320b
DL
4599 continue;
4600
4601 /* graceful restart STALE flag set. */
9af52ccf
DA
4602 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4603 && peer->nsf[afi][safi])
4604 || CHECK_FLAG(peer->af_sflags[afi][safi],
4605 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4606 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4607 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4608 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4609 else {
4610 /* If this is an EVPN route, process for
4611 * un-import. */
4612 if (safi == SAFI_EVPN)
9bcb3eef
DS
4613 bgp_evpn_unimport_route(
4614 bgp, afi, safi,
4615 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4616 /* Handle withdraw for VRF route-leaking and L3VPN */
4617 if (SAFI_UNICAST == safi
4618 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4619 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4620 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4621 bgp, pi);
960035b2 4622 }
3103e8d2 4623 if (SAFI_MPLS_VPN == safi &&
960035b2 4624 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4625 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4626 }
3103e8d2 4627
9bcb3eef 4628 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4629 }
ea47320b 4630 }
d62a17ae 4631 return WQ_SUCCESS;
200df115 4632}
4633
d62a17ae 4634static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4635{
d62a17ae 4636 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4637 struct bgp_dest *dest = cnq->dest;
4638 struct bgp_table *table = bgp_dest_table(dest);
228da428 4639
9bcb3eef 4640 bgp_dest_unlock_node(dest);
d62a17ae 4641 bgp_table_unlock(table);
4642 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4643}
4644
d62a17ae 4645static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4646{
d62a17ae 4647 struct peer *peer = wq->spec.data;
64e580a7 4648
d62a17ae 4649 /* Tickle FSM to start moving again */
4650 BGP_EVENT_ADD(peer, Clearing_Completed);
4651
4652 peer_unlock(peer); /* bgp_clear_route */
200df115 4653}
718e3744 4654
d62a17ae 4655static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4656{
d62a17ae 4657 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4658
4659 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4660#undef CLEAR_QUEUE_NAME_LEN
4661
0ce1ca80 4662 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4663 peer->clear_node_queue->spec.hold = 10;
4664 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4665 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4666 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4667 peer->clear_node_queue->spec.max_retries = 0;
4668
4669 /* we only 'lock' this peer reference when the queue is actually active
4670 */
4671 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4672}
4673
d62a17ae 4674static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4675 struct bgp_table *table)
65ca75e0 4676{
9bcb3eef 4677 struct bgp_dest *dest;
b6c386bb 4678 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4679
d62a17ae 4680 if (!table)
4681 table = peer->bgp->rib[afi][safi];
dc83d712 4682
d62a17ae 4683 /* If still no table => afi/safi isn't configured at all or smth. */
4684 if (!table)
4685 return;
dc83d712 4686
9bcb3eef 4687 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4688 struct bgp_path_info *pi, *next;
d62a17ae 4689 struct bgp_adj_in *ain;
4690 struct bgp_adj_in *ain_next;
4691
4692 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4693 * queued for every clearing peer, regardless of whether it is
4694 * relevant to the peer at hand.
4695 *
4696 * Overview: There are 3 different indices which need to be
4697 * scrubbed, potentially, when a peer is removed:
4698 *
4699 * 1 peer's routes visible via the RIB (ie accepted routes)
4700 * 2 peer's routes visible by the (optional) peer's adj-in index
4701 * 3 other routes visible by the peer's adj-out index
4702 *
4703 * 3 there is no hurry in scrubbing, once the struct peer is
4704 * removed from bgp->peer, we could just GC such deleted peer's
4705 * adj-outs at our leisure.
4706 *
4707 * 1 and 2 must be 'scrubbed' in some way, at least made
4708 * invisible via RIB index before peer session is allowed to be
4709 * brought back up. So one needs to know when such a 'search' is
4710 * complete.
4711 *
4712 * Ideally:
4713 *
4714 * - there'd be a single global queue or a single RIB walker
4715 * - rather than tracking which route_nodes still need to be
4716 * examined on a peer basis, we'd track which peers still
4717 * aren't cleared
4718 *
4719 * Given that our per-peer prefix-counts now should be reliable,
4720 * this may actually be achievable. It doesn't seem to be a huge
4721 * problem at this time,
4722 *
4723 * It is possible that we have multiple paths for a prefix from
4724 * a peer
4725 * if that peer is using AddPath.
4726 */
9bcb3eef 4727 ain = dest->adj_in;
d62a17ae 4728 while (ain) {
4729 ain_next = ain->next;
4730
4731 if (ain->peer == peer) {
9bcb3eef
DS
4732 bgp_adj_in_remove(dest, ain);
4733 bgp_dest_unlock_node(dest);
d62a17ae 4734 }
4735
4736 ain = ain_next;
4737 }
4738
9bcb3eef 4739 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4740 next = pi->next;
4741 if (pi->peer != peer)
d62a17ae 4742 continue;
4743
4744 if (force)
9bcb3eef 4745 bgp_path_info_reap(dest, pi);
d62a17ae 4746 else {
4747 struct bgp_clear_node_queue *cnq;
4748
4749 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4750 bgp_table_lock(bgp_dest_table(dest));
4751 bgp_dest_lock_node(dest);
d62a17ae 4752 cnq = XCALLOC(
4753 MTYPE_BGP_CLEAR_NODE_QUEUE,
4754 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4755 cnq->dest = dest;
d62a17ae 4756 work_queue_add(peer->clear_node_queue, cnq);
4757 break;
4758 }
4759 }
4760 }
4761 return;
4762}
4763
4764void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4765{
9bcb3eef 4766 struct bgp_dest *dest;
d62a17ae 4767 struct bgp_table *table;
4768
4769 if (peer->clear_node_queue == NULL)
4770 bgp_clear_node_queue_init(peer);
4771
4772 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4773 * Idle until it receives a Clearing_Completed event. This protects
4774 * against peers which flap faster than we can we clear, which could
4775 * lead to:
4776 *
4777 * a) race with routes from the new session being installed before
4778 * clear_route_node visits the node (to delete the route of that
4779 * peer)
4780 * b) resource exhaustion, clear_route_node likely leads to an entry
4781 * on the process_main queue. Fast-flapping could cause that queue
4782 * to grow and grow.
4783 */
4784
4785 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4786 * the unlock will happen upon work-queue completion; other wise, the
4787 * unlock happens at the end of this function.
4788 */
4789 if (!peer->clear_node_queue->thread)
4790 peer_lock(peer);
4791
4792 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4793 bgp_clear_route_table(peer, afi, safi, NULL);
4794 else
9bcb3eef
DS
4795 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4796 dest = bgp_route_next(dest)) {
4797 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4798 if (!table)
4799 continue;
4800
4801 bgp_clear_route_table(peer, afi, safi, table);
4802 }
d62a17ae 4803
4804 /* unlock if no nodes got added to the clear-node-queue. */
4805 if (!peer->clear_node_queue->thread)
4806 peer_unlock(peer);
718e3744 4807}
d62a17ae 4808
4809void bgp_clear_route_all(struct peer *peer)
718e3744 4810{
d62a17ae 4811 afi_t afi;
4812 safi_t safi;
718e3744 4813
05c7a1cc
QY
4814 FOREACH_AFI_SAFI (afi, safi)
4815 bgp_clear_route(peer, afi, safi);
65efcfce 4816
49e5a4a0 4817#ifdef ENABLE_BGP_VNC
d62a17ae 4818 rfapiProcessPeerDown(peer);
65efcfce 4819#endif
718e3744 4820}
4821
d62a17ae 4822void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4823{
d62a17ae 4824 struct bgp_table *table;
9bcb3eef 4825 struct bgp_dest *dest;
d62a17ae 4826 struct bgp_adj_in *ain;
4827 struct bgp_adj_in *ain_next;
718e3744 4828
d62a17ae 4829 table = peer->bgp->rib[afi][safi];
718e3744 4830
d62a17ae 4831 /* It is possible that we have multiple paths for a prefix from a peer
4832 * if that peer is using AddPath.
4833 */
9bcb3eef
DS
4834 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4835 ain = dest->adj_in;
43143c8f 4836
d62a17ae 4837 while (ain) {
4838 ain_next = ain->next;
43143c8f 4839
d62a17ae 4840 if (ain->peer == peer) {
9bcb3eef
DS
4841 bgp_adj_in_remove(dest, ain);
4842 bgp_dest_unlock_node(dest);
d62a17ae 4843 }
43143c8f 4844
d62a17ae 4845 ain = ain_next;
4846 }
4847 }
718e3744 4848}
93406d87 4849
d62a17ae 4850void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4851{
9bcb3eef 4852 struct bgp_dest *dest;
40381db7 4853 struct bgp_path_info *pi;
d62a17ae 4854 struct bgp_table *table;
4855
9af52ccf 4856 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
4857 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4858 dest = bgp_route_next(dest)) {
4859 struct bgp_dest *rm;
d62a17ae 4860
4861 /* look for neighbor in tables */
9bcb3eef 4862 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4863 if (!table)
ea47320b
DL
4864 continue;
4865
4866 for (rm = bgp_table_top(table); rm;
4867 rm = bgp_route_next(rm))
9bcb3eef 4868 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4869 pi = pi->next) {
40381db7 4870 if (pi->peer != peer)
ea47320b 4871 continue;
40381db7 4872 if (!CHECK_FLAG(pi->flags,
1defdda8 4873 BGP_PATH_STALE))
ea47320b
DL
4874 break;
4875
40381db7 4876 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4877 break;
4878 }
d62a17ae 4879 }
4880 } else {
9bcb3eef
DS
4881 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4882 dest = bgp_route_next(dest))
4883 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4884 pi = pi->next) {
40381db7 4885 if (pi->peer != peer)
ea47320b 4886 continue;
40381db7 4887 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4888 break;
9bcb3eef 4889 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4890 break;
4891 }
d62a17ae 4892 }
93406d87 4893}
6b0655a2 4894
9af52ccf
DA
4895void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4896{
4897 struct bgp_dest *dest, *ndest;
4898 struct bgp_path_info *pi;
4899 struct bgp_table *table;
4900
4901 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4902 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4903 dest = bgp_route_next(dest)) {
4904 table = bgp_dest_get_bgp_table_info(dest);
4905 if (!table)
4906 continue;
4907
4908 for (ndest = bgp_table_top(table); ndest;
4909 ndest = bgp_route_next(ndest)) {
4910 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
4911 pi = pi->next) {
4912 if (pi->peer != peer)
4913 continue;
4914
4915 if ((CHECK_FLAG(
4916 peer->af_sflags[afi][safi],
4917 PEER_STATUS_ENHANCED_REFRESH))
4918 && !CHECK_FLAG(pi->flags,
4919 BGP_PATH_STALE)
4920 && !CHECK_FLAG(
4921 pi->flags,
4922 BGP_PATH_UNUSEABLE)) {
4923 if (bgp_debug_neighbor_events(
4924 peer))
4925 zlog_debug(
4926 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4927 peer->host,
4928 afi2str(afi),
4929 safi2str(safi),
4930 bgp_dest_get_prefix(
4931 ndest));
4932
4933 bgp_path_info_set_flag(
4934 ndest, pi,
4935 BGP_PATH_STALE);
4936 }
4937 }
4938 }
4939 }
4940 } else {
4941 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4942 dest = bgp_route_next(dest)) {
4943 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
4944 pi = pi->next) {
4945 if (pi->peer != peer)
4946 continue;
4947
4948 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
4949 PEER_STATUS_ENHANCED_REFRESH))
4950 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4951 && !CHECK_FLAG(pi->flags,
4952 BGP_PATH_UNUSEABLE)) {
4953 if (bgp_debug_neighbor_events(peer))
4954 zlog_debug(
4955 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4956 peer->host,
4957 afi2str(afi),
4958 safi2str(safi),
4959 bgp_dest_get_prefix(
4960 dest));
4961
4962 bgp_path_info_set_flag(dest, pi,
4963 BGP_PATH_STALE);
4964 }
4965 }
4966 }
4967 }
4968}
4969
3dc339cd 4970bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4971{
e0df4c04 4972 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4973 return true;
e0df4c04 4974
9dac9fc8
DA
4975 if (peer->sort == BGP_PEER_EBGP
4976 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4977 || FILTER_LIST_OUT_NAME(filter)
4978 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4979 return true;
4980 return false;
9dac9fc8
DA
4981}
4982
3dc339cd 4983bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4984{
e0df4c04 4985 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4986 return true;
e0df4c04 4987
9dac9fc8
DA
4988 if (peer->sort == BGP_PEER_EBGP
4989 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4990 || FILTER_LIST_IN_NAME(filter)
4991 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4992 return true;
4993 return false;
9dac9fc8
DA
4994}
4995
568e10ca 4996static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4997 safi_t safi)
bb86c601 4998{
9bcb3eef 4999 struct bgp_dest *dest;
40381db7 5000 struct bgp_path_info *pi;
4b7e6066 5001 struct bgp_path_info *next;
bb86c601 5002
9bcb3eef
DS
5003 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5004 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5005 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5006
40381db7 5007 next = pi->next;
1b7bb747
CS
5008
5009 /* Unimport EVPN routes from VRFs */
5010 if (safi == SAFI_EVPN)
5011 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5012 SAFI_EVPN, p, pi);
1b7bb747 5013
40381db7
DS
5014 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5015 && pi->type == ZEBRA_ROUTE_BGP
5016 && (pi->sub_type == BGP_ROUTE_NORMAL
5017 || pi->sub_type == BGP_ROUTE_AGGREGATE
5018 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5019
d62a17ae 5020 if (bgp_fibupd_safi(safi))
b54892e0 5021 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5022 }
9514b37d 5023
9bcb3eef 5024 bgp_path_info_reap(dest, pi);
d62a17ae 5025 }
bb86c601
LB
5026}
5027
718e3744 5028/* Delete all kernel routes. */
d62a17ae 5029void bgp_cleanup_routes(struct bgp *bgp)
5030{
5031 afi_t afi;
9bcb3eef 5032 struct bgp_dest *dest;
67009e22 5033 struct bgp_table *table;
d62a17ae 5034
5035 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5036 if (afi == AFI_L2VPN)
5037 continue;
568e10ca 5038 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5039 SAFI_UNICAST);
d62a17ae 5040 /*
5041 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5042 */
5043 if (afi != AFI_L2VPN) {
5044 safi_t safi;
5045 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5046 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5047 dest = bgp_route_next(dest)) {
5048 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5049 if (table != NULL) {
5050 bgp_cleanup_table(bgp, table, safi);
5051 bgp_table_finish(&table);
9bcb3eef
DS
5052 bgp_dest_set_bgp_table_info(dest, NULL);
5053 bgp_dest_unlock_node(dest);
d62a17ae 5054 }
5055 }
5056 safi = SAFI_ENCAP;
9bcb3eef
DS
5057 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5058 dest = bgp_route_next(dest)) {
5059 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5060 if (table != NULL) {
5061 bgp_cleanup_table(bgp, table, safi);
5062 bgp_table_finish(&table);
9bcb3eef
DS
5063 bgp_dest_set_bgp_table_info(dest, NULL);
5064 bgp_dest_unlock_node(dest);
d62a17ae 5065 }
5066 }
5067 }
5068 }
9bcb3eef
DS
5069 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5070 dest = bgp_route_next(dest)) {
5071 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5072 if (table != NULL) {
5073 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5074 bgp_table_finish(&table);
9bcb3eef
DS
5075 bgp_dest_set_bgp_table_info(dest, NULL);
5076 bgp_dest_unlock_node(dest);
d62a17ae 5077 }
bb86c601 5078 }
718e3744 5079}
5080
d62a17ae 5081void bgp_reset(void)
718e3744 5082{
d62a17ae 5083 vty_reset();
5084 bgp_zclient_reset();
5085 access_list_reset();
5086 prefix_list_reset();
718e3744 5087}
6b0655a2 5088
d62a17ae 5089static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5090{
d62a17ae 5091 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5092 && CHECK_FLAG(peer->af_cap[afi][safi],
5093 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5094}
5095
718e3744 5096/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5097 value. */
d62a17ae 5098int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5099 struct bgp_nlri *packet)
5100{
d7c0a89a
QY
5101 uint8_t *pnt;
5102 uint8_t *lim;
d62a17ae 5103 struct prefix p;
5104 int psize;
5105 int ret;
5106 afi_t afi;
5107 safi_t safi;
5108 int addpath_encoded;
d7c0a89a 5109 uint32_t addpath_id;
d62a17ae 5110
d62a17ae 5111 pnt = packet->nlri;
5112 lim = pnt + packet->length;
5113 afi = packet->afi;
5114 safi = packet->safi;
5115 addpath_id = 0;
5116 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5117
5118 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5119 syntactic validity. If the field is syntactically incorrect,
5120 then the Error Subcode is set to Invalid Network Field. */
5121 for (; pnt < lim; pnt += psize) {
5122 /* Clear prefix structure. */
5123 memset(&p, 0, sizeof(struct prefix));
5124
5125 if (addpath_encoded) {
5126
5127 /* When packet overflow occurs return immediately. */
761ed665 5128 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5129 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5130
a3a850a1 5131 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5132 addpath_id = ntohl(addpath_id);
d62a17ae 5133 pnt += BGP_ADDPATH_ID_LEN;
5134 }
718e3744 5135
d62a17ae 5136 /* Fetch prefix length. */
5137 p.prefixlen = *pnt++;
5138 /* afi/safi validity already verified by caller,
5139 * bgp_update_receive */
5140 p.family = afi2family(afi);
5141
5142 /* Prefix length check. */
5143 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5144 flog_err(
e50f7cfd 5145 EC_BGP_UPDATE_RCV,
14454c9f 5146 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5147 peer->host, p.prefixlen, packet->afi);
513386b5 5148 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5149 }
6b0655a2 5150
d62a17ae 5151 /* Packet size overflow check. */
5152 psize = PSIZE(p.prefixlen);
5153
5154 /* When packet overflow occur return immediately. */
5155 if (pnt + psize > lim) {
af4c2728 5156 flog_err(
e50f7cfd 5157 EC_BGP_UPDATE_RCV,
d62a17ae 5158 "%s [Error] Update packet error (prefix length %d overflows packet)",
5159 peer->host, p.prefixlen);
513386b5 5160 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5161 }
5162
5163 /* Defensive coding, double-check the psize fits in a struct
5164 * prefix */
5165 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5166 flog_err(
e50f7cfd 5167 EC_BGP_UPDATE_RCV,
d62a17ae 5168 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5169 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5170 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5171 }
5172
5173 /* Fetch prefix from NLRI packet. */
a85297a7 5174 memcpy(p.u.val, pnt, psize);
d62a17ae 5175
5176 /* Check address. */
5177 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5178 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5179 /* From RFC4271 Section 6.3:
5180 *
5181 * If a prefix in the NLRI field is semantically
5182 * incorrect
5183 * (e.g., an unexpected multicast IP address),
5184 * an error SHOULD
5185 * be logged locally, and the prefix SHOULD be
5186 * ignored.
a4d82a8a 5187 */
af4c2728 5188 flog_err(
e50f7cfd 5189 EC_BGP_UPDATE_RCV,
23d0a753
DA
5190 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5191 peer->host, &p.u.prefix4);
d62a17ae 5192 continue;
5193 }
5194 }
5195
5196 /* Check address. */
5197 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5198 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5199 char buf[BUFSIZ];
5200
af4c2728 5201 flog_err(
e50f7cfd 5202 EC_BGP_UPDATE_RCV,
d62a17ae 5203 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5204 peer->host,
5205 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5206 BUFSIZ));
5207
5208 continue;
5209 }
5210 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5211 char buf[BUFSIZ];
5212
af4c2728 5213 flog_err(
e50f7cfd 5214 EC_BGP_UPDATE_RCV,
d62a17ae 5215 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5216 peer->host,
5217 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5218 BUFSIZ));
5219
5220 continue;
5221 }
5222 }
5223
5224 /* Normal process. */
5225 if (attr)
5226 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5227 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5228 NULL, NULL, 0, 0, NULL);
d62a17ae 5229 else
5230 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5231 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5232 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5233 NULL);
d62a17ae 5234
513386b5
DA
5235 /* Do not send BGP notification twice when maximum-prefix count
5236 * overflow. */
5237 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5238 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5239
5240 /* Address family configuration mismatch. */
d62a17ae 5241 if (ret < 0)
513386b5 5242 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5243 }
5244
5245 /* Packet length consistency check. */
5246 if (pnt != lim) {
af4c2728 5247 flog_err(
e50f7cfd 5248 EC_BGP_UPDATE_RCV,
d62a17ae 5249 "%s [Error] Update packet error (prefix length mismatch with total length)",
5250 peer->host);
513386b5 5251 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5252 }
6b0655a2 5253
513386b5 5254 return BGP_NLRI_PARSE_OK;
718e3744 5255}
5256
d62a17ae 5257static struct bgp_static *bgp_static_new(void)
718e3744 5258{
d62a17ae 5259 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5260}
5261
d62a17ae 5262static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5263{
0a22ddfb 5264 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5265 route_map_counter_decrement(bgp_static->rmap.map);
5266
0a22ddfb 5267 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5268 XFREE(MTYPE_BGP_STATIC, bgp_static);
5269}
5270
5f040085 5271void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5272 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5273{
9bcb3eef 5274 struct bgp_dest *dest;
40381db7 5275 struct bgp_path_info *pi;
4b7e6066 5276 struct bgp_path_info *new;
40381db7 5277 struct bgp_path_info rmap_path;
d62a17ae 5278 struct attr attr;
5279 struct attr *attr_new;
b68885f9 5280 route_map_result_t ret;
49e5a4a0 5281#ifdef ENABLE_BGP_VNC
d62a17ae 5282 int vnc_implicit_withdraw = 0;
65efcfce 5283#endif
fee0f4c6 5284
d62a17ae 5285 assert(bgp_static);
dd8103a9 5286
9bcb3eef 5287 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5288
d62a17ae 5289 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5290
d62a17ae 5291 attr.nexthop = bgp_static->igpnexthop;
5292 attr.med = bgp_static->igpmetric;
5293 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5294
d62a17ae 5295 if (bgp_static->atomic)
5296 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5297
d62a17ae 5298 /* Store label index, if required. */
5299 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5300 attr.label_index = bgp_static->label_index;
5301 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5302 }
718e3744 5303
d62a17ae 5304 /* Apply route-map. */
5305 if (bgp_static->rmap.name) {
5306 struct attr attr_tmp = attr;
80ced710 5307
40381db7
DS
5308 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5309 rmap_path.peer = bgp->peer_self;
5310 rmap_path.attr = &attr_tmp;
fee0f4c6 5311
d62a17ae 5312 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5313
1782514f 5314 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5315
d62a17ae 5316 bgp->peer_self->rmap_type = 0;
718e3744 5317
d62a17ae 5318 if (ret == RMAP_DENYMATCH) {
5319 /* Free uninterned attribute. */
5320 bgp_attr_flush(&attr_tmp);
718e3744 5321
d62a17ae 5322 /* Unintern original. */
5323 aspath_unintern(&attr.aspath);
5324 bgp_static_withdraw(bgp, p, afi, safi);
5325 return;
5326 }
7f323236 5327
637e5ba4 5328 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5329 bgp_attr_add_gshut_community(&attr_tmp);
5330
d62a17ae 5331 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5332 } else {
5333
637e5ba4 5334 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5335 bgp_attr_add_gshut_community(&attr);
5336
d62a17ae 5337 attr_new = bgp_attr_intern(&attr);
7f323236 5338 }
718e3744 5339
9bcb3eef 5340 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5341 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5342 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5343 break;
5344
40381db7
DS
5345 if (pi) {
5346 if (attrhash_cmp(pi->attr, attr_new)
5347 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5348 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5349 bgp_dest_unlock_node(dest);
d62a17ae 5350 bgp_attr_unintern(&attr_new);
5351 aspath_unintern(&attr.aspath);
5352 return;
5353 } else {
5354 /* The attribute is changed. */
9bcb3eef 5355 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5356
5357 /* Rewrite BGP route information. */
40381db7 5358 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5359 bgp_path_info_restore(dest, pi);
d62a17ae 5360 else
40381db7 5361 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5362#ifdef ENABLE_BGP_VNC
d62a17ae 5363 if ((afi == AFI_IP || afi == AFI_IP6)
5364 && (safi == SAFI_UNICAST)) {
40381db7 5365 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5366 /*
5367 * Implicit withdraw case.
40381db7 5368 * We have to do this before pi is
d62a17ae 5369 * changed
5370 */
5371 ++vnc_implicit_withdraw;
40381db7 5372 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5373 vnc_import_bgp_exterior_del_route(
40381db7 5374 bgp, p, pi);
d62a17ae 5375 }
5376 }
65efcfce 5377#endif
40381db7
DS
5378 bgp_attr_unintern(&pi->attr);
5379 pi->attr = attr_new;
5380 pi->uptime = bgp_clock();
49e5a4a0 5381#ifdef ENABLE_BGP_VNC
d62a17ae 5382 if ((afi == AFI_IP || afi == AFI_IP6)
5383 && (safi == SAFI_UNICAST)) {
5384 if (vnc_implicit_withdraw) {
40381db7 5385 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5386 vnc_import_bgp_exterior_add_route(
40381db7 5387 bgp, p, pi);
d62a17ae 5388 }
5389 }
65efcfce 5390#endif
718e3744 5391
d62a17ae 5392 /* Nexthop reachability check. */
892fedb6 5393 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5394 && (safi == SAFI_UNICAST
5395 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5396
5397 struct bgp *bgp_nexthop = bgp;
5398
40381db7
DS
5399 if (pi->extra && pi->extra->bgp_orig)
5400 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5401
5402 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5403 afi, pi, NULL, 0))
9bcb3eef 5404 bgp_path_info_set_flag(dest, pi,
18ee8310 5405 BGP_PATH_VALID);
d62a17ae 5406 else {
5407 if (BGP_DEBUG(nht, NHT)) {
5408 char buf1[INET6_ADDRSTRLEN];
5409 inet_ntop(p->family,
5410 &p->u.prefix, buf1,
5411 INET6_ADDRSTRLEN);
5412 zlog_debug(
5413 "%s(%s): Route not in table, not advertising",
15569c58 5414 __func__, buf1);
d62a17ae 5415 }
18ee8310 5416 bgp_path_info_unset_flag(
9bcb3eef 5417 dest, pi, BGP_PATH_VALID);
d62a17ae 5418 }
5419 } else {
5420 /* Delete the NHT structure if any, if we're
5421 * toggling between
5422 * enabling/disabling import check. We
5423 * deregister the route
5424 * from NHT to avoid overloading NHT and the
5425 * process interaction
5426 */
40381db7 5427 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5428 bgp_path_info_set_flag(dest, pi,
5429 BGP_PATH_VALID);
d62a17ae 5430 }
5431 /* Process change. */
40381db7 5432 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5433 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5434
5435 if (SAFI_UNICAST == safi
5436 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5437 || bgp->inst_type
5438 == BGP_INSTANCE_TYPE_DEFAULT)) {
5439 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5440 pi);
ddb5b488
PZ
5441 }
5442
9bcb3eef 5443 bgp_dest_unlock_node(dest);
d62a17ae 5444 aspath_unintern(&attr.aspath);
5445 return;
5446 }
718e3744 5447 }
718e3744 5448
d62a17ae 5449 /* Make new BGP info. */
5450 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5451 attr_new, dest);
d62a17ae 5452 /* Nexthop reachability check. */
892fedb6 5453 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5454 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5455 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5456 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5457 else {
5458 if (BGP_DEBUG(nht, NHT)) {
5459 char buf1[INET6_ADDRSTRLEN];
5460 inet_ntop(p->family, &p->u.prefix, buf1,
5461 INET6_ADDRSTRLEN);
5462 zlog_debug(
5463 "%s(%s): Route not in table, not advertising",
15569c58 5464 __func__, buf1);
d62a17ae 5465 }
9bcb3eef 5466 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5467 }
5468 } else {
5469 /* Delete the NHT structure if any, if we're toggling between
5470 * enabling/disabling import check. We deregister the route
5471 * from NHT to avoid overloading NHT and the process interaction
5472 */
5473 bgp_unlink_nexthop(new);
5474
9bcb3eef 5475 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5476 }
078430f6 5477
d62a17ae 5478 /* Aggregate address increment. */
5479 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5480
d62a17ae 5481 /* Register new BGP information. */
9bcb3eef 5482 bgp_path_info_add(dest, new);
718e3744 5483
d62a17ae 5484 /* route_node_get lock */
9bcb3eef 5485 bgp_dest_unlock_node(dest);
d62a17ae 5486
5487 /* Process change. */
9bcb3eef 5488 bgp_process(bgp, dest, afi, safi);
d62a17ae 5489
ddb5b488
PZ
5490 if (SAFI_UNICAST == safi
5491 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5492 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5493 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5494 }
5495
d62a17ae 5496 /* Unintern original. */
5497 aspath_unintern(&attr.aspath);
718e3744 5498}
5499
5f040085 5500void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5501 safi_t safi)
718e3744 5502{
9bcb3eef 5503 struct bgp_dest *dest;
40381db7 5504 struct bgp_path_info *pi;
718e3744 5505
9bcb3eef 5506 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5507
d62a17ae 5508 /* Check selected route and self inserted route. */
9bcb3eef 5509 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5510 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5511 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5512 break;
5513
5514 /* Withdraw static BGP route from routing table. */
40381db7 5515 if (pi) {
ddb5b488
PZ
5516 if (SAFI_UNICAST == safi
5517 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5518 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5519 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5520 }
40381db7
DS
5521 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5522 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5523 bgp_path_info_delete(dest, pi);
5524 bgp_process(bgp, dest, afi, safi);
d62a17ae 5525 }
718e3744 5526
d62a17ae 5527 /* Unlock bgp_node_lookup. */
9bcb3eef 5528 bgp_dest_unlock_node(dest);
718e3744 5529}
5530
137446f9
LB
5531/*
5532 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5533 */
5f040085 5534static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5535 afi_t afi, safi_t safi,
5536 struct prefix_rd *prd)
718e3744 5537{
9bcb3eef 5538 struct bgp_dest *dest;
40381db7 5539 struct bgp_path_info *pi;
718e3744 5540
9bcb3eef 5541 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5542
d62a17ae 5543 /* Check selected route and self inserted route. */
9bcb3eef 5544 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5545 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5546 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5547 break;
718e3744 5548
d62a17ae 5549 /* Withdraw static BGP route from routing table. */
40381db7 5550 if (pi) {
49e5a4a0 5551#ifdef ENABLE_BGP_VNC
d62a17ae 5552 rfapiProcessWithdraw(
40381db7 5553 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5554 1); /* Kill, since it is an administrative change */
65efcfce 5555#endif
ddb5b488
PZ
5556 if (SAFI_MPLS_VPN == safi
5557 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5558 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5559 }
40381db7 5560 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5561 bgp_path_info_delete(dest, pi);
5562 bgp_process(bgp, dest, afi, safi);
d62a17ae 5563 }
718e3744 5564
d62a17ae 5565 /* Unlock bgp_node_lookup. */
9bcb3eef 5566 bgp_dest_unlock_node(dest);
718e3744 5567}
5568
5f040085 5569static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5570 struct bgp_static *bgp_static, afi_t afi,
5571 safi_t safi)
137446f9 5572{
9bcb3eef 5573 struct bgp_dest *dest;
4b7e6066 5574 struct bgp_path_info *new;
d62a17ae 5575 struct attr *attr_new;
5576 struct attr attr = {0};
40381db7 5577 struct bgp_path_info *pi;
49e5a4a0 5578#ifdef ENABLE_BGP_VNC
d62a17ae 5579 mpls_label_t label = 0;
65efcfce 5580#endif
d7c0a89a 5581 uint32_t num_labels = 0;
d62a17ae 5582 union gw_addr add;
137446f9 5583
d62a17ae 5584 assert(bgp_static);
137446f9 5585
b57ba6d2
MK
5586 if (bgp_static->label != MPLS_INVALID_LABEL)
5587 num_labels = 1;
9bcb3eef
DS
5588 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5589 &bgp_static->prd);
137446f9 5590
d62a17ae 5591 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5592
d62a17ae 5593 attr.nexthop = bgp_static->igpnexthop;
5594 attr.med = bgp_static->igpmetric;
5595 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5596
d62a17ae 5597 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5598 || (safi == SAFI_ENCAP)) {
5599 if (afi == AFI_IP) {
5600 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5601 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5602 }
5603 }
5604 if (afi == AFI_L2VPN) {
5605 if (bgp_static->gatewayIp.family == AF_INET)
5606 add.ipv4.s_addr =
5607 bgp_static->gatewayIp.u.prefix4.s_addr;
5608 else if (bgp_static->gatewayIp.family == AF_INET6)
5609 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5610 sizeof(struct in6_addr));
0a50c248 5611 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5612 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5613 struct bgp_encap_type_vxlan bet;
5614 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5615 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5616 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5617 }
5618 if (bgp_static->router_mac) {
5619 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5620 }
5621 }
5622 /* Apply route-map. */
5623 if (bgp_static->rmap.name) {
5624 struct attr attr_tmp = attr;
40381db7 5625 struct bgp_path_info rmap_path;
b68885f9 5626 route_map_result_t ret;
137446f9 5627
40381db7
DS
5628 rmap_path.peer = bgp->peer_self;
5629 rmap_path.attr = &attr_tmp;
137446f9 5630
d62a17ae 5631 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5632
1782514f 5633 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5634
d62a17ae 5635 bgp->peer_self->rmap_type = 0;
137446f9 5636
d62a17ae 5637 if (ret == RMAP_DENYMATCH) {
5638 /* Free uninterned attribute. */
5639 bgp_attr_flush(&attr_tmp);
137446f9 5640
d62a17ae 5641 /* Unintern original. */
5642 aspath_unintern(&attr.aspath);
5643 bgp_static_withdraw_safi(bgp, p, afi, safi,
5644 &bgp_static->prd);
5645 return;
5646 }
137446f9 5647
d62a17ae 5648 attr_new = bgp_attr_intern(&attr_tmp);
5649 } else {
5650 attr_new = bgp_attr_intern(&attr);
5651 }
137446f9 5652
9bcb3eef 5653 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5654 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5655 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5656 break;
5657
40381db7 5658 if (pi) {
d62a17ae 5659 memset(&add, 0, sizeof(union gw_addr));
40381db7 5660 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5661 && overlay_index_equal(afi, pi, &add)
40381db7 5662 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5663 bgp_dest_unlock_node(dest);
d62a17ae 5664 bgp_attr_unintern(&attr_new);
5665 aspath_unintern(&attr.aspath);
5666 return;
5667 } else {
5668 /* The attribute is changed. */
9bcb3eef 5669 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5670
5671 /* Rewrite BGP route information. */
40381db7 5672 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5673 bgp_path_info_restore(dest, pi);
d62a17ae 5674 else
40381db7
DS
5675 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5676 bgp_attr_unintern(&pi->attr);
5677 pi->attr = attr_new;
5678 pi->uptime = bgp_clock();
49e5a4a0 5679#ifdef ENABLE_BGP_VNC
40381db7
DS
5680 if (pi->extra)
5681 label = decode_label(&pi->extra->label[0]);
65efcfce 5682#endif
137446f9 5683
d62a17ae 5684 /* Process change. */
40381db7 5685 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5686 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5687
5688 if (SAFI_MPLS_VPN == safi
5689 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5690 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5691 }
49e5a4a0 5692#ifdef ENABLE_BGP_VNC
40381db7
DS
5693 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5694 pi->attr, afi, safi, pi->type,
5695 pi->sub_type, &label);
65efcfce 5696#endif
9bcb3eef 5697 bgp_dest_unlock_node(dest);
d62a17ae 5698 aspath_unintern(&attr.aspath);
5699 return;
5700 }
5701 }
137446f9
LB
5702
5703
d62a17ae 5704 /* Make new BGP info. */
5705 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5706 attr_new, dest);
1defdda8 5707 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5708 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5709 if (num_labels) {
5710 new->extra->label[0] = bgp_static->label;
5711 new->extra->num_labels = num_labels;
5712 }
49e5a4a0 5713#ifdef ENABLE_BGP_VNC
d62a17ae 5714 label = decode_label(&bgp_static->label);
65efcfce 5715#endif
137446f9 5716
d62a17ae 5717 /* Aggregate address increment. */
5718 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5719
d62a17ae 5720 /* Register new BGP information. */
9bcb3eef 5721 bgp_path_info_add(dest, new);
d62a17ae 5722 /* route_node_get lock */
9bcb3eef 5723 bgp_dest_unlock_node(dest);
137446f9 5724
d62a17ae 5725 /* Process change. */
9bcb3eef 5726 bgp_process(bgp, dest, afi, safi);
137446f9 5727
ddb5b488
PZ
5728 if (SAFI_MPLS_VPN == safi
5729 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5730 vpn_leak_to_vrf_update(bgp, new);
5731 }
49e5a4a0 5732#ifdef ENABLE_BGP_VNC
d62a17ae 5733 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5734 safi, new->type, new->sub_type, &label);
65efcfce
LB
5735#endif
5736
d62a17ae 5737 /* Unintern original. */
5738 aspath_unintern(&attr.aspath);
137446f9
LB
5739}
5740
718e3744 5741/* Configure static BGP network. When user don't run zebra, static
5742 route should be installed as valid. */
37a87b8f
CS
5743int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5744 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5745 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5746{
d62a17ae 5747 struct prefix p;
5748 struct bgp_static *bgp_static;
9bcb3eef 5749 struct bgp_dest *dest;
d7c0a89a 5750 uint8_t need_update = 0;
d62a17ae 5751
37a87b8f 5752 prefix_copy(&p, pfx);
d62a17ae 5753 apply_mask(&p);
718e3744 5754
e2a86ad9 5755 if (negate) {
718e3744 5756
e2a86ad9 5757 /* Set BGP static route configuration. */
9bcb3eef 5758 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5759
9bcb3eef 5760 if (!dest) {
37a87b8f
CS
5761 snprintf(errmsg, errmsg_len,
5762 "Can't find static route specified\n");
5763 return -1;
d62a17ae 5764 }
5765
9bcb3eef 5766 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5767
e2a86ad9
DS
5768 if ((label_index != BGP_INVALID_LABEL_INDEX)
5769 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5770 snprintf(errmsg, errmsg_len,
5771 "label-index doesn't match static route\n");
5772 return -1;
d62a17ae 5773 }
d62a17ae 5774
e2a86ad9
DS
5775 if ((rmap && bgp_static->rmap.name)
5776 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5777 snprintf(errmsg, errmsg_len,
5778 "route-map name doesn't match static route\n");
5779 return -1;
d62a17ae 5780 }
718e3744 5781
e2a86ad9
DS
5782 /* Update BGP RIB. */
5783 if (!bgp_static->backdoor)
5784 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5785
e2a86ad9
DS
5786 /* Clear configuration. */
5787 bgp_static_free(bgp_static);
9bcb3eef
DS
5788 bgp_dest_set_bgp_static_info(dest, NULL);
5789 bgp_dest_unlock_node(dest);
5790 bgp_dest_unlock_node(dest);
e2a86ad9 5791 } else {
718e3744 5792
e2a86ad9 5793 /* Set BGP static route configuration. */
9bcb3eef
DS
5794 dest = bgp_node_get(bgp->route[afi][safi], &p);
5795 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5796 if (bgp_static) {
e2a86ad9 5797 /* Configuration change. */
e2a86ad9
DS
5798 /* Label index cannot be changed. */
5799 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5800 snprintf(errmsg, errmsg_len,
5801 "cannot change label-index\n");
5802 return -1;
e2a86ad9 5803 }
d62a17ae 5804
e2a86ad9 5805 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5806 if (bgp_static->valid
5807 && bgp_static->backdoor != backdoor)
e2a86ad9 5808 need_update = 1;
718e3744 5809
e2a86ad9 5810 bgp_static->backdoor = backdoor;
718e3744 5811
e2a86ad9 5812 if (rmap) {
0a22ddfb
QY
5813 XFREE(MTYPE_ROUTE_MAP_NAME,
5814 bgp_static->rmap.name);
b4897fa5 5815 route_map_counter_decrement(
5816 bgp_static->rmap.map);
e2a86ad9
DS
5817 bgp_static->rmap.name =
5818 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5819 bgp_static->rmap.map =
5820 route_map_lookup_by_name(rmap);
b4897fa5 5821 route_map_counter_increment(
5822 bgp_static->rmap.map);
e2a86ad9 5823 } else {
0a22ddfb
QY
5824 XFREE(MTYPE_ROUTE_MAP_NAME,
5825 bgp_static->rmap.name);
b4897fa5 5826 route_map_counter_decrement(
5827 bgp_static->rmap.map);
e2a86ad9
DS
5828 bgp_static->rmap.map = NULL;
5829 bgp_static->valid = 0;
5830 }
9bcb3eef 5831 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5832 } else {
5833 /* New configuration. */
5834 bgp_static = bgp_static_new();
5835 bgp_static->backdoor = backdoor;
5836 bgp_static->valid = 0;
5837 bgp_static->igpmetric = 0;
975a328e 5838 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5839 bgp_static->label_index = label_index;
718e3744 5840
e2a86ad9 5841 if (rmap) {
0a22ddfb
QY
5842 XFREE(MTYPE_ROUTE_MAP_NAME,
5843 bgp_static->rmap.name);
b4897fa5 5844 route_map_counter_decrement(
5845 bgp_static->rmap.map);
e2a86ad9
DS
5846 bgp_static->rmap.name =
5847 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5848 bgp_static->rmap.map =
5849 route_map_lookup_by_name(rmap);
b4897fa5 5850 route_map_counter_increment(
5851 bgp_static->rmap.map);
e2a86ad9 5852 }
9bcb3eef 5853 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5854 }
d62a17ae 5855
e2a86ad9
DS
5856 bgp_static->valid = 1;
5857 if (need_update)
5858 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5859
e2a86ad9
DS
5860 if (!bgp_static->backdoor)
5861 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5862 }
d62a17ae 5863
37a87b8f 5864 return 0;
d62a17ae 5865}
5866
5867void bgp_static_add(struct bgp *bgp)
5868{
5869 afi_t afi;
5870 safi_t safi;
9bcb3eef
DS
5871 struct bgp_dest *dest;
5872 struct bgp_dest *rm;
d62a17ae 5873 struct bgp_table *table;
5874 struct bgp_static *bgp_static;
5875
05c7a1cc 5876 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5877 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5878 dest = bgp_route_next(dest)) {
5879 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5880 continue;
ea47320b 5881
05c7a1cc
QY
5882 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5883 || (safi == SAFI_EVPN)) {
9bcb3eef 5884 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5885
5886 for (rm = bgp_table_top(table); rm;
5887 rm = bgp_route_next(rm)) {
a78beeb5 5888 bgp_static =
9bcb3eef 5889 bgp_dest_get_bgp_static_info(
5a8ba9fc 5890 rm);
9bcb3eef
DS
5891 bgp_static_update_safi(
5892 bgp, bgp_dest_get_prefix(rm),
5893 bgp_static, afi, safi);
d62a17ae 5894 }
05c7a1cc 5895 } else {
5a8ba9fc 5896 bgp_static_update(
9bcb3eef
DS
5897 bgp, bgp_dest_get_prefix(dest),
5898 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5899 safi);
ea47320b 5900 }
05c7a1cc 5901 }
6aeb9e78
DS
5902}
5903
718e3744 5904/* Called from bgp_delete(). Delete all static routes from the BGP
5905 instance. */
d62a17ae 5906void bgp_static_delete(struct bgp *bgp)
5907{
5908 afi_t afi;
5909 safi_t safi;
9bcb3eef
DS
5910 struct bgp_dest *dest;
5911 struct bgp_dest *rm;
d62a17ae 5912 struct bgp_table *table;
5913 struct bgp_static *bgp_static;
5914
05c7a1cc 5915 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5916 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5917 dest = bgp_route_next(dest)) {
5918 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5919 continue;
ea47320b 5920
05c7a1cc
QY
5921 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5922 || (safi == SAFI_EVPN)) {
9bcb3eef 5923 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5924
5925 for (rm = bgp_table_top(table); rm;
5926 rm = bgp_route_next(rm)) {
a78beeb5 5927 bgp_static =
9bcb3eef 5928 bgp_dest_get_bgp_static_info(
5a8ba9fc 5929 rm);
c7d14ba6
PG
5930 if (!bgp_static)
5931 continue;
5932
05c7a1cc 5933 bgp_static_withdraw_safi(
9bcb3eef 5934 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5935 AFI_IP, safi,
5936 (struct prefix_rd *)
9bcb3eef
DS
5937 bgp_dest_get_prefix(
5938 dest));
ea47320b 5939 bgp_static_free(bgp_static);
811c6797 5940 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5941 NULL);
811c6797 5942 bgp_dest_unlock_node(rm);
d62a17ae 5943 }
05c7a1cc 5944 } else {
9bcb3eef 5945 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5946 bgp_static_withdraw(bgp,
9bcb3eef 5947 bgp_dest_get_prefix(dest),
b54892e0 5948 afi, safi);
05c7a1cc 5949 bgp_static_free(bgp_static);
9bcb3eef
DS
5950 bgp_dest_set_bgp_static_info(dest, NULL);
5951 bgp_dest_unlock_node(dest);
ea47320b 5952 }
05c7a1cc 5953 }
d62a17ae 5954}
5955
5956void bgp_static_redo_import_check(struct bgp *bgp)
5957{
5958 afi_t afi;
5959 safi_t safi;
9bcb3eef
DS
5960 struct bgp_dest *dest;
5961 struct bgp_dest *rm;
d62a17ae 5962 struct bgp_table *table;
5963 struct bgp_static *bgp_static;
5964
5965 /* Use this flag to force reprocessing of the route */
892fedb6 5966 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5967 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5968 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5969 dest = bgp_route_next(dest)) {
5970 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5971 continue;
ea47320b 5972
05c7a1cc
QY
5973 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5974 || (safi == SAFI_EVPN)) {
9bcb3eef 5975 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5976
5977 for (rm = bgp_table_top(table); rm;
5978 rm = bgp_route_next(rm)) {
a78beeb5 5979 bgp_static =
9bcb3eef 5980 bgp_dest_get_bgp_static_info(
5a8ba9fc 5981 rm);
9bcb3eef
DS
5982 bgp_static_update_safi(
5983 bgp, bgp_dest_get_prefix(rm),
5984 bgp_static, afi, safi);
d62a17ae 5985 }
05c7a1cc 5986 } else {
9bcb3eef
DS
5987 bgp_static = bgp_dest_get_bgp_static_info(dest);
5988 bgp_static_update(bgp,
5989 bgp_dest_get_prefix(dest),
5990 bgp_static, afi, safi);
ea47320b 5991 }
05c7a1cc
QY
5992 }
5993 }
892fedb6 5994 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5995}
5996
5997static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5998 safi_t safi)
5999{
6000 struct bgp_table *table;
9bcb3eef 6001 struct bgp_dest *dest;
40381db7 6002 struct bgp_path_info *pi;
d62a17ae 6003
dfb6fd1d
NT
6004 /* Do not install the aggregate route if BGP is in the
6005 * process of termination.
6006 */
892fedb6
DA
6007 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6008 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6009 return;
6010
d62a17ae 6011 table = bgp->rib[afi][safi];
9bcb3eef
DS
6012 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6013 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6014 if (pi->peer == bgp->peer_self
6015 && ((pi->type == ZEBRA_ROUTE_BGP
6016 && pi->sub_type == BGP_ROUTE_STATIC)
6017 || (pi->type != ZEBRA_ROUTE_BGP
6018 && pi->sub_type
d62a17ae 6019 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6020 bgp_aggregate_decrement(
6021 bgp, bgp_dest_get_prefix(dest), pi, afi,
6022 safi);
40381db7 6023 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6024 bgp_path_info_delete(dest, pi);
6025 bgp_process(bgp, dest, afi, safi);
d62a17ae 6026 }
6027 }
6028 }
ad4cbda1 6029}
6030
6031/*
6032 * Purge all networks and redistributed routes from routing table.
6033 * Invoked upon the instance going down.
6034 */
d62a17ae 6035void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6036{
d62a17ae 6037 afi_t afi;
6038 safi_t safi;
ad4cbda1 6039
05c7a1cc
QY
6040 FOREACH_AFI_SAFI (afi, safi)
6041 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6042}
6043
137446f9
LB
6044/*
6045 * gpz 110624
6046 * Currently this is used to set static routes for VPN and ENCAP.
6047 * I think it can probably be factored with bgp_static_set.
6048 */
d62a17ae 6049int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6050 const char *ip_str, const char *rd_str,
6051 const char *label_str, const char *rmap_str,
6052 int evpn_type, const char *esi, const char *gwip,
6053 const char *ethtag, const char *routermac)
6054{
6055 VTY_DECLVAR_CONTEXT(bgp, bgp);
6056 int ret;
6057 struct prefix p;
6058 struct prefix_rd prd;
9bcb3eef
DS
6059 struct bgp_dest *pdest;
6060 struct bgp_dest *dest;
d62a17ae 6061 struct bgp_table *table;
6062 struct bgp_static *bgp_static;
6063 mpls_label_t label = MPLS_INVALID_LABEL;
6064 struct prefix gw_ip;
6065
6066 /* validate ip prefix */
6067 ret = str2prefix(ip_str, &p);
6068 if (!ret) {
6069 vty_out(vty, "%% Malformed prefix\n");
6070 return CMD_WARNING_CONFIG_FAILED;
6071 }
6072 apply_mask(&p);
6073 if ((afi == AFI_L2VPN)
6074 && (bgp_build_evpn_prefix(evpn_type,
6075 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6076 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6077 return CMD_WARNING_CONFIG_FAILED;
6078 }
718e3744 6079
d62a17ae 6080 ret = str2prefix_rd(rd_str, &prd);
6081 if (!ret) {
6082 vty_out(vty, "%% Malformed rd\n");
6083 return CMD_WARNING_CONFIG_FAILED;
6084 }
718e3744 6085
d62a17ae 6086 if (label_str) {
6087 unsigned long label_val;
6088 label_val = strtoul(label_str, NULL, 10);
6089 encode_label(label_val, &label);
6090 }
9bedbb1e 6091
d62a17ae 6092 if (safi == SAFI_EVPN) {
6093 if (esi && str2esi(esi, NULL) == 0) {
6094 vty_out(vty, "%% Malformed ESI\n");
6095 return CMD_WARNING_CONFIG_FAILED;
6096 }
6097 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6098 vty_out(vty, "%% Malformed Router MAC\n");
6099 return CMD_WARNING_CONFIG_FAILED;
6100 }
6101 if (gwip) {
6102 memset(&gw_ip, 0, sizeof(struct prefix));
6103 ret = str2prefix(gwip, &gw_ip);
6104 if (!ret) {
6105 vty_out(vty, "%% Malformed GatewayIp\n");
6106 return CMD_WARNING_CONFIG_FAILED;
6107 }
6108 if ((gw_ip.family == AF_INET
3714a385 6109 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6110 (struct prefix_evpn *)&p))
6111 || (gw_ip.family == AF_INET6
3714a385 6112 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6113 (struct prefix_evpn *)&p))) {
6114 vty_out(vty,
6115 "%% GatewayIp family differs with IP prefix\n");
6116 return CMD_WARNING_CONFIG_FAILED;
6117 }
6118 }
6119 }
9bcb3eef
DS
6120 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6121 if (!bgp_dest_has_bgp_path_info_data(pdest))
6122 bgp_dest_set_bgp_table_info(pdest,
67009e22 6123 bgp_table_init(bgp, afi, safi));
9bcb3eef 6124 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6125
9bcb3eef 6126 dest = bgp_node_get(table, &p);
d62a17ae 6127
9bcb3eef 6128 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6129 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6130 bgp_dest_unlock_node(dest);
d62a17ae 6131 } else {
6132 /* New configuration. */
6133 bgp_static = bgp_static_new();
6134 bgp_static->backdoor = 0;
6135 bgp_static->valid = 0;
6136 bgp_static->igpmetric = 0;
975a328e 6137 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6138 bgp_static->label = label;
6139 bgp_static->prd = prd;
6140
6141 if (rmap_str) {
0a22ddfb 6142 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6143 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6144 bgp_static->rmap.name =
6145 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6146 bgp_static->rmap.map =
6147 route_map_lookup_by_name(rmap_str);
b4897fa5 6148 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6149 }
718e3744 6150
d62a17ae 6151 if (safi == SAFI_EVPN) {
6152 if (esi) {
6153 bgp_static->eth_s_id =
6154 XCALLOC(MTYPE_ATTR,
0a50c248 6155 sizeof(esi_t));
d62a17ae 6156 str2esi(esi, bgp_static->eth_s_id);
6157 }
6158 if (routermac) {
6159 bgp_static->router_mac =
28328ea9 6160 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6161 (void)prefix_str2mac(routermac,
6162 bgp_static->router_mac);
d62a17ae 6163 }
6164 if (gwip)
6165 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6166 }
9bcb3eef 6167 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6168
d62a17ae 6169 bgp_static->valid = 1;
6170 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6171 }
718e3744 6172
d62a17ae 6173 return CMD_SUCCESS;
718e3744 6174}
6175
6176/* Configure static BGP network. */
d62a17ae 6177int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6178 const char *ip_str, const char *rd_str,
6179 const char *label_str, int evpn_type, const char *esi,
6180 const char *gwip, const char *ethtag)
6181{
6182 VTY_DECLVAR_CONTEXT(bgp, bgp);
6183 int ret;
6184 struct prefix p;
6185 struct prefix_rd prd;
9bcb3eef
DS
6186 struct bgp_dest *pdest;
6187 struct bgp_dest *dest;
d62a17ae 6188 struct bgp_table *table;
6189 struct bgp_static *bgp_static;
6190 mpls_label_t label = MPLS_INVALID_LABEL;
6191
6192 /* Convert IP prefix string to struct prefix. */
6193 ret = str2prefix(ip_str, &p);
6194 if (!ret) {
6195 vty_out(vty, "%% Malformed prefix\n");
6196 return CMD_WARNING_CONFIG_FAILED;
6197 }
6198 apply_mask(&p);
6199 if ((afi == AFI_L2VPN)
6200 && (bgp_build_evpn_prefix(evpn_type,
6201 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6202 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6203 return CMD_WARNING_CONFIG_FAILED;
6204 }
6205 ret = str2prefix_rd(rd_str, &prd);
6206 if (!ret) {
6207 vty_out(vty, "%% Malformed rd\n");
6208 return CMD_WARNING_CONFIG_FAILED;
6209 }
718e3744 6210
d62a17ae 6211 if (label_str) {
6212 unsigned long label_val;
6213 label_val = strtoul(label_str, NULL, 10);
6214 encode_label(label_val, &label);
6215 }
718e3744 6216
9bcb3eef
DS
6217 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6218 if (!bgp_dest_has_bgp_path_info_data(pdest))
6219 bgp_dest_set_bgp_table_info(pdest,
67009e22 6220 bgp_table_init(bgp, afi, safi));
d62a17ae 6221 else
9bcb3eef
DS
6222 bgp_dest_unlock_node(pdest);
6223 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6224
9bcb3eef 6225 dest = bgp_node_lookup(table, &p);
6b0655a2 6226
9bcb3eef 6227 if (dest) {
d62a17ae 6228 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6229
9bcb3eef 6230 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6231 bgp_static_free(bgp_static);
9bcb3eef
DS
6232 bgp_dest_set_bgp_static_info(dest, NULL);
6233 bgp_dest_unlock_node(dest);
6234 bgp_dest_unlock_node(dest);
d62a17ae 6235 } else
6236 vty_out(vty, "%% Can't find the route\n");
6237
6238 return CMD_SUCCESS;
6239}
6240
6241static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6242 const char *rmap_name)
6243{
6244 VTY_DECLVAR_CONTEXT(bgp, bgp);
6245 struct bgp_rmap *rmap;
6246
6247 rmap = &bgp->table_map[afi][safi];
6248 if (rmap_name) {
0a22ddfb 6249 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6250 route_map_counter_decrement(rmap->map);
d62a17ae 6251 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6252 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6253 route_map_counter_increment(rmap->map);
d62a17ae 6254 } else {
0a22ddfb 6255 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6256 route_map_counter_decrement(rmap->map);
d62a17ae 6257 rmap->map = NULL;
6258 }
73ac8160 6259
d62a17ae 6260 if (bgp_fibupd_safi(safi))
6261 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6262
d62a17ae 6263 return CMD_SUCCESS;
73ac8160
DS
6264}
6265
d62a17ae 6266static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6267 const char *rmap_name)
73ac8160 6268{
d62a17ae 6269 VTY_DECLVAR_CONTEXT(bgp, bgp);
6270 struct bgp_rmap *rmap;
73ac8160 6271
d62a17ae 6272 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6273 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6274 route_map_counter_decrement(rmap->map);
d62a17ae 6275 rmap->map = NULL;
73ac8160 6276
d62a17ae 6277 if (bgp_fibupd_safi(safi))
6278 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6279
d62a17ae 6280 return CMD_SUCCESS;
73ac8160
DS
6281}
6282
2b791107 6283void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6284 safi_t safi)
73ac8160 6285{
d62a17ae 6286 if (bgp->table_map[afi][safi].name) {
d62a17ae 6287 vty_out(vty, " table-map %s\n",
6288 bgp->table_map[afi][safi].name);
6289 }
73ac8160
DS
6290}
6291
73ac8160
DS
6292DEFUN (bgp_table_map,
6293 bgp_table_map_cmd,
6294 "table-map WORD",
6295 "BGP table to RIB route download filter\n"
6296 "Name of the route map\n")
6297{
d62a17ae 6298 int idx_word = 1;
6299 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6300 argv[idx_word]->arg);
73ac8160
DS
6301}
6302DEFUN (no_bgp_table_map,
6303 no_bgp_table_map_cmd,
6304 "no table-map WORD",
3a2d747c 6305 NO_STR
73ac8160
DS
6306 "BGP table to RIB route download filter\n"
6307 "Name of the route map\n")
6308{
d62a17ae 6309 int idx_word = 2;
6310 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6311 argv[idx_word]->arg);
73ac8160
DS
6312}
6313
37a87b8f
CS
6314DEFPY_YANG (bgp_network, bgp_network_cmd,
6315 "[no] network \
6316 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6317 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6318 backdoor$backdoor}]",
6319 NO_STR
6320 "Specify a network to announce via BGP\n"
6321 "IPv4 prefix\n"
6322 "Network number\n"
6323 "Network mask\n"
6324 "Network mask\n"
6325 "Route-map to modify the attributes\n"
6326 "Name of the route map\n"
6327 "Label index to associate with the prefix\n"
6328 "Label index value\n"
6329 "Specify a BGP backdoor route\n")
6330{
6331 char addr_prefix_str[PREFIX_STRLEN];
6332 char base_xpath[XPATH_MAXLEN];
6333 afi_t afi;
6334 safi_t safi;
e2a86ad9
DS
6335
6336 if (address_str) {
6337 int ret;
718e3744 6338
e2a86ad9
DS
6339 ret = netmask_str2prefix_str(address_str, netmask_str,
6340 addr_prefix_str);
6341 if (!ret) {
6342 vty_out(vty, "%% Inconsistent address and mask\n");
6343 return CMD_WARNING_CONFIG_FAILED;
6344 }
d62a17ae 6345 }
718e3744 6346
37a87b8f
CS
6347 afi = bgp_node_afi(vty);
6348 safi = bgp_node_safi(vty);
6349
6350 if (no) {
6351 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6352 } else {
6353 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6354
6355 if (map_name)
6356 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6357 NB_OP_CREATE, map_name);
6358 else
6359 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6360 NB_OP_DESTROY, NULL);
6361
6362 if (label_index_str)
6363 nb_cli_enqueue_change(vty, "./label-index",
6364 NB_OP_MODIFY, label_index_str);
6365
6366 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6367 backdoor ? "true" : "false");
6368 }
6369
6370 snprintf(
6371 base_xpath, sizeof(base_xpath),
6372 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6373 yang_afi_safi_value2identity(afi, safi),
6374 bgp_afi_safi_get_container_str(afi, safi),
6375 address_str ? addr_prefix_str : prefix_str);
6376
6377 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6378}
6379
37a87b8f
CS
6380DEFPY_YANG (ipv6_bgp_network,
6381 ipv6_bgp_network_cmd,
6382 "[no] network X:X::X:X/M$prefix \
6383 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6384 NO_STR
6385 "Specify a network to announce via BGP\n"
6386 "IPv6 prefix\n"
6387 "Route-map to modify the attributes\n"
6388 "Name of the route map\n"
6389 "Label index to associate with the prefix\n"
6390 "Label index value\n")
6391{
6392 char base_xpath[XPATH_MAXLEN];
6393 afi_t afi;
6394 safi_t safi;
6395
6396 afi = bgp_node_afi(vty);
6397 safi = bgp_node_safi(vty);
6398
6399 if (no) {
6400 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6401 } else {
6402 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6403
6404 if (map_name)
6405 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6406 NB_OP_MODIFY, map_name);
6407 else
6408 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6409 NB_OP_DESTROY, NULL);
6410
6411 if (label_index_str)
6412 nb_cli_enqueue_change(vty, "./label-index",
6413 NB_OP_MODIFY, label_index_str);
6414 }
6415
6416 snprintf(
6417 base_xpath, sizeof(base_xpath),
6418 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6419 yang_afi_safi_value2identity(afi, safi),
6420 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6421
6422 return nb_cli_apply_changes(vty, base_xpath);
6423}
6424
6425void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6426 struct lyd_node *dnode,
6427 bool show_defaults)
718e3744 6428{
37a87b8f
CS
6429 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6430
6431 if (yang_dnode_exists(dnode, "./label-index"))
6432 vty_out(vty, " label-index %s",
6433 yang_dnode_get_string(dnode, "./label-index"));
6434
6435 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6436 vty_out(vty, " route-map %s",
6437 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6438
6439 if (yang_dnode_get_bool(dnode, "./backdoor"))
6440 vty_out(vty, " backdoor");
6441
6442 vty_out(vty, "\n");
1b6d5c7e
VV
6443}
6444
d62a17ae 6445static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6446{
d62a17ae 6447 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6448}
6449
d62a17ae 6450static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6451{
365ab2e7
RZ
6452 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6453 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6454 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6455 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6456 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6457}
718e3744 6458
365ab2e7
RZ
6459/**
6460 * Helper function to avoid repeated code: prepare variables for a
6461 * `route_map_apply` call.
6462 *
6463 * \returns `true` on route map match, otherwise `false`.
6464 */
6465static bool aggr_suppress_map_test(struct bgp *bgp,
6466 struct bgp_aggregate *aggregate,
6467 struct bgp_path_info *pi)
6468{
6469 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6470 route_map_result_t rmr = RMAP_DENYMATCH;
6471 struct bgp_path_info rmap_path = {};
6472 struct attr attr = {};
6473
6474 /* No route map entries created, just don't match. */
6475 if (aggregate->suppress_map == NULL)
6476 return false;
6477
6478 /* Call route map matching and return result. */
6479 attr.aspath = aspath_empty();
6480 rmap_path.peer = bgp->peer_self;
6481 rmap_path.attr = &attr;
6482
6483 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6484 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6485 bgp->peer_self->rmap_type = 0;
6486
6487 bgp_attr_flush(&attr);
6488
6489 return rmr == RMAP_PERMITMATCH;
6490}
6491
4056a5f6
RZ
6492/** Test whether the aggregation has suppressed this path or not. */
6493static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6494 struct bgp_path_info *pi)
6495{
6496 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6497 return false;
6498
6499 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6500}
6501
6502/**
6503 * Suppress this path and keep the reference.
6504 *
6505 * \returns `true` if needs processing otherwise `false`.
6506 */
6507static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6508 struct bgp_path_info *pi)
6509{
6510 struct bgp_path_info_extra *pie;
6511
6512 /* Path is already suppressed by this aggregation. */
6513 if (aggr_suppress_exists(aggregate, pi))
6514 return false;
6515
6516 pie = bgp_path_info_extra_get(pi);
6517
6518 /* This is the first suppression, allocate memory and list it. */
6519 if (pie->aggr_suppressors == NULL)
6520 pie->aggr_suppressors = list_new();
6521
6522 listnode_add(pie->aggr_suppressors, aggregate);
6523
6524 /* Only mark for processing if suppressed. */
6525 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6526 if (BGP_DEBUG(update, UPDATE_OUT))
6527 zlog_debug("aggregate-address suppressing: %pFX",
6528 bgp_dest_get_prefix(pi->net));
6529
4056a5f6
RZ
6530 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6531 return true;
6532 }
6533
6534 return false;
6535}
6536
6537/**
6538 * Unsuppress this path and remove the reference.
6539 *
6540 * \returns `true` if needs processing otherwise `false`.
6541 */
6542static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6543 struct bgp_path_info *pi)
6544{
6545 /* Path wasn't suppressed. */
6546 if (!aggr_suppress_exists(aggregate, pi))
6547 return false;
6548
6549 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6550
6551 /* Unsuppress and free extra memory if last item. */
6552 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6553 if (BGP_DEBUG(update, UPDATE_OUT))
6554 zlog_debug("aggregate-address unsuppressing: %pFX",
6555 bgp_dest_get_prefix(pi->net));
6556
4056a5f6
RZ
6557 list_delete(&pi->extra->aggr_suppressors);
6558 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6559 return true;
6560 }
6561
6562 return false;
6563}
6564
3dc339cd
DA
6565static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6566 struct aspath *aspath,
6567 struct community *comm,
6568 struct ecommunity *ecomm,
6569 struct lcommunity *lcomm)
eaaf8adb
DS
6570{
6571 static struct aspath *ae = NULL;
6572
6573 if (!ae)
6574 ae = aspath_empty();
6575
40381db7 6576 if (!pi)
3dc339cd 6577 return false;
eaaf8adb 6578
40381db7 6579 if (origin != pi->attr->origin)
3dc339cd 6580 return false;
eaaf8adb 6581
40381db7 6582 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6583 return false;
29f7d023 6584
40381db7 6585 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6586 return false;
eaaf8adb 6587
3da2cc32 6588 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6589 return false;
eaaf8adb 6590
dd18c5a9 6591 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6592 return false;
dd18c5a9 6593
40381db7 6594 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6595 return false;
7ce8a8e0 6596
3dc339cd 6597 return true;
eaaf8adb
DS
6598}
6599
5f040085
DS
6600static void bgp_aggregate_install(
6601 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6602 uint8_t origin, struct aspath *aspath, struct community *community,
6603 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6604 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6605{
9bcb3eef 6606 struct bgp_dest *dest;
c701010e 6607 struct bgp_table *table;
6f94b685 6608 struct bgp_path_info *pi, *orig, *new;
20894f50 6609 struct attr *attr;
c701010e
DS
6610
6611 table = bgp->rib[afi][safi];
6612
9bcb3eef 6613 dest = bgp_node_get(table, p);
eaaf8adb 6614
9bcb3eef 6615 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6616 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6617 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6618 break;
6619
6aabb15d
RZ
6620 /*
6621 * If we have paths with different MEDs, then don't install
6622 * (or uninstall) the aggregate route.
6623 */
6624 if (aggregate->match_med && aggregate->med_mismatched)
6625 goto uninstall_aggregate_route;
6626
c701010e 6627 if (aggregate->count > 0) {
eaaf8adb
DS
6628 /*
6629 * If the aggregate information has not changed
6630 * no need to re-install it again.
6631 */
6f94b685 6632 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6633 ecommunity, lcommunity)) {
9bcb3eef 6634 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6635
6636 if (aspath)
6637 aspath_free(aspath);
6638 if (community)
3c1f53de 6639 community_free(&community);
3da2cc32
DS
6640 if (ecommunity)
6641 ecommunity_free(&ecommunity);
dd18c5a9
DS
6642 if (lcommunity)
6643 lcommunity_free(&lcommunity);
eaaf8adb
DS
6644
6645 return;
6646 }
6647
6648 /*
6649 * Mark the old as unusable
6650 */
40381db7 6651 if (pi)
9bcb3eef 6652 bgp_path_info_delete(dest, pi);
eaaf8adb 6653
20894f50
DA
6654 attr = bgp_attr_aggregate_intern(
6655 bgp, origin, aspath, community, ecommunity, lcommunity,
6656 aggregate, atomic_aggregate, p);
6657
6658 if (!attr) {
6659 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6660 return;
6661 }
6662
3da2cc32 6663 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6664 bgp->peer_self, attr, dest);
20894f50 6665
1defdda8 6666 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6667
9bcb3eef
DS
6668 bgp_path_info_add(dest, new);
6669 bgp_process(bgp, dest, afi, safi);
c701010e 6670 } else {
6aabb15d 6671 uninstall_aggregate_route:
6f94b685 6672 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6673 if (pi->peer == bgp->peer_self
6674 && pi->type == ZEBRA_ROUTE_BGP
6675 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6676 break;
6677
6678 /* Withdraw static BGP route from routing table. */
40381db7 6679 if (pi) {
9bcb3eef
DS
6680 bgp_path_info_delete(dest, pi);
6681 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6682 }
6683 }
6684
9bcb3eef 6685 bgp_dest_unlock_node(dest);
c701010e
DS
6686}
6687
6aabb15d
RZ
6688/**
6689 * Check if the current path has different MED than other known paths.
6690 *
6691 * \returns `true` if the MED matched the others else `false`.
6692 */
6693static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6694 struct bgp *bgp, struct bgp_path_info *pi)
6695{
6696 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6697
6698 /* This is the first route being analyzed. */
6699 if (!aggregate->med_initialized) {
6700 aggregate->med_initialized = true;
6701 aggregate->med_mismatched = false;
6702 aggregate->med_matched_value = cur_med;
6703 } else {
6704 /* Check if routes with different MED showed up. */
6705 if (cur_med != aggregate->med_matched_value)
6706 aggregate->med_mismatched = true;
6707 }
6708
6709 return !aggregate->med_mismatched;
6710}
6711
6712/**
6713 * Initializes and tests all routes in the aggregate address path for MED
6714 * values.
6715 *
6716 * \returns `true` if all MEDs are the same otherwise `false`.
6717 */
6718static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6719 struct bgp *bgp, const struct prefix *p,
6720 afi_t afi, safi_t safi)
6721{
6722 struct bgp_table *table = bgp->rib[afi][safi];
6723 const struct prefix *dest_p;
6724 struct bgp_dest *dest, *top;
6725 struct bgp_path_info *pi;
6726 bool med_matched = true;
6727
6728 aggregate->med_initialized = false;
6729
6730 top = bgp_node_get(table, p);
6731 for (dest = bgp_node_get(table, p); dest;
6732 dest = bgp_route_next_until(dest, top)) {
6733 dest_p = bgp_dest_get_prefix(dest);
6734 if (dest_p->prefixlen <= p->prefixlen)
6735 continue;
6736
6737 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6738 if (BGP_PATH_HOLDDOWN(pi))
6739 continue;
6740 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6741 continue;
6742 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6743 med_matched = false;
6744 break;
6745 }
6746 }
6747 if (!med_matched)
6748 break;
6749 }
6750 bgp_dest_unlock_node(top);
6751
6752 return med_matched;
6753}
6754
6755/**
6756 * Toggles the route suppression status for this aggregate address
6757 * configuration.
6758 */
4056a5f6
RZ
6759void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6760 struct bgp *bgp, const struct prefix *p,
6761 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6762{
6763 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6764 const struct prefix *dest_p;
6765 struct bgp_dest *dest, *top;
6766 struct bgp_path_info *pi;
6767 bool toggle_suppression;
6768
6769 /* We've found a different MED we must revert any suppressed routes. */
6770 top = bgp_node_get(table, p);
6771 for (dest = bgp_node_get(table, p); dest;
6772 dest = bgp_route_next_until(dest, top)) {
6773 dest_p = bgp_dest_get_prefix(dest);
6774 if (dest_p->prefixlen <= p->prefixlen)
6775 continue;
6776
6777 toggle_suppression = false;
6778 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6779 if (BGP_PATH_HOLDDOWN(pi))
6780 continue;
6781 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6782 continue;
6783
6aabb15d
RZ
6784 /* We are toggling suppression back. */
6785 if (suppress) {
6aabb15d 6786 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6787 if (aggr_suppress_path(aggregate, pi))
6788 toggle_suppression = true;
6aabb15d
RZ
6789 continue;
6790 }
6791
6aabb15d 6792 /* Install route if there is no more suppression. */
4056a5f6 6793 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6794 toggle_suppression = true;
6aabb15d
RZ
6795 }
6796
6797 if (toggle_suppression)
6798 bgp_process(bgp, dest, afi, safi);
6799 }
6800 bgp_dest_unlock_node(top);
6801}
6802
6803/**
6804 * Aggregate address MED matching incremental test: this function is called
6805 * when the initial aggregation occurred and we are only testing a single
6806 * new path.
6807 *
6808 * In addition to testing and setting the MED validity it also installs back
6809 * suppressed routes (if summary is configured).
6810 *
6811 * Must not be called in `bgp_aggregate_route`.
6812 */
6813static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6814 struct bgp *bgp, const struct prefix *p,
6815 afi_t afi, safi_t safi,
6816 struct bgp_path_info *pi, bool is_adding)
6817{
6818 /* MED matching disabled. */
6819 if (!aggregate->match_med)
6820 return;
6821
6822 /* Aggregation with different MED, nothing to do. */
6823 if (aggregate->med_mismatched)
6824 return;
6825
6826 /*
6827 * Test the current entry:
6828 *
6829 * is_adding == true: if the new entry doesn't match then we must
6830 * install all suppressed routes.
6831 *
6832 * is_adding == false: if the entry being removed was the last
6833 * unmatching entry then we can suppress all routes.
6834 */
6835 if (!is_adding) {
6836 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6837 && aggregate->summary_only)
6838 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6839 safi, true);
6840 } else
6841 bgp_aggregate_med_match(aggregate, bgp, pi);
6842
6843 /* No mismatches, just quit. */
6844 if (!aggregate->med_mismatched)
6845 return;
6846
6847 /* Route summarization is disabled. */
6848 if (!aggregate->summary_only)
6849 return;
6850
6851 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6852}
6853
b5d58c32 6854/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6855void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6856 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6857{
6858 struct bgp_table *table;
9bcb3eef
DS
6859 struct bgp_dest *top;
6860 struct bgp_dest *dest;
d7c0a89a 6861 uint8_t origin;
d62a17ae 6862 struct aspath *aspath = NULL;
d62a17ae 6863 struct community *community = NULL;
3da2cc32 6864 struct ecommunity *ecommunity = NULL;
dd18c5a9 6865 struct lcommunity *lcommunity = NULL;
40381db7 6866 struct bgp_path_info *pi;
d62a17ae 6867 unsigned long match = 0;
d7c0a89a 6868 uint8_t atomic_aggregate = 0;
d62a17ae 6869
9f822fa2
S
6870 /* If the bgp instance is being deleted or self peer is deleted
6871 * then do not create aggregate route
6872 */
892fedb6
DA
6873 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6874 || (bgp->peer_self == NULL))
9f822fa2
S
6875 return;
6876
6aabb15d
RZ
6877 /* Initialize and test routes for MED difference. */
6878 if (aggregate->match_med)
6879 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6880
4056a5f6
RZ
6881 /*
6882 * Reset aggregate count: we might've been called from route map
6883 * update so in that case we must retest all more specific routes.
6884 *
6885 * \see `bgp_route_map_process_update`.
6886 */
6887 aggregate->count = 0;
6888 aggregate->incomplete_origin_count = 0;
6889 aggregate->incomplete_origin_count = 0;
6890 aggregate->egp_origin_count = 0;
6891
d62a17ae 6892 /* ORIGIN attribute: If at least one route among routes that are
6893 aggregated has ORIGIN with the value INCOMPLETE, then the
6894 aggregated route must have the ORIGIN attribute with the value
6895 INCOMPLETE. Otherwise, if at least one route among routes that
6896 are aggregated has ORIGIN with the value EGP, then the aggregated
6897 route must have the origin attribute with the value EGP. In all
6898 other case the value of the ORIGIN attribute of the aggregated
6899 route is INTERNAL. */
6900 origin = BGP_ORIGIN_IGP;
718e3744 6901
d62a17ae 6902 table = bgp->rib[afi][safi];
718e3744 6903
d62a17ae 6904 top = bgp_node_get(table, p);
9bcb3eef
DS
6905 for (dest = bgp_node_get(table, p); dest;
6906 dest = bgp_route_next_until(dest, top)) {
6907 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6908
9bcb3eef 6909 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6910 continue;
d62a17ae 6911
a77e2f4b
S
6912 /* If suppress fib is enabled and route not installed
6913 * in FIB, skip the route
6914 */
6915 if (!bgp_check_advertise(bgp, dest))
6916 continue;
6917
c2ff8b3e 6918 match = 0;
d62a17ae 6919
9bcb3eef 6920 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6921 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6922 continue;
718e3744 6923
40381db7 6924 if (pi->attr->flag
c2ff8b3e
DS
6925 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6926 atomic_aggregate = 1;
d62a17ae 6927
40381db7 6928 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6929 continue;
d62a17ae 6930
f273fef1
DS
6931 /*
6932 * summary-only aggregate route suppress
6933 * aggregated route announcements.
6aabb15d
RZ
6934 *
6935 * MED matching:
6936 * Don't create summaries if MED didn't match
6937 * otherwise neither the specific routes and the
6938 * aggregation will be announced.
f273fef1 6939 */
6aabb15d
RZ
6940 if (aggregate->summary_only
6941 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6942 if (aggr_suppress_path(aggregate, pi))
6943 match++;
d62a17ae 6944 }
c2ff8b3e 6945
365ab2e7
RZ
6946 /*
6947 * Suppress more specific routes that match the route
6948 * map results.
6949 *
6950 * MED matching:
6951 * Don't suppress routes if MED matching is enabled and
6952 * it mismatched otherwise we might end up with no
6953 * routes for this path.
6954 */
6955 if (aggregate->suppress_map_name
6956 && AGGREGATE_MED_VALID(aggregate)
6957 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
6958 if (aggr_suppress_path(aggregate, pi))
6959 match++;
d62a17ae 6960 }
c2ff8b3e
DS
6961
6962 aggregate->count++;
6963
f273fef1
DS
6964 /*
6965 * If at least one route among routes that are
6966 * aggregated has ORIGIN with the value INCOMPLETE,
6967 * then the aggregated route MUST have the ORIGIN
6968 * attribute with the value INCOMPLETE. Otherwise, if
6969 * at least one route among routes that are aggregated
6970 * has ORIGIN with the value EGP, then the aggregated
6971 * route MUST have the ORIGIN attribute with the value
6972 * EGP.
6973 */
fc968841
NT
6974 switch (pi->attr->origin) {
6975 case BGP_ORIGIN_INCOMPLETE:
6976 aggregate->incomplete_origin_count++;
6977 break;
6978 case BGP_ORIGIN_EGP:
6979 aggregate->egp_origin_count++;
6980 break;
6981 default:
6982 /*Do nothing.
6983 */
6984 break;
6985 }
c2ff8b3e
DS
6986
6987 if (!aggregate->as_set)
6988 continue;
6989
f273fef1
DS
6990 /*
6991 * as-set aggregate route generate origin, as path,
6992 * and community aggregation.
6993 */
fc968841
NT
6994 /* Compute aggregate route's as-path.
6995 */
ef51a7d8 6996 bgp_compute_aggregate_aspath_hash(aggregate,
6997 pi->attr->aspath);
c2ff8b3e 6998
fc968841
NT
6999 /* Compute aggregate route's community.
7000 */
7001 if (pi->attr->community)
21fec674 7002 bgp_compute_aggregate_community_hash(
fc968841
NT
7003 aggregate,
7004 pi->attr->community);
dd18c5a9 7005
fc968841
NT
7006 /* Compute aggregate route's extended community.
7007 */
7008 if (pi->attr->ecommunity)
4edd83f9 7009 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7010 aggregate,
7011 pi->attr->ecommunity);
7012
7013 /* Compute aggregate route's large community.
7014 */
7015 if (pi->attr->lcommunity)
f1eb1f05 7016 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7017 aggregate,
7018 pi->attr->lcommunity);
d62a17ae 7019 }
c2ff8b3e 7020 if (match)
9bcb3eef 7021 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7022 }
21fec674 7023 if (aggregate->as_set) {
ef51a7d8 7024 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7025 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7026 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7027 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7028 }
7029
f1eb1f05 7030
9bcb3eef 7031 bgp_dest_unlock_node(top);
718e3744 7032
718e3744 7033
fc968841
NT
7034 if (aggregate->incomplete_origin_count > 0)
7035 origin = BGP_ORIGIN_INCOMPLETE;
7036 else if (aggregate->egp_origin_count > 0)
7037 origin = BGP_ORIGIN_EGP;
d62a17ae 7038
229757f1
DA
7039 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7040 origin = aggregate->origin;
7041
fc968841
NT
7042 if (aggregate->as_set) {
7043 if (aggregate->aspath)
7044 /* Retrieve aggregate route's as-path.
7045 */
7046 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7047
fc968841
NT
7048 if (aggregate->community)
7049 /* Retrieve aggregate route's community.
7050 */
7051 community = community_dup(aggregate->community);
3da2cc32 7052
fc968841
NT
7053 if (aggregate->ecommunity)
7054 /* Retrieve aggregate route's ecommunity.
7055 */
7056 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7057
fc968841
NT
7058 if (aggregate->lcommunity)
7059 /* Retrieve aggregate route's lcommunity.
7060 */
7061 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7062 }
718e3744 7063
c701010e 7064 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7065 ecommunity, lcommunity, atomic_aggregate,
7066 aggregate);
718e3744 7067}
7068
5f040085
DS
7069void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7070 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7071{
7072 struct bgp_table *table;
9bcb3eef
DS
7073 struct bgp_dest *top;
7074 struct bgp_dest *dest;
40381db7 7075 struct bgp_path_info *pi;
3b7db173
DS
7076 unsigned long match;
7077
7078 table = bgp->rib[afi][safi];
7079
7080 /* If routes exists below this node, generate aggregate routes. */
7081 top = bgp_node_get(table, p);
9bcb3eef
DS
7082 for (dest = bgp_node_get(table, p); dest;
7083 dest = bgp_route_next_until(dest, top)) {
7084 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7085
9bcb3eef 7086 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7087 continue;
7088 match = 0;
7089
9bcb3eef 7090 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7091 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7092 continue;
7093
40381db7 7094 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7095 continue;
7096
6aabb15d
RZ
7097 if (aggregate->summary_only && pi->extra
7098 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7099 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7100 match++;
3b7db173 7101 }
3b7db173 7102
365ab2e7
RZ
7103 if (aggregate->suppress_map_name
7104 && AGGREGATE_MED_VALID(aggregate)
7105 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7106 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7107 match++;
3b7db173 7108 }
365ab2e7 7109
3b7db173 7110 aggregate->count--;
fc968841
NT
7111
7112 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7113 aggregate->incomplete_origin_count--;
7114 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7115 aggregate->egp_origin_count--;
7116
7117 if (aggregate->as_set) {
7118 /* Remove as-path from aggregate.
7119 */
ef51a7d8 7120 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7121 aggregate,
7122 pi->attr->aspath);
7123
7124 if (pi->attr->community)
7125 /* Remove community from aggregate.
7126 */
21fec674 7127 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7128 aggregate,
7129 pi->attr->community);
7130
7131 if (pi->attr->ecommunity)
7132 /* Remove ecommunity from aggregate.
7133 */
4edd83f9 7134 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7135 aggregate,
7136 pi->attr->ecommunity);
7137
7138 if (pi->attr->lcommunity)
7139 /* Remove lcommunity from aggregate.
7140 */
f1eb1f05 7141 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7142 aggregate,
7143 pi->attr->lcommunity);
7144 }
3b7db173
DS
7145 }
7146
7147 /* If this node was suppressed, process the change. */
7148 if (match)
9bcb3eef 7149 bgp_process(bgp, dest, afi, safi);
3b7db173 7150 }
f1eb1f05 7151 if (aggregate->as_set) {
ef51a7d8 7152 aspath_free(aggregate->aspath);
7153 aggregate->aspath = NULL;
21fec674 7154 if (aggregate->community)
7155 community_free(&aggregate->community);
4edd83f9 7156 if (aggregate->ecommunity)
7157 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7158 if (aggregate->lcommunity)
7159 lcommunity_free(&aggregate->lcommunity);
7160 }
7161
9bcb3eef 7162 bgp_dest_unlock_node(top);
3b7db173 7163}
718e3744 7164
5f040085
DS
7165static void bgp_add_route_to_aggregate(struct bgp *bgp,
7166 const struct prefix *aggr_p,
fc968841
NT
7167 struct bgp_path_info *pinew, afi_t afi,
7168 safi_t safi,
7169 struct bgp_aggregate *aggregate)
7170{
7171 uint8_t origin;
7172 struct aspath *aspath = NULL;
7173 uint8_t atomic_aggregate = 0;
7174 struct community *community = NULL;
7175 struct ecommunity *ecommunity = NULL;
7176 struct lcommunity *lcommunity = NULL;
7177
7178 /* ORIGIN attribute: If at least one route among routes that are
7179 * aggregated has ORIGIN with the value INCOMPLETE, then the
7180 * aggregated route must have the ORIGIN attribute with the value
7181 * INCOMPLETE. Otherwise, if at least one route among routes that
7182 * are aggregated has ORIGIN with the value EGP, then the aggregated
7183 * route must have the origin attribute with the value EGP. In all
7184 * other case the value of the ORIGIN attribute of the aggregated
7185 * route is INTERNAL.
7186 */
7187 origin = BGP_ORIGIN_IGP;
7188
7189 aggregate->count++;
7190
6aabb15d
RZ
7191 /*
7192 * This must be called before `summary` check to avoid
7193 * "suppressing" twice.
7194 */
7195 if (aggregate->match_med)
7196 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7197 pinew, true);
7198
7199 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7200 aggr_suppress_path(aggregate, pinew);
fc968841 7201
365ab2e7
RZ
7202 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7203 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7204 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7205
7206 switch (pinew->attr->origin) {
7207 case BGP_ORIGIN_INCOMPLETE:
7208 aggregate->incomplete_origin_count++;
7209 break;
7210 case BGP_ORIGIN_EGP:
7211 aggregate->egp_origin_count++;
7212 break;
7213 default:
7214 /* Do nothing.
7215 */
7216 break;
7217 }
7218
7219 if (aggregate->incomplete_origin_count > 0)
7220 origin = BGP_ORIGIN_INCOMPLETE;
7221 else if (aggregate->egp_origin_count > 0)
7222 origin = BGP_ORIGIN_EGP;
7223
229757f1
DA
7224 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7225 origin = aggregate->origin;
7226
fc968841
NT
7227 if (aggregate->as_set) {
7228 /* Compute aggregate route's as-path.
7229 */
7230 bgp_compute_aggregate_aspath(aggregate,
7231 pinew->attr->aspath);
7232
7233 /* Compute aggregate route's community.
7234 */
7235 if (pinew->attr->community)
7236 bgp_compute_aggregate_community(
7237 aggregate,
7238 pinew->attr->community);
7239
7240 /* Compute aggregate route's extended community.
7241 */
7242 if (pinew->attr->ecommunity)
7243 bgp_compute_aggregate_ecommunity(
7244 aggregate,
7245 pinew->attr->ecommunity);
7246
7247 /* Compute aggregate route's large community.
7248 */
7249 if (pinew->attr->lcommunity)
7250 bgp_compute_aggregate_lcommunity(
7251 aggregate,
7252 pinew->attr->lcommunity);
7253
7254 /* Retrieve aggregate route's as-path.
7255 */
7256 if (aggregate->aspath)
7257 aspath = aspath_dup(aggregate->aspath);
7258
7259 /* Retrieve aggregate route's community.
7260 */
7261 if (aggregate->community)
7262 community = community_dup(aggregate->community);
7263
7264 /* Retrieve aggregate route's ecommunity.
7265 */
7266 if (aggregate->ecommunity)
7267 ecommunity = ecommunity_dup(aggregate->ecommunity);
7268
7269 /* Retrieve aggregate route's lcommunity.
7270 */
7271 if (aggregate->lcommunity)
7272 lcommunity = lcommunity_dup(aggregate->lcommunity);
7273 }
7274
7275 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7276 aspath, community, ecommunity,
7277 lcommunity, atomic_aggregate, aggregate);
7278}
7279
7280static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7281 safi_t safi,
7282 struct bgp_path_info *pi,
7283 struct bgp_aggregate *aggregate,
5f040085 7284 const struct prefix *aggr_p)
fc968841
NT
7285{
7286 uint8_t origin;
7287 struct aspath *aspath = NULL;
7288 uint8_t atomic_aggregate = 0;
7289 struct community *community = NULL;
7290 struct ecommunity *ecommunity = NULL;
7291 struct lcommunity *lcommunity = NULL;
7292 unsigned long match = 0;
7293
7294 if (BGP_PATH_HOLDDOWN(pi))
7295 return;
7296
7297 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7298 return;
7299
4056a5f6
RZ
7300 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7301 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7302 match++;
fc968841 7303
365ab2e7 7304 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7305 && aggr_suppress_map_test(bgp, aggregate, pi))
7306 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7307 match++;
fc968841 7308
6aabb15d 7309 /*
365ab2e7 7310 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7311 * "unsuppressing" twice.
7312 */
7313 if (aggregate->match_med)
7314 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7315 true);
7316
fc968841
NT
7317 if (aggregate->count > 0)
7318 aggregate->count--;
7319
7320 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7321 aggregate->incomplete_origin_count--;
7322 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7323 aggregate->egp_origin_count--;
7324
7325 if (aggregate->as_set) {
7326 /* Remove as-path from aggregate.
7327 */
7328 bgp_remove_aspath_from_aggregate(aggregate,
7329 pi->attr->aspath);
7330
7331 if (pi->attr->community)
7332 /* Remove community from aggregate.
7333 */
7334 bgp_remove_community_from_aggregate(
7335 aggregate,
7336 pi->attr->community);
7337
7338 if (pi->attr->ecommunity)
7339 /* Remove ecommunity from aggregate.
7340 */
7341 bgp_remove_ecommunity_from_aggregate(
7342 aggregate,
7343 pi->attr->ecommunity);
7344
7345 if (pi->attr->lcommunity)
7346 /* Remove lcommunity from aggregate.
7347 */
7348 bgp_remove_lcommunity_from_aggregate(
7349 aggregate,
7350 pi->attr->lcommunity);
7351 }
7352
7353 /* If this node was suppressed, process the change. */
7354 if (match)
7355 bgp_process(bgp, pi->net, afi, safi);
7356
7357 origin = BGP_ORIGIN_IGP;
7358 if (aggregate->incomplete_origin_count > 0)
7359 origin = BGP_ORIGIN_INCOMPLETE;
7360 else if (aggregate->egp_origin_count > 0)
7361 origin = BGP_ORIGIN_EGP;
7362
229757f1
DA
7363 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7364 origin = aggregate->origin;
7365
fc968841
NT
7366 if (aggregate->as_set) {
7367 /* Retrieve aggregate route's as-path.
7368 */
7369 if (aggregate->aspath)
7370 aspath = aspath_dup(aggregate->aspath);
7371
7372 /* Retrieve aggregate route's community.
7373 */
7374 if (aggregate->community)
7375 community = community_dup(aggregate->community);
7376
7377 /* Retrieve aggregate route's ecommunity.
7378 */
7379 if (aggregate->ecommunity)
7380 ecommunity = ecommunity_dup(aggregate->ecommunity);
7381
7382 /* Retrieve aggregate route's lcommunity.
7383 */
7384 if (aggregate->lcommunity)
7385 lcommunity = lcommunity_dup(aggregate->lcommunity);
7386 }
7387
7388 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7389 aspath, community, ecommunity,
7390 lcommunity, atomic_aggregate, aggregate);
7391}
7392
5a1ae2c2 7393void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7394 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7395{
9bcb3eef
DS
7396 struct bgp_dest *child;
7397 struct bgp_dest *dest;
d62a17ae 7398 struct bgp_aggregate *aggregate;
7399 struct bgp_table *table;
718e3744 7400
d62a17ae 7401 table = bgp->aggregate[afi][safi];
f018db83 7402
d62a17ae 7403 /* No aggregates configured. */
7404 if (bgp_table_top_nolock(table) == NULL)
7405 return;
f018db83 7406
d62a17ae 7407 if (p->prefixlen == 0)
7408 return;
718e3744 7409
40381db7 7410 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7411 return;
718e3744 7412
a77e2f4b
S
7413 /* If suppress fib is enabled and route not installed
7414 * in FIB, do not update the aggregate route
7415 */
7416 if (!bgp_check_advertise(bgp, pi->net))
7417 return;
7418
d62a17ae 7419 child = bgp_node_get(table, p);
718e3744 7420
d62a17ae 7421 /* Aggregate address configuration check. */
9bcb3eef
DS
7422 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7423 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7424
9bcb3eef
DS
7425 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7426 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7427 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7428 aggregate);
d62a17ae 7429 }
b1e62edd 7430 }
9bcb3eef 7431 bgp_dest_unlock_node(child);
718e3744 7432}
7433
5a1ae2c2 7434void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7435 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7436{
9bcb3eef
DS
7437 struct bgp_dest *child;
7438 struct bgp_dest *dest;
d62a17ae 7439 struct bgp_aggregate *aggregate;
7440 struct bgp_table *table;
718e3744 7441
d62a17ae 7442 table = bgp->aggregate[afi][safi];
718e3744 7443
d62a17ae 7444 /* No aggregates configured. */
7445 if (bgp_table_top_nolock(table) == NULL)
7446 return;
718e3744 7447
d62a17ae 7448 if (p->prefixlen == 0)
7449 return;
718e3744 7450
d62a17ae 7451 child = bgp_node_get(table, p);
718e3744 7452
d62a17ae 7453 /* Aggregate address configuration check. */
9bcb3eef
DS
7454 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7455 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7456
9bcb3eef
DS
7457 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7458 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7459 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7460 aggregate, dest_p);
d62a17ae 7461 }
b1e62edd 7462 }
9bcb3eef 7463 bgp_dest_unlock_node(child);
d62a17ae 7464}
718e3744 7465
718e3744 7466/* Aggregate route attribute. */
7467#define AGGREGATE_SUMMARY_ONLY 1
7468#define AGGREGATE_AS_SET 1
fb29348a 7469#define AGGREGATE_AS_UNSET 0
718e3744 7470
229757f1
DA
7471static const char *bgp_origin2str(uint8_t origin)
7472{
7473 switch (origin) {
7474 case BGP_ORIGIN_IGP:
7475 return "igp";
7476 case BGP_ORIGIN_EGP:
7477 return "egp";
7478 case BGP_ORIGIN_INCOMPLETE:
7479 return "incomplete";
7480 }
7481 return "n/a";
7482}
7483
37a87b8f
CS
7484int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7485 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7486{
9bcb3eef 7487 struct bgp_dest *dest;
d62a17ae 7488 struct bgp_aggregate *aggregate;
718e3744 7489
37a87b8f 7490 apply_mask(prefix);
d62a17ae 7491 /* Old configuration check. */
37a87b8f 7492 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7493 if (!dest) {
37a87b8f
CS
7494 snprintf(errmsg, errmsg_len,
7495 "There is no aggregate-address configuration.\n");
7496 return -1;
d62a17ae 7497 }
f6269b4f 7498
9bcb3eef 7499 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7500 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7501 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7502 0, aggregate);
d62a17ae 7503
7504 /* Unlock aggregate address configuration. */
9bcb3eef 7505 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7506
7507 if (aggregate->community)
7508 community_free(&aggregate->community);
7509
7510 if (aggregate->community_hash) {
7511 /* Delete all communities in the hash.
7512 */
7513 hash_clean(aggregate->community_hash,
7514 bgp_aggr_community_remove);
7515 /* Free up the community_hash.
7516 */
7517 hash_free(aggregate->community_hash);
7518 }
7519
7520 if (aggregate->ecommunity)
7521 ecommunity_free(&aggregate->ecommunity);
7522
7523 if (aggregate->ecommunity_hash) {
7524 /* Delete all ecommunities in the hash.
7525 */
7526 hash_clean(aggregate->ecommunity_hash,
7527 bgp_aggr_ecommunity_remove);
7528 /* Free up the ecommunity_hash.
7529 */
7530 hash_free(aggregate->ecommunity_hash);
7531 }
7532
7533 if (aggregate->lcommunity)
7534 lcommunity_free(&aggregate->lcommunity);
7535
7536 if (aggregate->lcommunity_hash) {
7537 /* Delete all lcommunities in the hash.
7538 */
7539 hash_clean(aggregate->lcommunity_hash,
7540 bgp_aggr_lcommunity_remove);
7541 /* Free up the lcommunity_hash.
7542 */
7543 hash_free(aggregate->lcommunity_hash);
7544 }
7545
7546 if (aggregate->aspath)
7547 aspath_free(aggregate->aspath);
7548
7549 if (aggregate->aspath_hash) {
7550 /* Delete all as-paths in the hash.
7551 */
7552 hash_clean(aggregate->aspath_hash,
7553 bgp_aggr_aspath_remove);
7554 /* Free up the aspath_hash.
7555 */
7556 hash_free(aggregate->aspath_hash);
7557 }
7558
d62a17ae 7559 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7560 bgp_dest_unlock_node(dest);
7561 bgp_dest_unlock_node(dest);
d62a17ae 7562
37a87b8f 7563 return 0;
d62a17ae 7564}
7565
37a87b8f
CS
7566int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7567 safi_t safi, const char *rmap, uint8_t summary_only,
7568 uint8_t as_set, uint8_t origin, bool match_med,
7569 const char *suppress_map,
7570 char *errmsg, size_t errmsg_len)
d62a17ae 7571{
d62a17ae 7572 int ret;
9bcb3eef 7573 struct bgp_dest *dest;
d62a17ae 7574 struct bgp_aggregate *aggregate;
fb29348a 7575 uint8_t as_set_new = as_set;
37a87b8f 7576 char buf[PREFIX2STR_BUFFER];
d62a17ae 7577
365ab2e7 7578 if (suppress_map && summary_only) {
37a87b8f 7579 snprintf(errmsg, errmsg_len,
365ab2e7 7580 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7581 return -1;
365ab2e7
RZ
7582 }
7583
37a87b8f 7584 apply_mask(prefix);
d62a17ae 7585
37a87b8f
CS
7586 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7587 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7588 snprintf(
7589 errmsg, errmsg_len,
7590 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7591 prefix2str(prefix, buf, PREFIX_STRLEN));
7592 return -1;
3624ac81
DS
7593 }
7594
d62a17ae 7595 /* Old configuration check. */
37a87b8f 7596 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7597 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7598
20894f50 7599 if (aggregate) {
37a87b8f
CS
7600 snprintf(errmsg, errmsg_len,
7601 "There is already same aggregate network.\n");
d62a17ae 7602 /* try to remove the old entry */
37a87b8f
CS
7603 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7604 errmsg_len);
d62a17ae 7605 if (ret) {
37a87b8f
CS
7606 snprintf(errmsg, errmsg_len,
7607 "Error deleting aggregate.\n");
9bcb3eef 7608 bgp_dest_unlock_node(dest);
37a87b8f 7609 return -1;
d62a17ae 7610 }
7611 }
718e3744 7612
d62a17ae 7613 /* Make aggregate address structure. */
7614 aggregate = bgp_aggregate_new();
7615 aggregate->summary_only = summary_only;
6aabb15d 7616 aggregate->match_med = match_med;
fb29348a
DA
7617
7618 /* Network operators MUST NOT locally generate any new
7619 * announcements containing AS_SET or AS_CONFED_SET. If they have
7620 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7621 * SHOULD withdraw those routes and re-announce routes for the
7622 * aggregate or component prefixes (i.e., the more-specific routes
7623 * subsumed by the previously aggregated route) without AS_SET
7624 * or AS_CONFED_SET in the updates.
7625 */
7f972cd8 7626 if (bgp->reject_as_sets) {
fb29348a
DA
7627 if (as_set == AGGREGATE_AS_SET) {
7628 as_set_new = AGGREGATE_AS_UNSET;
7629 zlog_warn(
63efca0e 7630 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7631 __func__);
37a87b8f
CS
7632 snprintf(
7633 errmsg, errmsg_len,
fb29348a
DA
7634 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7635 }
7636 }
7637
7638 aggregate->as_set = as_set_new;
d62a17ae 7639 aggregate->safi = safi;
229757f1
DA
7640 /* Override ORIGIN attribute if defined.
7641 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7642 * to IGP which is not what rfc4271 says.
7643 * This enables the same behavior, optionally.
7644 */
7645 aggregate->origin = origin;
20894f50
DA
7646
7647 if (rmap) {
7648 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7649 route_map_counter_decrement(aggregate->rmap.map);
7650 aggregate->rmap.name =
7651 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7652 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7653 route_map_counter_increment(aggregate->rmap.map);
7654 }
365ab2e7
RZ
7655
7656 if (suppress_map) {
7657 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7658 route_map_counter_decrement(aggregate->suppress_map);
7659
7660 aggregate->suppress_map_name =
7661 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7662 aggregate->suppress_map =
7663 route_map_lookup_by_name(aggregate->suppress_map_name);
7664 route_map_counter_increment(aggregate->suppress_map);
7665 }
7666
9bcb3eef 7667 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7668
d62a17ae 7669 /* Aggregate address insert into BGP routing table. */
37a87b8f 7670 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7671
37a87b8f 7672 return 0;
718e3744 7673}
7674
37a87b8f
CS
7675DEFPY_YANG(
7676 aggregate_addressv4, aggregate_addressv4_cmd,
7677 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7678 "as-set$as_set_s"
7679 "|summary-only$summary_only"
7680 "|route-map WORD$rmap_name"
7681 "|origin <egp|igp|incomplete>$origin_s"
7682 "|matching-MED-only$match_med"
90e21f35 7683 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7684 "}",
7685 NO_STR
7686 "Configure BGP aggregate entries\n"
7687 "Aggregate prefix\n"
7688 "Aggregate address\n"
7689 "Aggregate mask\n"
7690 "Generate AS set path information\n"
7691 "Filter more specific routes from updates\n"
7692 "Apply route map to aggregate network\n"
7693 "Route map name\n"
7694 "BGP origin code\n"
7695 "Remote EGP\n"
7696 "Local IGP\n"
7697 "Unknown heritage\n"
7698 "Only aggregate routes with matching MED\n"
90e21f35
CS
7699 "Suppress the selected more specific routes\n"
7700 "Route map with the route selectors\n")
37a87b8f
CS
7701{
7702 char base_xpath[XPATH_MAXLEN];
554b3b10 7703 safi_t safi = bgp_node_safi(vty);
554b3b10 7704 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7705
554b3b10
RZ
7706 if (addr_str) {
7707 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7708 == 0) {
7709 vty_out(vty, "%% Inconsistent address and mask\n");
7710 return CMD_WARNING_CONFIG_FAILED;
7711 }
37a87b8f
CS
7712 } else {
7713 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7714 }
7715
37a87b8f
CS
7716 if (!no && origin_s)
7717 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7718
7719 if (!no && as_set_s)
7720 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7721 else
7722 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7723
7724 if (!no && summary_only)
7725 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7726 "true");
7727 else
7728 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7729 "false");
7730
fa423774
CS
7731 if (!no && match_med)
7732 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7733 else
7734 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7735 "false");
7736
37a87b8f
CS
7737 if (rmap_name)
7738 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7739 rmap_name);
7740 else
7741 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7742 NB_OP_DESTROY, NULL);
7743
90e21f35
CS
7744 if (suppress_map)
7745 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7746 suppress_map);
7747 else
7748 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7749 NULL);
7750
37a87b8f
CS
7751 snprintf(
7752 base_xpath, sizeof(base_xpath),
7753 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7754 yang_afi_safi_value2identity(AFI_IP, safi),
7755 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7756
554b3b10 7757 if (no)
37a87b8f
CS
7758 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7759 else
7760 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7761
7762 return nb_cli_apply_changes(vty, base_xpath);
7763}
7764
7765DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7766 "[no] aggregate-address X:X::X:X/M$prefix {"
7767 "as-set$as_set_s"
7768 "|summary-only$summary_only"
7769 "|route-map WORD$rmap_name"
7770 "|origin <egp|igp|incomplete>$origin_s"
7771 "|matching-MED-only$match_med"
90e21f35 7772 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7773 "}",
7774 NO_STR
7775 "Configure BGP aggregate entries\n"
7776 "Aggregate prefix\n"
7777 "Generate AS set path information\n"
7778 "Filter more specific routes from updates\n"
7779 "Apply route map to aggregate network\n"
7780 "Route map name\n"
7781 "BGP origin code\n"
7782 "Remote EGP\n"
7783 "Local IGP\n"
7784 "Unknown heritage\n"
7785 "Only aggregate routes with matching MED\n"
7786 "Suppress the selected more specific routes\n"
90e21f35 7787 "Route map with the route selectors\n")
37a87b8f
CS
7788{
7789 char base_xpath[XPATH_MAXLEN];
7790 safi_t safi = bgp_node_safi(vty);
7791
7792 if (!no && origin_s)
7793 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7794
7795 if (!no && as_set_s)
7796 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7797 else
7798 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7799
7800 if (!no && summary_only)
7801 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7802 "true");
7803 else
7804 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7805 "false");
7806
fa423774
CS
7807 if (!no && match_med)
7808 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7809 else
7810 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7811 "false");
7812
37a87b8f
CS
7813 if (rmap_name)
7814 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7815 rmap_name);
7816
90e21f35
CS
7817 if (suppress_map)
7818 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7819 suppress_map);
7820 else
7821 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7822 NULL);
7823
37a87b8f
CS
7824 snprintf(
7825 base_xpath, sizeof(base_xpath),
7826 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7827 yang_afi_safi_value2identity(AFI_IP6, safi),
7828 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7829
554b3b10 7830 if (no)
37a87b8f
CS
7831 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7832 else
7833 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7834
37a87b8f
CS
7835 return nb_cli_apply_changes(vty, base_xpath);
7836}
7837
7838void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7839 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7840{
7841 uint8_t origin;
7842
7843 vty_out(vty, " aggregate-address %s",
7844 yang_dnode_get_string(dnode, "./prefix"));
7845
7846 if (yang_dnode_get_bool(dnode, "./as-set"))
7847 vty_out(vty, " as-set");
7848
7849 if (yang_dnode_get_bool(dnode, "./summary-only"))
7850 vty_out(vty, " summary-only");
7851
7852 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7853 vty_out(vty, " route-map %s",
7854 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7855
7856 origin = yang_dnode_get_enum(dnode, "./origin");
7857 if (origin != BGP_ORIGIN_UNSPECIFIED)
7858 vty_out(vty, " origin %s", bgp_origin2str(origin));
7859
fa423774
CS
7860 if (yang_dnode_get_bool(dnode, "./match-med"))
7861 vty_out(vty, " matching-MED-only");
7862
37a87b8f 7863 vty_out(vty, "\n");
718e3744 7864}
7865
718e3744 7866/* Redistribute route treatment. */
d62a17ae 7867void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7868 const union g_addr *nexthop, ifindex_t ifindex,
7869 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7870 uint8_t type, unsigned short instance,
7871 route_tag_t tag)
d62a17ae 7872{
4b7e6066 7873 struct bgp_path_info *new;
40381db7
DS
7874 struct bgp_path_info *bpi;
7875 struct bgp_path_info rmap_path;
9bcb3eef 7876 struct bgp_dest *bn;
d62a17ae 7877 struct attr attr;
7878 struct attr *new_attr;
7879 afi_t afi;
b68885f9 7880 route_map_result_t ret;
d62a17ae 7881 struct bgp_redist *red;
7882
7883 /* Make default attribute. */
7884 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7885 /*
7886 * This must not be NULL to satisfy Coverity SA
7887 */
7888 assert(attr.aspath);
9de1f7ff 7889
a4d82a8a 7890 switch (nhtype) {
9de1f7ff
DS
7891 case NEXTHOP_TYPE_IFINDEX:
7892 break;
7893 case NEXTHOP_TYPE_IPV4:
7894 case NEXTHOP_TYPE_IPV4_IFINDEX:
7895 attr.nexthop = nexthop->ipv4;
7896 break;
7897 case NEXTHOP_TYPE_IPV6:
7898 case NEXTHOP_TYPE_IPV6_IFINDEX:
7899 attr.mp_nexthop_global = nexthop->ipv6;
7900 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7901 break;
7902 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7903 switch (p->family) {
7904 case AF_INET:
9de1f7ff 7905 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7906 break;
7907 case AF_INET6:
9de1f7ff
DS
7908 memset(&attr.mp_nexthop_global, 0,
7909 sizeof(attr.mp_nexthop_global));
74489921 7910 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7911 break;
74489921 7912 }
9de1f7ff 7913 break;
d62a17ae 7914 }
74489921 7915 attr.nh_ifindex = ifindex;
f04a80a5 7916
d62a17ae 7917 attr.med = metric;
7918 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7919 attr.tag = tag;
718e3744 7920
d62a17ae 7921 afi = family2afi(p->family);
6aeb9e78 7922
d62a17ae 7923 red = bgp_redist_lookup(bgp, afi, type, instance);
7924 if (red) {
7925 struct attr attr_new;
718e3744 7926
d62a17ae 7927 /* Copy attribute for modification. */
6f4f49b2 7928 attr_new = attr;
718e3744 7929
d62a17ae 7930 if (red->redist_metric_flag)
7931 attr_new.med = red->redist_metric;
718e3744 7932
d62a17ae 7933 /* Apply route-map. */
7934 if (red->rmap.name) {
40381db7
DS
7935 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7936 rmap_path.peer = bgp->peer_self;
7937 rmap_path.attr = &attr_new;
718e3744 7938
d62a17ae 7939 SET_FLAG(bgp->peer_self->rmap_type,
7940 PEER_RMAP_TYPE_REDISTRIBUTE);
7941
1782514f 7942 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 7943
7944 bgp->peer_self->rmap_type = 0;
7945
7946 if (ret == RMAP_DENYMATCH) {
7947 /* Free uninterned attribute. */
7948 bgp_attr_flush(&attr_new);
7949
7950 /* Unintern original. */
7951 aspath_unintern(&attr.aspath);
7952 bgp_redistribute_delete(bgp, p, type, instance);
7953 return;
7954 }
7955 }
7956
637e5ba4 7957 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
7958 bgp_attr_add_gshut_community(&attr_new);
7959
d62a17ae 7960 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7961 SAFI_UNICAST, p, NULL);
7962
7963 new_attr = bgp_attr_intern(&attr_new);
7964
9bcb3eef 7965 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7966 if (bpi->peer == bgp->peer_self
7967 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7968 break;
7969
40381db7 7970 if (bpi) {
d62a17ae 7971 /* Ensure the (source route) type is updated. */
40381db7
DS
7972 bpi->type = type;
7973 if (attrhash_cmp(bpi->attr, new_attr)
7974 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7975 bgp_attr_unintern(&new_attr);
7976 aspath_unintern(&attr.aspath);
9bcb3eef 7977 bgp_dest_unlock_node(bn);
d62a17ae 7978 return;
7979 } else {
7980 /* The attribute is changed. */
40381db7 7981 bgp_path_info_set_flag(bn, bpi,
18ee8310 7982 BGP_PATH_ATTR_CHANGED);
d62a17ae 7983
7984 /* Rewrite BGP route information. */
40381db7
DS
7985 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7986 bgp_path_info_restore(bn, bpi);
d62a17ae 7987 else
40381db7
DS
7988 bgp_aggregate_decrement(
7989 bgp, p, bpi, afi, SAFI_UNICAST);
7990 bgp_attr_unintern(&bpi->attr);
7991 bpi->attr = new_attr;
7992 bpi->uptime = bgp_clock();
d62a17ae 7993
7994 /* Process change. */
40381db7 7995 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7996 SAFI_UNICAST);
7997 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7998 bgp_dest_unlock_node(bn);
d62a17ae 7999 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8000
8001 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8002 || (bgp->inst_type
8003 == BGP_INSTANCE_TYPE_DEFAULT)) {
8004
8005 vpn_leak_from_vrf_update(
40381db7 8006 bgp_get_default(), bgp, bpi);
ddb5b488 8007 }
d62a17ae 8008 return;
8009 }
8010 }
8011
8012 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8013 bgp->peer_self, new_attr, bn);
1defdda8 8014 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8015
8016 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8017 bgp_path_info_add(bn, new);
9bcb3eef 8018 bgp_dest_unlock_node(bn);
d62a17ae 8019 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8020
8021 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8022 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8023
8024 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8025 }
d62a17ae 8026 }
8027
8028 /* Unintern original. */
8029 aspath_unintern(&attr.aspath);
718e3744 8030}
8031
d7c0a89a
QY
8032void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8033 unsigned short instance)
718e3744 8034{
d62a17ae 8035 afi_t afi;
9bcb3eef 8036 struct bgp_dest *dest;
40381db7 8037 struct bgp_path_info *pi;
d62a17ae 8038 struct bgp_redist *red;
718e3744 8039
d62a17ae 8040 afi = family2afi(p->family);
718e3744 8041
d62a17ae 8042 red = bgp_redist_lookup(bgp, afi, type, instance);
8043 if (red) {
9bcb3eef
DS
8044 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8045 SAFI_UNICAST, p, NULL);
d62a17ae 8046
9bcb3eef 8047 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8048 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8049 break;
8050
40381db7 8051 if (pi) {
ddb5b488
PZ
8052 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8053 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8054
8055 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8056 bgp, pi);
ddb5b488 8057 }
40381db7 8058 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8059 bgp_path_info_delete(dest, pi);
8060 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8061 }
9bcb3eef 8062 bgp_dest_unlock_node(dest);
d62a17ae 8063 }
8064}
8065
8066/* Withdraw specified route type's route. */
8067void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8068 unsigned short instance)
d62a17ae 8069{
9bcb3eef 8070 struct bgp_dest *dest;
40381db7 8071 struct bgp_path_info *pi;
d62a17ae 8072 struct bgp_table *table;
8073
8074 table = bgp->rib[afi][SAFI_UNICAST];
8075
9bcb3eef
DS
8076 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8077 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8078 if (pi->peer == bgp->peer_self && pi->type == type
8079 && pi->instance == instance)
d62a17ae 8080 break;
8081
40381db7 8082 if (pi) {
ddb5b488
PZ
8083 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8084 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8085
8086 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8087 bgp, pi);
ddb5b488 8088 }
9bcb3eef 8089 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8090 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8091 bgp_path_info_delete(dest, pi);
8092 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8093 }
718e3744 8094 }
718e3744 8095}
6b0655a2 8096
718e3744 8097/* Static function to display route. */
bd494ec5 8098static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8099 json_object *json, bool wide)
718e3744 8100{
be054588 8101 int len = 0;
d62a17ae 8102 char buf[BUFSIZ];
50e05855 8103 char buf2[BUFSIZ];
718e3744 8104
d62a17ae 8105 if (p->family == AF_INET) {
c6462ff4 8106 if (!json) {
8228a9a7 8107 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8108 } else {
8109 json_object_string_add(json, "prefix",
8110 inet_ntop(p->family,
8111 &p->u.prefix, buf,
8112 BUFSIZ));
8113 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8114 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8115 json_object_string_add(json, "network", buf2);
c6462ff4 8116 }
d62a17ae 8117 } else if (p->family == AF_ETHERNET) {
8228a9a7 8118 len = vty_out(vty, "%pFX", p);
b03b8898 8119 } else if (p->family == AF_EVPN) {
57f7feb6 8120 if (!json)
2dbe669b 8121 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8122 else
60466a63 8123 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8124 } else if (p->family == AF_FLOWSPEC) {
8125 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8126 json ?
8127 NLRI_STRING_FORMAT_JSON_SIMPLE :
8128 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8129 } else {
c6462ff4 8130 if (!json)
8228a9a7 8131 len = vty_out(vty, "%pFX", p);
50e05855
AD
8132 else {
8133 json_object_string_add(json, "prefix",
8134 inet_ntop(p->family,
8135 &p->u.prefix, buf,
8136 BUFSIZ));
8137 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8138 prefix2str(p, buf2, PREFIX_STRLEN);
8139 json_object_string_add(json, "network", buf2);
8140 }
9c92b5f7 8141 }
d62a17ae 8142
9c92b5f7 8143 if (!json) {
ae248832 8144 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8145 if (len < 1)
8146 vty_out(vty, "\n%*s", 20, " ");
8147 else
8148 vty_out(vty, "%*s", len, " ");
8149 }
718e3744 8150}
8151
d62a17ae 8152enum bgp_display_type {
8153 normal_list,
718e3744 8154};
8155
bbb46eb5
DA
8156static const char *
8157bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8158{
8159 switch (reason) {
8160 case bgp_path_selection_none:
8161 return "Nothing to Select";
8162 case bgp_path_selection_first:
8163 return "First path received";
8164 case bgp_path_selection_evpn_sticky_mac:
8165 return "EVPN Sticky Mac";
8166 case bgp_path_selection_evpn_seq:
8167 return "EVPN sequence number";
8168 case bgp_path_selection_evpn_lower_ip:
8169 return "EVPN lower IP";
8170 case bgp_path_selection_evpn_local_path:
8171 return "EVPN local ES path";
8172 case bgp_path_selection_evpn_non_proxy:
8173 return "EVPN non proxy";
8174 case bgp_path_selection_weight:
8175 return "Weight";
8176 case bgp_path_selection_local_pref:
8177 return "Local Pref";
8178 case bgp_path_selection_local_route:
8179 return "Local Route";
8180 case bgp_path_selection_confed_as_path:
8181 return "Confederation based AS Path";
8182 case bgp_path_selection_as_path:
8183 return "AS Path";
8184 case bgp_path_selection_origin:
8185 return "Origin";
8186 case bgp_path_selection_med:
8187 return "MED";
8188 case bgp_path_selection_peer:
8189 return "Peer Type";
8190 case bgp_path_selection_confed:
8191 return "Confed Peer Type";
8192 case bgp_path_selection_igp_metric:
8193 return "IGP Metric";
8194 case bgp_path_selection_older:
8195 return "Older Path";
8196 case bgp_path_selection_router_id:
8197 return "Router ID";
8198 case bgp_path_selection_cluster_length:
8199 return "Cluser length";
8200 case bgp_path_selection_stale:
8201 return "Path Staleness";
8202 case bgp_path_selection_local_configured:
8203 return "Locally configured route";
8204 case bgp_path_selection_neighbor_ip:
8205 return "Neighbor IP";
8206 case bgp_path_selection_default:
8207 return "Nothing left to compare";
8208 }
8209 return "Invalid (internal error)";
8210}
8211
18ee8310 8212/* Print the short form route status for a bgp_path_info */
4b7e6066 8213static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8214 struct bgp_path_info *path,
d62a17ae 8215 json_object *json_path)
718e3744 8216{
d62a17ae 8217 if (json_path) {
b05a1c8b 8218
d62a17ae 8219 /* Route status display. */
9b6d8fcf 8220 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8221 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8222
9b6d8fcf 8223 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8224 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8225
4056a5f6 8226 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8227 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8228
9b6d8fcf
DS
8229 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8230 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8231 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8232
d62a17ae 8233 /* Selected */
9b6d8fcf 8234 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8235 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8236
9b6d8fcf 8237 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8238 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8239
bbb46eb5 8240 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8241 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8242 json_object_string_add(json_path, "selectionReason",
8243 bgp_path_selection_reason2str(
8244 path->net->reason));
8245 }
b05a1c8b 8246
9b6d8fcf 8247 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8248 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8249
d62a17ae 8250 /* Internal route. */
9b6d8fcf
DS
8251 if ((path->peer->as)
8252 && (path->peer->as == path->peer->local_as))
d62a17ae 8253 json_object_string_add(json_path, "pathFrom",
8254 "internal");
8255 else
8256 json_object_string_add(json_path, "pathFrom",
8257 "external");
b05a1c8b 8258
d62a17ae 8259 return;
8260 }
b05a1c8b 8261
d62a17ae 8262 /* Route status display. */
9b6d8fcf 8263 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8264 vty_out(vty, "R");
9b6d8fcf 8265 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8266 vty_out(vty, "S");
4056a5f6 8267 else if (bgp_path_suppressed(path))
d62a17ae 8268 vty_out(vty, "s");
9b6d8fcf
DS
8269 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8270 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8271 vty_out(vty, "*");
8272 else
8273 vty_out(vty, " ");
8274
8275 /* Selected */
9b6d8fcf 8276 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8277 vty_out(vty, "h");
9b6d8fcf 8278 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8279 vty_out(vty, "d");
9b6d8fcf 8280 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8281 vty_out(vty, ">");
9b6d8fcf 8282 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8283 vty_out(vty, "=");
8284 else
8285 vty_out(vty, " ");
718e3744 8286
d62a17ae 8287 /* Internal route. */
9b6d8fcf
DS
8288 if (path->peer && (path->peer->as)
8289 && (path->peer->as == path->peer->local_as))
d62a17ae 8290 vty_out(vty, "i");
8291 else
8292 vty_out(vty, " ");
b40d939b 8293}
8294
2ba93fd6
DA
8295static char *bgp_nexthop_hostname(struct peer *peer,
8296 struct bgp_nexthop_cache *bnc)
25b5da8d 8297{
892fedb6 8298 if (peer->hostname
aef999a2 8299 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8300 return peer->hostname;
8301 return NULL;
8302}
8303
b40d939b 8304/* called from terminal list command */
bd494ec5 8305void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8306 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8307 json_object *json_paths, bool wide)
d62a17ae 8308{
aef999a2 8309 int len;
515c2602 8310 struct attr *attr = path->attr;
d62a17ae 8311 json_object *json_path = NULL;
8312 json_object *json_nexthops = NULL;
8313 json_object *json_nexthop_global = NULL;
8314 json_object *json_nexthop_ll = NULL;
6f214dd3 8315 json_object *json_ext_community = NULL;
9df8b37c 8316 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8317 bool nexthop_self =
9b6d8fcf 8318 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8319 bool nexthop_othervrf = false;
43089216 8320 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8321 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8322 char *nexthop_hostname =
8323 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8324 char esi_buf[ESI_STR_LEN];
d62a17ae 8325
8326 if (json_paths)
8327 json_path = json_object_new_object();
8328
8329 /* short status lead text */
9b6d8fcf 8330 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8331
8332 if (!json_paths) {
8333 /* print prefix and mask */
8334 if (!display)
ae248832 8335 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8336 else
ae248832 8337 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8338 } else {
ae248832 8339 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8340 }
47fc97cc 8341
9df8b37c
PZ
8342 /*
8343 * If vrf id of nexthop is different from that of prefix,
8344 * set up printable string to append
8345 */
9b6d8fcf 8346 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8347 const char *self = "";
8348
8349 if (nexthop_self)
8350 self = "<";
8351
8352 nexthop_othervrf = true;
9b6d8fcf 8353 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8354
9b6d8fcf 8355 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8356 snprintf(vrf_id_str, sizeof(vrf_id_str),
8357 "@%s%s", VRFID_NONE_STR, self);
8358 else
8359 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8360 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8361
9b6d8fcf
DS
8362 if (path->extra->bgp_orig->inst_type
8363 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8364
9b6d8fcf 8365 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8366 } else {
8367 const char *self = "";
8368
8369 if (nexthop_self)
8370 self = "<";
8371
8372 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8373 }
8374
445c2480
DS
8375 /*
8376 * For ENCAP and EVPN routes, nexthop address family is not
8377 * neccessarily the same as the prefix address family.
8378 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8379 * EVPN routes are also exchanged with a MP nexthop. Currently,
8380 * this
8381 * is only IPv4, the value will be present in either
8382 * attr->nexthop or
8383 * attr->mp_nexthop_global_in
8384 */
8385 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8386 char buf[BUFSIZ];
8387 char nexthop[128];
8388 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8389
8390 switch (af) {
8391 case AF_INET:
772270f3
QY
8392 snprintf(nexthop, sizeof(nexthop), "%s",
8393 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8394 BUFSIZ));
445c2480
DS
8395 break;
8396 case AF_INET6:
772270f3
QY
8397 snprintf(nexthop, sizeof(nexthop), "%s",
8398 inet_ntop(af, &attr->mp_nexthop_global, buf,
8399 BUFSIZ));
445c2480
DS
8400 break;
8401 default:
772270f3 8402 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8403 break;
d62a17ae 8404 }
d62a17ae 8405
445c2480
DS
8406 if (json_paths) {
8407 json_nexthop_global = json_object_new_object();
8408
515c2602
DA
8409 json_object_string_add(json_nexthop_global, "ip",
8410 nexthop);
8411
939a97f4 8412 if (path->peer->hostname)
515c2602
DA
8413 json_object_string_add(json_nexthop_global,
8414 "hostname",
939a97f4 8415 path->peer->hostname);
515c2602
DA
8416
8417 json_object_string_add(json_nexthop_global, "afi",
8418 (af == AF_INET) ? "ipv4"
8419 : "ipv6");
445c2480
DS
8420 json_object_boolean_true_add(json_nexthop_global,
8421 "used");
aef999a2
DA
8422 } else {
8423 if (nexthop_hostname)
8424 len = vty_out(vty, "%s(%s)%s", nexthop,
8425 nexthop_hostname, vrf_id_str);
8426 else
8427 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8428
ae248832 8429 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8430 if (len < 1)
8431 vty_out(vty, "\n%*s", 36, " ");
8432 else
8433 vty_out(vty, "%*s", len, " ");
8434 }
445c2480
DS
8435 } else if (safi == SAFI_EVPN) {
8436 if (json_paths) {
23d0a753
DA
8437 char buf[BUFSIZ] = {0};
8438
445c2480
DS
8439 json_nexthop_global = json_object_new_object();
8440
515c2602 8441 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8442 inet_ntop(AF_INET,
8443 &attr->nexthop, buf,
8444 sizeof(buf)));
515c2602 8445
939a97f4 8446 if (path->peer->hostname)
515c2602
DA
8447 json_object_string_add(json_nexthop_global,
8448 "hostname",
939a97f4 8449 path->peer->hostname);
515c2602 8450
a4d82a8a
PZ
8451 json_object_string_add(json_nexthop_global, "afi",
8452 "ipv4");
445c2480
DS
8453 json_object_boolean_true_add(json_nexthop_global,
8454 "used");
aef999a2
DA
8455 } else {
8456 if (nexthop_hostname)
8457 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8458 nexthop_hostname, vrf_id_str);
8459 else
8460 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8461 vrf_id_str);
8462
ae248832 8463 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8464 if (len < 1)
8465 vty_out(vty, "\n%*s", 36, " ");
8466 else
8467 vty_out(vty, "%*s", len, " ");
8468 }
d33fc23b 8469 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8470 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8471 if (json_paths) {
23d0a753
DA
8472 char buf[BUFSIZ] = {0};
8473
026b914a 8474 json_nexthop_global = json_object_new_object();
515c2602 8475
026b914a
PG
8476 json_object_string_add(json_nexthop_global,
8477 "afi", "ipv4");
515c2602
DA
8478 json_object_string_add(
8479 json_nexthop_global, "ip",
23d0a753
DA
8480 inet_ntop(AF_INET, &attr->nexthop, buf,
8481 sizeof(buf)));
515c2602 8482
939a97f4 8483 if (path->peer->hostname)
515c2602
DA
8484 json_object_string_add(
8485 json_nexthop_global, "hostname",
939a97f4 8486 path->peer->hostname);
515c2602 8487
50e05855
AD
8488 json_object_boolean_true_add(
8489 json_nexthop_global,
026b914a
PG
8490 "used");
8491 } else {
aef999a2
DA
8492 if (nexthop_hostname)
8493 len = vty_out(vty, "%pI4(%s)%s",
8494 &attr->nexthop,
8495 nexthop_hostname,
8496 vrf_id_str);
8497 else
8498 len = vty_out(vty, "%pI4%s",
8499 &attr->nexthop,
8500 vrf_id_str);
8501
ae248832 8502 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8503 if (len < 1)
8504 vty_out(vty, "\n%*s", 36, " ");
8505 else
8506 vty_out(vty, "%*s", len, " ");
026b914a
PG
8507 }
8508 }
d33fc23b 8509 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8510 if (json_paths) {
23d0a753
DA
8511 char buf[BUFSIZ] = {0};
8512
445c2480 8513 json_nexthop_global = json_object_new_object();
d62a17ae 8514
515c2602 8515 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8516 inet_ntop(AF_INET,
8517 &attr->nexthop, buf,
8518 sizeof(buf)));
515c2602 8519
939a97f4 8520 if (path->peer->hostname)
515c2602
DA
8521 json_object_string_add(json_nexthop_global,
8522 "hostname",
939a97f4 8523 path->peer->hostname);
445c2480 8524
a4d82a8a
PZ
8525 json_object_string_add(json_nexthop_global, "afi",
8526 "ipv4");
445c2480
DS
8527 json_object_boolean_true_add(json_nexthop_global,
8528 "used");
8529 } else {
aef999a2
DA
8530 if (nexthop_hostname)
8531 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8532 nexthop_hostname, vrf_id_str);
8533 else
8534 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8535 vrf_id_str);
9df8b37c 8536
ae248832 8537 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8538 if (len < 1)
8539 vty_out(vty, "\n%*s", 36, " ");
8540 else
8541 vty_out(vty, "%*s", len, " ");
d62a17ae 8542 }
445c2480 8543 }
b05a1c8b 8544
445c2480 8545 /* IPv6 Next Hop */
a4d82a8a 8546 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8547 char buf[BUFSIZ];
d62a17ae 8548
445c2480
DS
8549 if (json_paths) {
8550 json_nexthop_global = json_object_new_object();
a4d82a8a 8551 json_object_string_add(
515c2602
DA
8552 json_nexthop_global, "ip",
8553 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8554 buf, BUFSIZ));
8555
939a97f4 8556 if (path->peer->hostname)
515c2602
DA
8557 json_object_string_add(json_nexthop_global,
8558 "hostname",
939a97f4 8559 path->peer->hostname);
515c2602 8560
a4d82a8a
PZ
8561 json_object_string_add(json_nexthop_global, "afi",
8562 "ipv6");
8563 json_object_string_add(json_nexthop_global, "scope",
8564 "global");
445c2480
DS
8565
8566 /* We display both LL & GL if both have been
8567 * received */
0606039c
DA
8568 if ((attr->mp_nexthop_len
8569 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8570 || (path->peer->conf_if)) {
a4d82a8a 8571 json_nexthop_ll = json_object_new_object();
d62a17ae 8572 json_object_string_add(
515c2602
DA
8573 json_nexthop_ll, "ip",
8574 inet_ntop(AF_INET6,
8575 &attr->mp_nexthop_local, buf,
8576 BUFSIZ));
8577
939a97f4 8578 if (path->peer->hostname)
515c2602
DA
8579 json_object_string_add(
8580 json_nexthop_ll, "hostname",
939a97f4 8581 path->peer->hostname);
515c2602 8582
a4d82a8a
PZ
8583 json_object_string_add(json_nexthop_ll, "afi",
8584 "ipv6");
8585 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8586 "link-local");
d62a17ae 8587
a4d82a8a
PZ
8588 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8589 &attr->mp_nexthop_local)
445c2480
DS
8590 != 0)
8591 && !attr->mp_nexthop_prefer_global)
d62a17ae 8592 json_object_boolean_true_add(
a4d82a8a 8593 json_nexthop_ll, "used");
445c2480
DS
8594 else
8595 json_object_boolean_true_add(
a4d82a8a 8596 json_nexthop_global, "used");
445c2480
DS
8597 } else
8598 json_object_boolean_true_add(
8599 json_nexthop_global, "used");
8600 } else {
8601 /* Display LL if LL/Global both in table unless
8602 * prefer-global is set */
0606039c
DA
8603 if (((attr->mp_nexthop_len
8604 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8605 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8606 || (path->peer->conf_if)) {
8607 if (path->peer->conf_if) {
a4d82a8a 8608 len = vty_out(vty, "%s",
9b6d8fcf 8609 path->peer->conf_if);
ae248832
MK
8610 /* len of IPv6 addr + max len of def
8611 * ifname */
8612 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8613
8614 if (len < 1)
a4d82a8a 8615 vty_out(vty, "\n%*s", 36, " ");
445c2480 8616 else
a4d82a8a 8617 vty_out(vty, "%*s", len, " ");
d62a17ae 8618 } else {
aef999a2
DA
8619 if (nexthop_hostname)
8620 len = vty_out(
8621 vty, "%pI6(%s)%s",
8622 &attr->mp_nexthop_local,
8623 nexthop_hostname,
8624 vrf_id_str);
8625 else
8626 len = vty_out(
8627 vty, "%pI6%s",
8628 &attr->mp_nexthop_local,
8629 vrf_id_str);
8630
ae248832 8631 len = wide ? (41 - len) : (16 - len);
d62a17ae 8632
8633 if (len < 1)
a4d82a8a 8634 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8635 else
a4d82a8a 8636 vty_out(vty, "%*s", len, " ");
d62a17ae 8637 }
445c2480 8638 } else {
aef999a2
DA
8639 if (nexthop_hostname)
8640 len = vty_out(vty, "%pI6(%s)%s",
8641 &attr->mp_nexthop_global,
8642 nexthop_hostname,
8643 vrf_id_str);
8644 else
8645 len = vty_out(vty, "%pI6%s",
8646 &attr->mp_nexthop_global,
8647 vrf_id_str);
8648
ae248832 8649 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8650
8651 if (len < 1)
8652 vty_out(vty, "\n%*s", 36, " ");
8653 else
8654 vty_out(vty, "%*s", len, " ");
d62a17ae 8655 }
8656 }
445c2480 8657 }
718e3744 8658
445c2480
DS
8659 /* MED/Metric */
8660 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8661 if (json_paths)
50e05855 8662 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8663 else if (wide)
8664 vty_out(vty, "%7u", attr->med);
0fbac0b4 8665 else
445c2480 8666 vty_out(vty, "%10u", attr->med);
ae248832
MK
8667 else if (!json_paths) {
8668 if (wide)
8669 vty_out(vty, "%*s", 7, " ");
8670 else
8671 vty_out(vty, "%*s", 10, " ");
8672 }
d62a17ae 8673
445c2480
DS
8674 /* Local Pref */
8675 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8676 if (json_paths)
50e05855 8677 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8678 attr->local_pref);
8679 else
445c2480
DS
8680 vty_out(vty, "%7u", attr->local_pref);
8681 else if (!json_paths)
8682 vty_out(vty, " ");
d62a17ae 8683
445c2480
DS
8684 if (json_paths)
8685 json_object_int_add(json_path, "weight", attr->weight);
8686 else
8687 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8688
445c2480
DS
8689 if (json_paths) {
8690 char buf[BUFSIZ];
a4d82a8a
PZ
8691 json_object_string_add(
8692 json_path, "peerId",
9b6d8fcf 8693 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8694 }
b05a1c8b 8695
445c2480
DS
8696 /* Print aspath */
8697 if (attr->aspath) {
0fbac0b4 8698 if (json_paths)
50e05855 8699 json_object_string_add(json_path, "path",
0fbac0b4
DA
8700 attr->aspath->str);
8701 else
445c2480 8702 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8703 }
f1aa5d8a 8704
445c2480
DS
8705 /* Print origin */
8706 if (json_paths)
a4d82a8a
PZ
8707 json_object_string_add(json_path, "origin",
8708 bgp_origin_long_str[attr->origin]);
445c2480
DS
8709 else
8710 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8711
9df8b37c 8712 if (json_paths) {
d071f237 8713 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8714 json_object_string_add(json_path, "esi",
8715 esi_to_str(&attr->esi,
8716 esi_buf, sizeof(esi_buf)));
8717 }
6f214dd3
CS
8718 if (safi == SAFI_EVPN &&
8719 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8720 json_ext_community = json_object_new_object();
8721 json_object_string_add(json_ext_community,
8722 "string",
8723 attr->ecommunity->str);
8724 json_object_object_add(json_path,
8725 "extendedCommunity",
8726 json_ext_community);
8727 }
8728
9df8b37c
PZ
8729 if (nexthop_self)
8730 json_object_boolean_true_add(json_path,
8731 "announceNexthopSelf");
8732 if (nexthop_othervrf) {
8733 json_object_string_add(json_path, "nhVrfName",
8734 nexthop_vrfname);
8735
8736 json_object_int_add(json_path, "nhVrfId",
8737 ((nexthop_vrfid == VRF_UNKNOWN)
8738 ? -1
8739 : (int)nexthop_vrfid));
8740 }
8741 }
8742
d62a17ae 8743 if (json_paths) {
8744 if (json_nexthop_global || json_nexthop_ll) {
8745 json_nexthops = json_object_new_array();
f1aa5d8a 8746
d62a17ae 8747 if (json_nexthop_global)
8748 json_object_array_add(json_nexthops,
8749 json_nexthop_global);
f1aa5d8a 8750
d62a17ae 8751 if (json_nexthop_ll)
8752 json_object_array_add(json_nexthops,
8753 json_nexthop_ll);
f1aa5d8a 8754
d62a17ae 8755 json_object_object_add(json_path, "nexthops",
8756 json_nexthops);
8757 }
8758
8759 json_object_array_add(json_paths, json_path);
8760 } else {
8761 vty_out(vty, "\n");
6f214dd3 8762
b5e140c8 8763 if (safi == SAFI_EVPN) {
229587fb
AK
8764 struct bgp_path_es_info *path_es_info = NULL;
8765
8766 if (path->extra)
8767 path_es_info = path->extra->es_info;
8768
d071f237 8769 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8770 /* XXX - add these params to the json out */
b5e140c8 8771 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8772 vty_out(vty, "ESI:%s",
8773 esi_to_str(&attr->esi, esi_buf,
8774 sizeof(esi_buf)));
8775 if (path_es_info && path_es_info->es)
8776 vty_out(vty, " VNI: %u",
8777 path_es_info->vni);
8778 vty_out(vty, "\n");
b5e140c8
AK
8779 }
8780 if (attr->flag &
8781 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8782 vty_out(vty, "%*s", 20, " ");
8783 vty_out(vty, "%s\n", attr->ecommunity->str);
8784 }
6f214dd3
CS
8785 }
8786
49e5a4a0 8787#ifdef ENABLE_BGP_VNC
d62a17ae 8788 /* prints an additional line, indented, with VNC info, if
8789 * present */
8790 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8791 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8792#endif
d62a17ae 8793 }
8794}
718e3744 8795
8796/* called from terminal list command */
5f040085
DS
8797void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8798 struct attr *attr, safi_t safi, bool use_json,
ae248832 8799 json_object *json_ar, bool wide)
d62a17ae 8800{
8801 json_object *json_status = NULL;
8802 json_object *json_net = NULL;
aef999a2 8803 int len;
d62a17ae 8804 char buff[BUFSIZ];
dc387b0f 8805
d62a17ae 8806 /* Route status display. */
8807 if (use_json) {
8808 json_status = json_object_new_object();
8809 json_net = json_object_new_object();
8810 } else {
8811 vty_out(vty, "*");
8812 vty_out(vty, ">");
8813 vty_out(vty, " ");
8814 }
718e3744 8815
d62a17ae 8816 /* print prefix and mask */
50e05855 8817 if (use_json) {
dc387b0f
LK
8818 if (safi == SAFI_EVPN)
8819 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8820 else if (p->family == AF_INET || p->family == AF_INET6) {
8821 json_object_string_add(
8822 json_net, "addrPrefix",
8823 inet_ntop(p->family, &p->u.prefix, buff,
8824 BUFSIZ));
8825 json_object_int_add(json_net, "prefixLen",
8826 p->prefixlen);
8827 prefix2str(p, buff, PREFIX_STRLEN);
8828 json_object_string_add(json_net, "network", buff);
8829 }
50e05855 8830 } else
ae248832 8831 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8832
8833 /* Print attribute */
8834 if (attr) {
8835 if (use_json) {
23d0a753
DA
8836 char buf[BUFSIZ] = {0};
8837
d62a17ae 8838 if (p->family == AF_INET
8839 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8840 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8841 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8842 json_object_string_add(
8843 json_net, "nextHop",
23d0a753
DA
8844 inet_ntop(
8845 AF_INET,
8846 &attr->mp_nexthop_global_in,
8847 buf, sizeof(buf)));
d62a17ae 8848 else
8849 json_object_string_add(
8850 json_net, "nextHop",
23d0a753
DA
8851 inet_ntop(AF_INET,
8852 &attr->nexthop, buf,
8853 sizeof(buf)));
d62a17ae 8854 } else if (p->family == AF_INET6
8855 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8856 char buf[BUFSIZ];
8857
8858 json_object_string_add(
aa0a10fc 8859 json_net, "nextHopGlobal",
d62a17ae 8860 inet_ntop(AF_INET6,
8861 &attr->mp_nexthop_global, buf,
8862 BUFSIZ));
23d0a753
DA
8863 } else if (p->family == AF_EVPN
8864 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8865 char buf[BUFSIZ] = {0};
8866
8867 json_object_string_add(
8868 json_net, "nextHop",
8869 inet_ntop(AF_INET,
8870 &attr->mp_nexthop_global_in,
8871 buf, sizeof(buf)));
8872 }
d62a17ae 8873
8874 if (attr->flag
8875 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8876 json_object_int_add(json_net, "metric",
8877 attr->med);
8878
0fbac0b4 8879 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8880 json_object_int_add(json_net, "locPrf",
0fbac0b4 8881 attr->local_pref);
d62a17ae 8882
8883 json_object_int_add(json_net, "weight", attr->weight);
8884
8885 /* Print aspath */
0fbac0b4 8886 if (attr->aspath)
50e05855 8887 json_object_string_add(json_net, "path",
0fbac0b4 8888 attr->aspath->str);
d62a17ae 8889
8890 /* Print origin */
8891 json_object_string_add(json_net, "bgpOriginCode",
8892 bgp_origin_str[attr->origin]);
8893 } else {
8894 if (p->family == AF_INET
8895 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8896 || safi == SAFI_EVPN
8897 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8898 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8899 || safi == SAFI_EVPN)
23d0a753
DA
8900 vty_out(vty, "%-16pI4",
8901 &attr->mp_nexthop_global_in);
ae248832 8902 else if (wide)
23d0a753 8903 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8904 else
23d0a753 8905 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8906 } else if (p->family == AF_INET6
8907 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8908 char buf[BUFSIZ];
8909
8910 len = vty_out(
8911 vty, "%s",
8912 inet_ntop(AF_INET6,
8913 &attr->mp_nexthop_global, buf,
8914 BUFSIZ));
ae248832 8915 len = wide ? (41 - len) : (16 - len);
d62a17ae 8916 if (len < 1)
8917 vty_out(vty, "\n%*s", 36, " ");
8918 else
8919 vty_out(vty, "%*s", len, " ");
8920 }
8921 if (attr->flag
8922 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8923 if (wide)
8924 vty_out(vty, "%7u", attr->med);
8925 else
8926 vty_out(vty, "%10u", attr->med);
8927 else if (wide)
8928 vty_out(vty, " ");
d62a17ae 8929 else
8930 vty_out(vty, " ");
718e3744 8931
d62a17ae 8932 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8933 vty_out(vty, "%7u", attr->local_pref);
8934 else
8935 vty_out(vty, " ");
8936
8937 vty_out(vty, "%7u ", attr->weight);
8938
8939 /* Print aspath */
8940 if (attr->aspath)
8941 aspath_print_vty(vty, "%s", attr->aspath, " ");
8942
8943 /* Print origin */
8944 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8945 }
8946 }
8947 if (use_json) {
8948 json_object_boolean_true_add(json_status, "*");
8949 json_object_boolean_true_add(json_status, ">");
8950 json_object_object_add(json_net, "appliedStatusSymbols",
8951 json_status);
1608ff77 8952
dc387b0f
LK
8953 prefix2str(p, buff, PREFIX_STRLEN);
8954 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8955 } else
8956 vty_out(vty, "\n");
8957}
8958
bd494ec5 8959void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8960 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8961 json_object *json)
8962{
8963 json_object *json_out = NULL;
8964 struct attr *attr;
8965 mpls_label_t label = MPLS_INVALID_LABEL;
8966
9b6d8fcf 8967 if (!path->extra)
d62a17ae 8968 return;
8969
8970 if (json)
8971 json_out = json_object_new_object();
8972
8973 /* short status lead text */
9b6d8fcf 8974 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8975
8976 /* print prefix and mask */
8977 if (json == NULL) {
8978 if (!display)
ae248832 8979 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8980 else
8981 vty_out(vty, "%*s", 17, " ");
8982 }
8983
8984 /* Print attribute */
9b6d8fcf 8985 attr = path->attr;
05864da7
DS
8986 if (((p->family == AF_INET)
8987 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8988 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8989 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
8990 char buf[BUFSIZ] = {0};
8991
05864da7
DS
8992 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8993 || safi == SAFI_EVPN) {
8994 if (json)
8995 json_object_string_add(
8996 json_out, "mpNexthopGlobalIn",
23d0a753
DA
8997 inet_ntop(AF_INET,
8998 &attr->mp_nexthop_global_in,
8999 buf, sizeof(buf)));
05864da7 9000 else
23d0a753
DA
9001 vty_out(vty, "%-16pI4",
9002 &attr->mp_nexthop_global_in);
05864da7
DS
9003 } else {
9004 if (json)
9005 json_object_string_add(
9006 json_out, "nexthop",
23d0a753
DA
9007 inet_ntop(AF_INET, &attr->nexthop, buf,
9008 sizeof(buf)));
05864da7 9009 else
23d0a753 9010 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9011 }
9012 } else if (((p->family == AF_INET6)
9013 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9014 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9015 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9016 char buf_a[512];
9017
9018 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9019 if (json)
9020 json_object_string_add(
9021 json_out, "mpNexthopGlobalIn",
9022 inet_ntop(AF_INET6,
9023 &attr->mp_nexthop_global,
9024 buf_a, sizeof(buf_a)));
9025 else
9026 vty_out(vty, "%s",
9027 inet_ntop(AF_INET6,
9028 &attr->mp_nexthop_global,
9029 buf_a, sizeof(buf_a)));
9030 } else if (attr->mp_nexthop_len
9031 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9032 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9033 &attr->mp_nexthop_global,
9034 &attr->mp_nexthop_local);
9035 if (json)
9036 json_object_string_add(json_out,
9037 "mpNexthopGlobalLocal",
9038 buf_a);
9039 else
9040 vty_out(vty, "%s", buf_a);
d62a17ae 9041 }
9042 }
9043
9b6d8fcf 9044 label = decode_label(&path->extra->label[0]);
d62a17ae 9045
9046 if (bgp_is_valid_label(&label)) {
9047 if (json) {
9048 json_object_int_add(json_out, "notag", label);
9049 json_object_array_add(json, json_out);
9050 } else {
9051 vty_out(vty, "notag/%d", label);
9052 vty_out(vty, "\n");
9053 }
9054 }
9055}
718e3744 9056
bd494ec5 9057void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9058 struct bgp_path_info *path, int display,
d62a17ae 9059 json_object *json_paths)
718e3744 9060{
d62a17ae 9061 struct attr *attr;
14f51eba 9062 char buf[BUFSIZ] = {0};
d62a17ae 9063 json_object *json_path = NULL;
14f51eba
LK
9064 json_object *json_nexthop = NULL;
9065 json_object *json_overlay = NULL;
856ca177 9066
9b6d8fcf 9067 if (!path->extra)
d62a17ae 9068 return;
718e3744 9069
14f51eba
LK
9070 if (json_paths) {
9071 json_path = json_object_new_object();
9072 json_overlay = json_object_new_object();
9073 json_nexthop = json_object_new_object();
9074 }
9075
d62a17ae 9076 /* short status lead text */
9b6d8fcf 9077 route_vty_short_status_out(vty, path, json_path);
856ca177 9078
d62a17ae 9079 /* print prefix and mask */
9080 if (!display)
ae248832 9081 route_vty_out_route(p, vty, json_path, false);
d62a17ae 9082 else
9083 vty_out(vty, "%*s", 17, " ");
9084
9085 /* Print attribute */
9b6d8fcf 9086 attr = path->attr;
05864da7
DS
9087 char buf1[BUFSIZ];
9088 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9089
05864da7
DS
9090 switch (af) {
9091 case AF_INET:
9092 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9093 if (!json_path) {
9094 vty_out(vty, "%-16s", buf);
9095 } else {
9096 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9097
05864da7 9098 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9099
05864da7
DS
9100 json_object_object_add(json_path, "nexthop",
9101 json_nexthop);
9102 }
9103 break;
9104 case AF_INET6:
9105 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9106 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9107 if (!json_path) {
9108 vty_out(vty, "%s(%s)", buf, buf1);
9109 } else {
9110 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9111
05864da7
DS
9112 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9113 buf1);
14f51eba 9114
05864da7 9115 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9116
05864da7
DS
9117 json_object_object_add(json_path, "nexthop",
9118 json_nexthop);
9119 }
9120 break;
9121 default:
9122 if (!json_path) {
9123 vty_out(vty, "?");
9124 } else {
9125 json_object_string_add(json_nexthop, "Error",
9126 "Unsupported address-family");
d62a17ae 9127 }
05864da7 9128 }
988258b4 9129
6c924775
DS
9130 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9131
9132 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9133 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9134 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9135 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9136
05864da7
DS
9137 if (!json_path)
9138 vty_out(vty, "/%s", buf);
9139 else
9140 json_object_string_add(json_overlay, "gw", buf);
9141
9142 if (attr->ecommunity) {
9143 char *mac = NULL;
9144 struct ecommunity_val *routermac = ecommunity_lookup(
9145 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9146 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9147
9148 if (routermac)
9149 mac = ecom_mac2str((char *)routermac->val);
9150 if (mac) {
9151 if (!json_path) {
c4efd0f4 9152 vty_out(vty, "/%s", mac);
05864da7
DS
9153 } else {
9154 json_object_string_add(json_overlay, "rmac",
9155 mac);
988258b4 9156 }
05864da7 9157 XFREE(MTYPE_TMP, mac);
988258b4 9158 }
05864da7 9159 }
718e3744 9160
05864da7
DS
9161 if (!json_path) {
9162 vty_out(vty, "\n");
9163 } else {
9164 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9165
05864da7 9166 json_object_array_add(json_paths, json_path);
14f51eba 9167 }
d62a17ae 9168}
718e3744 9169
d62a17ae 9170/* dampening route */
5f040085
DS
9171static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9172 struct bgp_path_info *path, int display,
9173 afi_t afi, safi_t safi, bool use_json,
9174 json_object *json)
d62a17ae 9175{
9176 struct attr *attr;
9177 int len;
9178 char timebuf[BGP_UPTIME_LEN];
9179
9180 /* short status lead text */
9b6d8fcf 9181 route_vty_short_status_out(vty, path, json);
d62a17ae 9182
9183 /* print prefix and mask */
9184 if (!use_json) {
9185 if (!display)
ae248832 9186 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9187 else
9188 vty_out(vty, "%*s", 17, " ");
9189 }
9190
9b6d8fcf 9191 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9192 len = 17 - len;
9193 if (len < 1) {
9194 if (!use_json)
9195 vty_out(vty, "\n%*s", 34, " ");
9196 } else {
9197 if (use_json)
9198 json_object_int_add(json, "peerHost", len);
9199 else
9200 vty_out(vty, "%*s", len, " ");
9201 }
9202
9203 if (use_json)
a935f597
DA
9204 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9205 safi, use_json, json);
d62a17ae 9206 else
9b6d8fcf
DS
9207 vty_out(vty, "%s ",
9208 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9209 BGP_UPTIME_LEN, afi, safi,
9210 use_json, json));
d62a17ae 9211
9212 /* Print attribute */
9b6d8fcf 9213 attr = path->attr;
d62a17ae 9214
05864da7
DS
9215 /* Print aspath */
9216 if (attr->aspath) {
d62a17ae 9217 if (use_json)
05864da7
DS
9218 json_object_string_add(json, "asPath",
9219 attr->aspath->str);
d62a17ae 9220 else
05864da7 9221 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9222 }
05864da7
DS
9223
9224 /* Print origin */
9225 if (use_json)
9226 json_object_string_add(json, "origin",
9227 bgp_origin_str[attr->origin]);
9228 else
9229 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9230
d62a17ae 9231 if (!use_json)
9232 vty_out(vty, "\n");
9233}
718e3744 9234
d62a17ae 9235/* flap route */
5f040085
DS
9236static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9237 struct bgp_path_info *path, int display,
9238 afi_t afi, safi_t safi, bool use_json,
9239 json_object *json)
784d3a42 9240{
d62a17ae 9241 struct attr *attr;
9242 struct bgp_damp_info *bdi;
9243 char timebuf[BGP_UPTIME_LEN];
9244 int len;
784d3a42 9245
9b6d8fcf 9246 if (!path->extra)
d62a17ae 9247 return;
784d3a42 9248
9b6d8fcf 9249 bdi = path->extra->damp_info;
784d3a42 9250
d62a17ae 9251 /* short status lead text */
9b6d8fcf 9252 route_vty_short_status_out(vty, path, json);
784d3a42 9253
d62a17ae 9254 /* print prefix and mask */
9255 if (!use_json) {
9256 if (!display)
ae248832 9257 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9258 else
9259 vty_out(vty, "%*s", 17, " ");
9260 }
784d3a42 9261
9b6d8fcf 9262 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9263 len = 16 - len;
9264 if (len < 1) {
9265 if (!use_json)
9266 vty_out(vty, "\n%*s", 33, " ");
9267 } else {
9268 if (use_json)
9269 json_object_int_add(json, "peerHost", len);
9270 else
9271 vty_out(vty, "%*s", len, " ");
9272 }
784d3a42 9273
d62a17ae 9274 len = vty_out(vty, "%d", bdi->flap);
9275 len = 5 - len;
9276 if (len < 1) {
9277 if (!use_json)
9278 vty_out(vty, " ");
9279 } else {
9280 if (use_json)
9281 json_object_int_add(json, "bdiFlap", len);
9282 else
9283 vty_out(vty, "%*s", len, " ");
9284 }
9285
9286 if (use_json)
9287 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9288 json);
9289 else
996c9314
LB
9290 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9291 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9292
9b6d8fcf
DS
9293 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9294 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9295 if (use_json)
9b6d8fcf 9296 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9297 BGP_UPTIME_LEN, afi, safi,
9298 use_json, json);
d62a17ae 9299 else
9300 vty_out(vty, "%s ",
9b6d8fcf 9301 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9302 BGP_UPTIME_LEN, afi,
9303 safi, use_json, json));
d62a17ae 9304 } else {
9305 if (!use_json)
9306 vty_out(vty, "%*s ", 8, " ");
9307 }
9308
9309 /* Print attribute */
9b6d8fcf 9310 attr = path->attr;
d62a17ae 9311
05864da7
DS
9312 /* Print aspath */
9313 if (attr->aspath) {
d62a17ae 9314 if (use_json)
05864da7
DS
9315 json_object_string_add(json, "asPath",
9316 attr->aspath->str);
d62a17ae 9317 else
05864da7 9318 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9319 }
05864da7
DS
9320
9321 /* Print origin */
9322 if (use_json)
9323 json_object_string_add(json, "origin",
9324 bgp_origin_str[attr->origin]);
9325 else
9326 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9327
d62a17ae 9328 if (!use_json)
9329 vty_out(vty, "\n");
9330}
9331
9332static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9333 int *first, const char *header,
9334 json_object *json_adv_to)
9335{
9336 char buf1[INET6_ADDRSTRLEN];
9337 json_object *json_peer = NULL;
9338
9339 if (json_adv_to) {
9340 /* 'advertised-to' is a dictionary of peers we have advertised
9341 * this
9342 * prefix too. The key is the peer's IP or swpX, the value is
9343 * the
9344 * hostname if we know it and "" if not.
9345 */
9346 json_peer = json_object_new_object();
9347
9348 if (peer->hostname)
9349 json_object_string_add(json_peer, "hostname",
9350 peer->hostname);
9351
9352 if (peer->conf_if)
9353 json_object_object_add(json_adv_to, peer->conf_if,
9354 json_peer);
9355 else
9356 json_object_object_add(
9357 json_adv_to,
9358 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9359 json_peer);
9360 } else {
9361 if (*first) {
9362 vty_out(vty, "%s", header);
9363 *first = 0;
9364 }
9365
9366 if (peer->hostname
892fedb6 9367 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9368 if (peer->conf_if)
9369 vty_out(vty, " %s(%s)", peer->hostname,
9370 peer->conf_if);
9371 else
9372 vty_out(vty, " %s(%s)", peer->hostname,
9373 sockunion2str(&peer->su, buf1,
9374 SU_ADDRSTRLEN));
9375 } else {
9376 if (peer->conf_if)
9377 vty_out(vty, " %s", peer->conf_if);
9378 else
9379 vty_out(vty, " %s",
9380 sockunion2str(&peer->su, buf1,
9381 SU_ADDRSTRLEN));
9382 }
9383 }
784d3a42
PG
9384}
9385
dcc68b5e
MS
9386static void route_vty_out_tx_ids(struct vty *vty,
9387 struct bgp_addpath_info_data *d)
9388{
9389 int i;
9390
9391 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9392 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9393 d->addpath_tx_id[i],
9394 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9395 }
9396}
9397
5e4d4c8a 9398static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9399 struct bgp_path_info *pi,
9400 struct attr *attr,
9401 json_object *json_path)
5e4d4c8a
AK
9402{
9403 char esi_buf[ESI_STR_LEN];
9404 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9405 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9406 ATTR_ES_PEER_ROUTER);
9407 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9408 ATTR_ES_PEER_ACTIVE);
9409 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9410 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9411 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9412 if (json_path) {
9413 json_object *json_es_info = NULL;
9414
9415 json_object_string_add(
9416 json_path, "esi",
9417 esi_buf);
9418 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9419 json_es_info = json_object_new_object();
9420 if (es_local)
9421 json_object_boolean_true_add(
9422 json_es_info, "localEs");
9423 if (peer_active)
9424 json_object_boolean_true_add(
9425 json_es_info, "peerActive");
9426 if (peer_proxy)
9427 json_object_boolean_true_add(
9428 json_es_info, "peerProxy");
9429 if (peer_router)
9430 json_object_boolean_true_add(
9431 json_es_info, "peerRouter");
9432 if (attr->mm_sync_seqnum)
9433 json_object_int_add(
9434 json_es_info, "peerSeq",
9435 attr->mm_sync_seqnum);
9436 json_object_object_add(
9437 json_path, "es_info",
9438 json_es_info);
9439 }
9440 } else {
9441 if (bgp_evpn_attr_is_sync(attr))
9442 vty_out(vty,
9443 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9444 esi_buf,
9445 es_local ? "local-es":"",
9446 peer_proxy ? "proxy " : "",
9447 peer_active ? "active ":"",
9448 peer_router ? "router ":"",
9449 attr->mm_sync_seqnum);
9450 else
9451 vty_out(vty, " ESI %s %s\n",
9452 esi_buf,
9453 es_local ? "local-es":"");
9454 }
9455}
9456
9457void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9458 struct bgp_dest *bn, struct bgp_path_info *path,
9459 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9460{
9461 char buf[INET6_ADDRSTRLEN];
9462 char buf1[BUFSIZ];
515c2602 9463 struct attr *attr = path->attr;
d62a17ae 9464 int sockunion_vty_out(struct vty *, union sockunion *);
9465 time_t tbuf;
9466 json_object *json_bestpath = NULL;
9467 json_object *json_cluster_list = NULL;
9468 json_object *json_cluster_list_list = NULL;
9469 json_object *json_ext_community = NULL;
9470 json_object *json_last_update = NULL;
7fd077aa 9471 json_object *json_pmsi = NULL;
d62a17ae 9472 json_object *json_nexthop_global = NULL;
9473 json_object *json_nexthop_ll = NULL;
9474 json_object *json_nexthops = NULL;
9475 json_object *json_path = NULL;
9476 json_object *json_peer = NULL;
9477 json_object *json_string = NULL;
9478 json_object *json_adv_to = NULL;
9479 int first = 0;
9480 struct listnode *node, *nnode;
9481 struct peer *peer;
9482 int addpath_capable;
9483 int has_adj;
9484 unsigned int first_as;
1defdda8 9485 bool nexthop_self =
9b6d8fcf 9486 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9487 int i;
2ba93fd6
DA
9488 char *nexthop_hostname =
9489 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9490
9491 if (json_paths) {
9492 json_path = json_object_new_object();
9493 json_peer = json_object_new_object();
9494 json_nexthop_global = json_object_new_object();
9495 }
9496
44c69747 9497 if (path->extra) {
b57ba6d2 9498 char tag_buf[30];
d62a17ae 9499
d62a17ae 9500 tag_buf[0] = '\0';
9b6d8fcf
DS
9501 if (path->extra && path->extra->num_labels) {
9502 bgp_evpn_label2str(path->extra->label,
9503 path->extra->num_labels, tag_buf,
a4d82a8a 9504 sizeof(tag_buf));
d62a17ae 9505 }
d7325ee7 9506 if (safi == SAFI_EVPN) {
44c69747 9507 if (!json_paths) {
2dbe669b
DA
9508 vty_out(vty, " Route %pFX",
9509 (struct prefix_evpn *)
9510 bgp_dest_get_prefix(bn));
44c69747
LK
9511 if (tag_buf[0] != '\0')
9512 vty_out(vty, " VNI %s", tag_buf);
9513 vty_out(vty, "\n");
9514 } else {
9515 if (tag_buf[0])
9516 json_object_string_add(json_path, "VNI",
9517 tag_buf);
9518 }
d7325ee7
DD
9519 }
9520
44c69747 9521 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9522 struct bgp_path_info *parent_ri;
9bcb3eef 9523 struct bgp_dest *dest, *pdest;
d62a17ae 9524
9b6d8fcf 9525 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9526 dest = parent_ri->net;
9527 if (dest && dest->pdest) {
9528 pdest = dest->pdest;
9529 prefix_rd2str(
9530 (struct prefix_rd *)bgp_dest_get_prefix(
9531 pdest),
9532 buf1, sizeof(buf1));
d7325ee7 9533 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9534 vty_out(vty,
9535 " Imported from %s:%pFX, VNI %s\n",
9536 buf1,
9537 (struct prefix_evpn *)
9538 bgp_dest_get_prefix(
9539 dest),
9540 tag_buf);
d7325ee7 9541 } else
2dbe669b
DA
9542 vty_out(vty,
9543 " Imported from %s:%pFX\n",
9544 buf1,
9545 (struct prefix_evpn *)
9546 bgp_dest_get_prefix(
9547 dest));
d62a17ae 9548 }
9549 }
9550 }
d62a17ae 9551
05864da7
DS
9552 /* Line1 display AS-path, Aggregator */
9553 if (attr->aspath) {
9554 if (json_paths) {
9555 if (!attr->aspath->json)
9556 aspath_str_update(attr->aspath, true);
9557 json_object_lock(attr->aspath->json);
9558 json_object_object_add(json_path, "aspath",
9559 attr->aspath->json);
9560 } else {
9561 if (attr->aspath->segments)
9562 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9563 else
05864da7 9564 vty_out(vty, " Local");
d62a17ae 9565 }
05864da7 9566 }
d62a17ae 9567
05864da7
DS
9568 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9569 if (json_paths)
9570 json_object_boolean_true_add(json_path, "removed");
9571 else
9572 vty_out(vty, ", (removed)");
9573 }
d62a17ae 9574
05864da7
DS
9575 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9576 if (json_paths)
9577 json_object_boolean_true_add(json_path, "stale");
9578 else
9579 vty_out(vty, ", (stale)");
9580 }
d62a17ae 9581
05864da7
DS
9582 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9583 if (json_paths) {
23d0a753
DA
9584 char buf[BUFSIZ] = {0};
9585
05864da7
DS
9586 json_object_int_add(json_path, "aggregatorAs",
9587 attr->aggregator_as);
23d0a753
DA
9588 json_object_string_add(json_path, "aggregatorId",
9589 inet_ntop(AF_INET,
9590 &attr->aggregator_addr,
9591 buf, sizeof(buf)));
87c82131
DA
9592 if (attr->aggregator_as == BGP_AS_ZERO)
9593 json_object_boolean_true_add(
9594 json_path, "aggregatorAsMalformed");
9595 else
9596 json_object_boolean_false_add(
9597 json_path, "aggregatorAsMalformed");
05864da7 9598 } else {
87c82131
DA
9599 if (attr->aggregator_as == BGP_AS_ZERO)
9600 vty_out(vty,
23d0a753 9601 ", (aggregated by %u(malformed) %pI4)",
87c82131 9602 attr->aggregator_as,
23d0a753 9603 &attr->aggregator_addr);
87c82131 9604 else
23d0a753 9605 vty_out(vty, ", (aggregated by %u %pI4)",
87c82131 9606 attr->aggregator_as,
23d0a753 9607 &attr->aggregator_addr);
d62a17ae 9608 }
05864da7 9609 }
d62a17ae 9610
05864da7
DS
9611 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9612 PEER_FLAG_REFLECTOR_CLIENT)) {
9613 if (json_paths)
9614 json_object_boolean_true_add(json_path,
9615 "rxedFromRrClient");
9616 else
9617 vty_out(vty, ", (Received from a RR-client)");
9618 }
d62a17ae 9619
05864da7
DS
9620 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9621 PEER_FLAG_RSERVER_CLIENT)) {
9622 if (json_paths)
9623 json_object_boolean_true_add(json_path,
9624 "rxedFromRsClient");
9625 else
9626 vty_out(vty, ", (Received from a RS-client)");
9627 }
d62a17ae 9628
05864da7
DS
9629 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9630 if (json_paths)
9631 json_object_boolean_true_add(json_path,
9632 "dampeningHistoryEntry");
9633 else
9634 vty_out(vty, ", (history entry)");
9635 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9636 if (json_paths)
9637 json_object_boolean_true_add(json_path,
9638 "dampeningSuppressed");
9639 else
9640 vty_out(vty, ", (suppressed due to dampening)");
9641 }
d62a17ae 9642
05864da7
DS
9643 if (!json_paths)
9644 vty_out(vty, "\n");
d62a17ae 9645
05864da7
DS
9646 /* Line2 display Next-hop, Neighbor, Router-id */
9647 /* Display the nexthop */
9bcb3eef 9648 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9649
9650 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9651 || bn_p->family == AF_EVPN)
05864da7
DS
9652 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9653 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9654 char buf[BUFSIZ] = {0};
9655
05864da7
DS
9656 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9657 || safi == SAFI_EVPN) {
515c2602 9658 if (json_paths) {
d62a17ae 9659 json_object_string_add(
515c2602 9660 json_nexthop_global, "ip",
23d0a753
DA
9661 inet_ntop(AF_INET,
9662 &attr->mp_nexthop_global_in,
9663 buf, sizeof(buf)));
515c2602 9664
939a97f4 9665 if (path->peer->hostname)
515c2602
DA
9666 json_object_string_add(
9667 json_nexthop_global, "hostname",
939a97f4 9668 path->peer->hostname);
aef999a2
DA
9669 } else {
9670 if (nexthop_hostname)
9671 vty_out(vty, " %pI4(%s)",
9672 &attr->mp_nexthop_global_in,
9673 nexthop_hostname);
9674 else
9675 vty_out(vty, " %pI4",
9676 &attr->mp_nexthop_global_in);
9677 }
d62a17ae 9678 } else {
515c2602 9679 if (json_paths) {
05864da7 9680 json_object_string_add(
515c2602 9681 json_nexthop_global, "ip",
23d0a753
DA
9682 inet_ntop(AF_INET, &attr->nexthop, buf,
9683 sizeof(buf)));
515c2602 9684
939a97f4 9685 if (path->peer->hostname)
515c2602
DA
9686 json_object_string_add(
9687 json_nexthop_global, "hostname",
939a97f4 9688 path->peer->hostname);
aef999a2
DA
9689 } else {
9690 if (nexthop_hostname)
9691 vty_out(vty, " %pI4(%s)",
9692 &attr->nexthop,
9693 nexthop_hostname);
9694 else
9695 vty_out(vty, " %pI4",
9696 &attr->nexthop);
9697 }
d62a17ae 9698 }
9699
05864da7
DS
9700 if (json_paths)
9701 json_object_string_add(json_nexthop_global, "afi",
9702 "ipv4");
9703 } else {
9704 if (json_paths) {
9705 json_object_string_add(
515c2602
DA
9706 json_nexthop_global, "ip",
9707 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9708 buf, INET6_ADDRSTRLEN));
9709
939a97f4 9710 if (path->peer->hostname)
515c2602
DA
9711 json_object_string_add(json_nexthop_global,
9712 "hostname",
939a97f4 9713 path->peer->hostname);
515c2602 9714
05864da7
DS
9715 json_object_string_add(json_nexthop_global, "afi",
9716 "ipv6");
9717 json_object_string_add(json_nexthop_global, "scope",
9718 "global");
9719 } else {
aef999a2
DA
9720 if (nexthop_hostname)
9721 vty_out(vty, " %pI6(%s)",
9722 &attr->mp_nexthop_global,
9723 nexthop_hostname);
9724 else
9725 vty_out(vty, " %pI6",
9726 &attr->mp_nexthop_global);
d62a17ae 9727 }
05864da7 9728 }
d62a17ae 9729
05864da7
DS
9730 /* Display the IGP cost or 'inaccessible' */
9731 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9732 if (json_paths)
9733 json_object_boolean_false_add(json_nexthop_global,
9734 "accessible");
9735 else
9736 vty_out(vty, " (inaccessible)");
9737 } else {
9738 if (path->extra && path->extra->igpmetric) {
d62a17ae 9739 if (json_paths)
05864da7
DS
9740 json_object_int_add(json_nexthop_global,
9741 "metric",
9742 path->extra->igpmetric);
d62a17ae 9743 else
05864da7
DS
9744 vty_out(vty, " (metric %u)",
9745 path->extra->igpmetric);
d62a17ae 9746 }
9747
05864da7 9748 /* IGP cost is 0, display this only for json */
d62a17ae 9749 else {
d62a17ae 9750 if (json_paths)
05864da7
DS
9751 json_object_int_add(json_nexthop_global,
9752 "metric", 0);
d62a17ae 9753 }
d62a17ae 9754
05864da7
DS
9755 if (json_paths)
9756 json_object_boolean_true_add(json_nexthop_global,
9757 "accessible");
9758 }
d62a17ae 9759
05864da7
DS
9760 /* Display peer "from" output */
9761 /* This path was originated locally */
9762 if (path->peer == bgp->peer_self) {
d62a17ae 9763
05864da7 9764 if (safi == SAFI_EVPN
b54892e0 9765 || (bn_p->family == AF_INET
05864da7 9766 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9767 if (json_paths)
05864da7
DS
9768 json_object_string_add(json_peer, "peerId",
9769 "0.0.0.0");
d62a17ae 9770 else
05864da7
DS
9771 vty_out(vty, " from 0.0.0.0 ");
9772 } else {
d62a17ae 9773 if (json_paths)
05864da7
DS
9774 json_object_string_add(json_peer, "peerId",
9775 "::");
d62a17ae 9776 else
05864da7 9777 vty_out(vty, " from :: ");
d62a17ae 9778 }
d62a17ae 9779
23d0a753
DA
9780 if (json_paths) {
9781 char buf[BUFSIZ] = {0};
9782
05864da7 9783 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9784 inet_ntop(AF_INET,
9785 &bgp->router_id, buf,
9786 sizeof(buf)));
9787 } else {
9788 vty_out(vty, "(%pI4)", &bgp->router_id);
9789 }
05864da7 9790 }
d62a17ae 9791
05864da7
DS
9792 /* We RXed this path from one of our peers */
9793 else {
9794
9795 if (json_paths) {
9796 json_object_string_add(json_peer, "peerId",
9797 sockunion2str(&path->peer->su,
9798 buf,
9799 SU_ADDRSTRLEN));
9800 json_object_string_add(json_peer, "routerId",
9801 inet_ntop(AF_INET,
9802 &path->peer->remote_id,
9803 buf1, sizeof(buf1)));
9804
9805 if (path->peer->hostname)
9806 json_object_string_add(json_peer, "hostname",
9807 path->peer->hostname);
9808
9809 if (path->peer->domainname)
9810 json_object_string_add(json_peer, "domainname",
9811 path->peer->domainname);
9812
9813 if (path->peer->conf_if)
9814 json_object_string_add(json_peer, "interface",
9815 path->peer->conf_if);
9816 } else {
9817 if (path->peer->conf_if) {
9818 if (path->peer->hostname
892fedb6
DA
9819 && CHECK_FLAG(path->peer->bgp->flags,
9820 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9821 vty_out(vty, " from %s(%s)",
9822 path->peer->hostname,
9823 path->peer->conf_if);
d62a17ae 9824 else
05864da7 9825 vty_out(vty, " from %s",
9b6d8fcf 9826 path->peer->conf_if);
d62a17ae 9827 } else {
05864da7 9828 if (path->peer->hostname
892fedb6
DA
9829 && CHECK_FLAG(path->peer->bgp->flags,
9830 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9831 vty_out(vty, " from %s(%s)",
9832 path->peer->hostname,
9833 path->peer->host);
d62a17ae 9834 else
05864da7
DS
9835 vty_out(vty, " from %s",
9836 sockunion2str(&path->peer->su,
9837 buf,
9838 SU_ADDRSTRLEN));
d62a17ae 9839 }
d62a17ae 9840
05864da7 9841 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9842 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9843 else
9844 vty_out(vty, " (%s)",
9845 inet_ntop(AF_INET,
9846 &path->peer->remote_id, buf1,
9847 sizeof(buf1)));
d62a17ae 9848 }
05864da7 9849 }
9df8b37c 9850
05864da7
DS
9851 /*
9852 * Note when vrfid of nexthop is different from that of prefix
9853 */
9854 if (path->extra && path->extra->bgp_orig) {
9855 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9856
05864da7
DS
9857 if (json_paths) {
9858 const char *vn;
9df8b37c 9859
05864da7
DS
9860 if (path->extra->bgp_orig->inst_type
9861 == BGP_INSTANCE_TYPE_DEFAULT)
9862 vn = VRF_DEFAULT_NAME;
9863 else
9864 vn = path->extra->bgp_orig->name;
9df8b37c 9865
05864da7 9866 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9867
05864da7
DS
9868 if (nexthop_vrfid == VRF_UNKNOWN) {
9869 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9870 } else {
05864da7
DS
9871 json_object_int_add(json_path, "nhVrfId",
9872 (int)nexthop_vrfid);
9df8b37c 9873 }
05864da7
DS
9874 } else {
9875 if (nexthop_vrfid == VRF_UNKNOWN)
9876 vty_out(vty, " vrf ?");
137147c6
DS
9877 else {
9878 struct vrf *vrf;
9879
9880 vrf = vrf_lookup_by_id(nexthop_vrfid);
9881 vty_out(vty, " vrf %s(%u)",
9882 VRF_LOGNAME(vrf), nexthop_vrfid);
9883 }
9df8b37c 9884 }
05864da7 9885 }
9df8b37c 9886
05864da7
DS
9887 if (nexthop_self) {
9888 if (json_paths) {
9889 json_object_boolean_true_add(json_path,
9890 "announceNexthopSelf");
9891 } else {
9892 vty_out(vty, " announce-nh-self");
9df8b37c 9893 }
05864da7 9894 }
9df8b37c 9895
05864da7
DS
9896 if (!json_paths)
9897 vty_out(vty, "\n");
d62a17ae 9898
05864da7
DS
9899 /* display the link-local nexthop */
9900 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9901 if (json_paths) {
9902 json_nexthop_ll = json_object_new_object();
9903 json_object_string_add(
515c2602
DA
9904 json_nexthop_ll, "ip",
9905 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9906 buf, INET6_ADDRSTRLEN));
9907
939a97f4 9908 if (path->peer->hostname)
515c2602
DA
9909 json_object_string_add(json_nexthop_ll,
9910 "hostname",
939a97f4 9911 path->peer->hostname);
515c2602 9912
05864da7
DS
9913 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9914 json_object_string_add(json_nexthop_ll, "scope",
9915 "link-local");
d62a17ae 9916
05864da7
DS
9917 json_object_boolean_true_add(json_nexthop_ll,
9918 "accessible");
d62a17ae 9919
05864da7 9920 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9921 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9922 "used");
9923 else
9924 json_object_boolean_true_add(
9925 json_nexthop_global, "used");
9926 } else {
9927 vty_out(vty, " (%s) %s\n",
9928 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9929 buf, INET6_ADDRSTRLEN),
9930 attr->mp_nexthop_prefer_global
9931 ? "(prefer-global)"
9932 : "(used)");
d62a17ae 9933 }
05864da7
DS
9934 }
9935 /* If we do not have a link-local nexthop then we must flag the
9936 global as "used" */
9937 else {
9938 if (json_paths)
9939 json_object_boolean_true_add(json_nexthop_global,
9940 "used");
9941 }
d62a17ae 9942
b5e140c8 9943 if (safi == SAFI_EVPN &&
5e4d4c8a 9944 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9945 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
9946 }
9947
05864da7
DS
9948 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9949 * Int/Ext/Local, Atomic, best */
9950 if (json_paths)
9951 json_object_string_add(json_path, "origin",
9952 bgp_origin_long_str[attr->origin]);
9953 else
9954 vty_out(vty, " Origin %s",
9955 bgp_origin_long_str[attr->origin]);
9df8b37c 9956
05864da7 9957 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9958 if (json_paths)
05864da7 9959 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9960 else
05864da7
DS
9961 vty_out(vty, ", metric %u", attr->med);
9962 }
9df8b37c 9963
05864da7
DS
9964 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9965 if (json_paths)
0fbac0b4 9966 json_object_int_add(json_path, "locPrf",
05864da7
DS
9967 attr->local_pref);
9968 else
9969 vty_out(vty, ", localpref %u", attr->local_pref);
9970 }
9df8b37c 9971
05864da7
DS
9972 if (attr->weight != 0) {
9973 if (json_paths)
9974 json_object_int_add(json_path, "weight", attr->weight);
9975 else
9976 vty_out(vty, ", weight %u", attr->weight);
9977 }
9df8b37c 9978
05864da7
DS
9979 if (attr->tag != 0) {
9980 if (json_paths)
9981 json_object_int_add(json_path, "tag", attr->tag);
9982 else
9983 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9984 }
9df8b37c 9985
05864da7
DS
9986 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9987 if (json_paths)
9988 json_object_boolean_false_add(json_path, "valid");
9989 else
9990 vty_out(vty, ", invalid");
9991 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9992 if (json_paths)
9993 json_object_boolean_true_add(json_path, "valid");
9994 else
9995 vty_out(vty, ", valid");
9996 }
9df8b37c 9997
05864da7
DS
9998 if (path->peer != bgp->peer_self) {
9999 if (path->peer->as == path->peer->local_as) {
10000 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10001 if (json_paths)
10002 json_object_string_add(
10003 json_peer, "type",
10004 "confed-internal");
d62a17ae 10005 else
05864da7 10006 vty_out(vty, ", confed-internal");
d62a17ae 10007 } else {
05864da7
DS
10008 if (json_paths)
10009 json_object_string_add(
10010 json_peer, "type", "internal");
10011 else
10012 vty_out(vty, ", internal");
9df8b37c 10013 }
05864da7
DS
10014 } else {
10015 if (bgp_confederation_peers_check(bgp,
10016 path->peer->as)) {
10017 if (json_paths)
10018 json_object_string_add(
10019 json_peer, "type",
10020 "confed-external");
d62a17ae 10021 else
05864da7 10022 vty_out(vty, ", confed-external");
d62a17ae 10023 } else {
05864da7
DS
10024 if (json_paths)
10025 json_object_string_add(
10026 json_peer, "type", "external");
10027 else
10028 vty_out(vty, ", external");
d62a17ae 10029 }
10030 }
05864da7
DS
10031 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10032 if (json_paths) {
10033 json_object_boolean_true_add(json_path, "aggregated");
10034 json_object_boolean_true_add(json_path, "local");
10035 } else {
10036 vty_out(vty, ", aggregated, local");
10037 }
10038 } else if (path->type != ZEBRA_ROUTE_BGP) {
10039 if (json_paths)
10040 json_object_boolean_true_add(json_path, "sourced");
10041 else
10042 vty_out(vty, ", sourced");
10043 } else {
10044 if (json_paths) {
10045 json_object_boolean_true_add(json_path, "sourced");
10046 json_object_boolean_true_add(json_path, "local");
10047 } else {
10048 vty_out(vty, ", sourced, local");
d62a17ae 10049 }
05864da7 10050 }
718e3744 10051
05864da7 10052 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10053 if (json_paths)
05864da7
DS
10054 json_object_boolean_true_add(json_path,
10055 "atomicAggregate");
d62a17ae 10056 else
05864da7
DS
10057 vty_out(vty, ", atomic-aggregate");
10058 }
d62a17ae 10059
05864da7
DS
10060 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10061 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10062 && bgp_path_info_mpath_count(path))) {
10063 if (json_paths)
10064 json_object_boolean_true_add(json_path, "multipath");
10065 else
10066 vty_out(vty, ", multipath");
10067 }
50e05855 10068
05864da7
DS
10069 // Mark the bestpath(s)
10070 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10071 first_as = aspath_get_first_as(attr->aspath);
718e3744 10072
05864da7
DS
10073 if (json_paths) {
10074 if (!json_bestpath)
10075 json_bestpath = json_object_new_object();
10076 json_object_int_add(json_bestpath, "bestpathFromAs",
10077 first_as);
10078 } else {
10079 if (first_as)
10080 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10081 else
05864da7 10082 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10083 }
05864da7 10084 }
718e3744 10085
05864da7
DS
10086 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10087 if (json_paths) {
10088 if (!json_bestpath)
10089 json_bestpath = json_object_new_object();
10090 json_object_boolean_true_add(json_bestpath, "overall");
10091 json_object_string_add(
10092 json_bestpath, "selectionReason",
10093 bgp_path_selection_reason2str(bn->reason));
10094 } else {
10095 vty_out(vty, ", best");
10096 vty_out(vty, " (%s)",
10097 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10098 }
05864da7 10099 }
718e3744 10100
05864da7
DS
10101 if (json_bestpath)
10102 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10103
05864da7
DS
10104 if (!json_paths)
10105 vty_out(vty, "\n");
10106
10107 /* Line 4 display Community */
10108 if (attr->community) {
10109 if (json_paths) {
10110 if (!attr->community->json)
10111 community_str(attr->community, true);
10112 json_object_lock(attr->community->json);
10113 json_object_object_add(json_path, "community",
10114 attr->community->json);
10115 } else {
10116 vty_out(vty, " Community: %s\n",
10117 attr->community->str);
d62a17ae 10118 }
05864da7 10119 }
718e3744 10120
05864da7
DS
10121 /* Line 5 display Extended-community */
10122 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10123 if (json_paths) {
10124 json_ext_community = json_object_new_object();
10125 json_object_string_add(json_ext_community, "string",
10126 attr->ecommunity->str);
10127 json_object_object_add(json_path, "extendedCommunity",
10128 json_ext_community);
d62a17ae 10129 } else {
05864da7
DS
10130 vty_out(vty, " Extended Community: %s\n",
10131 attr->ecommunity->str);
d62a17ae 10132 }
05864da7 10133 }
718e3744 10134
05864da7
DS
10135 /* Line 6 display Large community */
10136 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10137 if (json_paths) {
10138 if (!attr->lcommunity->json)
10139 lcommunity_str(attr->lcommunity, true);
10140 json_object_lock(attr->lcommunity->json);
10141 json_object_object_add(json_path, "largeCommunity",
10142 attr->lcommunity->json);
10143 } else {
10144 vty_out(vty, " Large Community: %s\n",
10145 attr->lcommunity->str);
d62a17ae 10146 }
05864da7 10147 }
718e3744 10148
05864da7
DS
10149 /* Line 7 display Originator, Cluster-id */
10150 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10151 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10152 char buf[BUFSIZ] = {0};
10153
05864da7 10154 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10155 if (json_paths)
05864da7
DS
10156 json_object_string_add(
10157 json_path, "originatorId",
23d0a753
DA
10158 inet_ntop(AF_INET, &attr->originator_id,
10159 buf, sizeof(buf)));
d62a17ae 10160 else
23d0a753
DA
10161 vty_out(vty, " Originator: %pI4",
10162 &attr->originator_id);
d62a17ae 10163 }
856ca177 10164
05864da7 10165 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10166 struct cluster_list *cluster =
10167 bgp_attr_get_cluster(attr);
05864da7 10168 int i;
d62a17ae 10169
10170 if (json_paths) {
05864da7
DS
10171 json_cluster_list = json_object_new_object();
10172 json_cluster_list_list =
10173 json_object_new_array();
10174
779fee93 10175 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10176 json_string = json_object_new_string(
779fee93
DS
10177 inet_ntop(AF_INET,
10178 &cluster->list[i],
10179 buf, sizeof(buf)));
05864da7
DS
10180 json_object_array_add(
10181 json_cluster_list_list,
10182 json_string);
10183 }
718e3744 10184
05864da7
DS
10185 /*
10186 * struct cluster_list does not have
10187 * "str" variable like aspath and community
10188 * do. Add this someday if someone asks
10189 * for it.
10190 * json_object_string_add(json_cluster_list,
779fee93 10191 * "string", cluster->str);
05864da7
DS
10192 */
10193 json_object_object_add(json_cluster_list,
10194 "list",
10195 json_cluster_list_list);
10196 json_object_object_add(json_path, "clusterList",
10197 json_cluster_list);
0dc8ee70 10198 } else {
05864da7
DS
10199 vty_out(vty, ", Cluster list: ");
10200
779fee93 10201 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10202 vty_out(vty, "%pI4 ",
779fee93 10203 &cluster->list[i]);
05864da7 10204 }
0dc8ee70 10205 }
d62a17ae 10206 }
718e3744 10207
d62a17ae 10208 if (!json_paths)
10209 vty_out(vty, "\n");
05864da7 10210 }
d62a17ae 10211
05864da7 10212 if (path->extra && path->extra->damp_info)
40ec3340 10213 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10214
05864da7
DS
10215 /* Remote Label */
10216 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10217 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10218 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10219
05864da7
DS
10220 if (json_paths)
10221 json_object_int_add(json_path, "remoteLabel", label);
10222 else
10223 vty_out(vty, " Remote label: %d\n", label);
10224 }
d62a17ae 10225
e496b420
HS
10226 /* Remote SID */
10227 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10228 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10229 if (json_paths)
10230 json_object_string_add(json_path, "remoteSid", buf);
10231 else
10232 vty_out(vty, " Remote SID: %s\n", buf);
10233 }
10234
05864da7
DS
10235 /* Label Index */
10236 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10237 if (json_paths)
10238 json_object_int_add(json_path, "labelIndex",
10239 attr->label_index);
10240 else
10241 vty_out(vty, " Label Index: %d\n",
10242 attr->label_index);
10243 }
d62a17ae 10244
05864da7
DS
10245 /* Line 8 display Addpath IDs */
10246 if (path->addpath_rx_id
10247 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10248 if (json_paths) {
10249 json_object_int_add(json_path, "addpathRxId",
10250 path->addpath_rx_id);
d62a17ae 10251
05864da7
DS
10252 /* Keep backwards compatibility with the old API
10253 * by putting TX All's ID in the old field
10254 */
10255 json_object_int_add(
10256 json_path, "addpathTxId",
10257 path->tx_addpath
10258 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10259
05864da7
DS
10260 /* ... but create a specific field for each
10261 * strategy
10262 */
10263 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10264 json_object_int_add(
10265 json_path,
10266 bgp_addpath_names(i)->id_json_name,
10267 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10268 }
05864da7
DS
10269 } else {
10270 vty_out(vty, " AddPath ID: RX %u, ",
10271 path->addpath_rx_id);
d62a17ae 10272
05864da7 10273 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10274 }
05864da7 10275 }
520d5d76 10276
05864da7
DS
10277 /* If we used addpath to TX a non-bestpath we need to display
10278 * "Advertised to" on a path-by-path basis
10279 */
10280 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10281 first = 1;
dcc68b5e 10282
05864da7
DS
10283 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10284 addpath_capable =
10285 bgp_addpath_encode_tx(peer, afi, safi);
10286 has_adj = bgp_adj_out_lookup(
10287 peer, path->net,
10288 bgp_addpath_id_for_peer(peer, afi, safi,
10289 &path->tx_addpath));
10290
10291 if ((addpath_capable && has_adj)
10292 || (!addpath_capable && has_adj
10293 && CHECK_FLAG(path->flags,
10294 BGP_PATH_SELECTED))) {
10295 if (json_path && !json_adv_to)
10296 json_adv_to = json_object_new_object();
dcc68b5e 10297
05864da7
DS
10298 route_vty_out_advertised_to(
10299 vty, peer, &first,
10300 " Advertised to:", json_adv_to);
d62a17ae 10301 }
10302 }
718e3744 10303
05864da7
DS
10304 if (json_path) {
10305 if (json_adv_to) {
10306 json_object_object_add(
10307 json_path, "advertisedTo", json_adv_to);
d62a17ae 10308 }
05864da7
DS
10309 } else {
10310 if (!first) {
10311 vty_out(vty, "\n");
d62a17ae 10312 }
10313 }
05864da7 10314 }
b05a1c8b 10315
05864da7
DS
10316 /* Line 9 display Uptime */
10317 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10318 if (json_paths) {
10319 json_last_update = json_object_new_object();
10320 json_object_int_add(json_last_update, "epoch", tbuf);
10321 json_object_string_add(json_last_update, "string",
10322 ctime(&tbuf));
10323 json_object_object_add(json_path, "lastUpdate",
10324 json_last_update);
10325 } else
10326 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10327
05864da7
DS
10328 /* Line 10 display PMSI tunnel attribute, if present */
10329 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10330 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10331 bgp_attr_get_pmsi_tnl_type(attr),
10332 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10333
05864da7
DS
10334 if (json_paths) {
10335 json_pmsi = json_object_new_object();
10336 json_object_string_add(json_pmsi, "tunnelType", str);
10337 json_object_int_add(json_pmsi, "label",
10338 label2vni(&attr->label));
10339 json_object_object_add(json_path, "pmsi", json_pmsi);
10340 } else
10341 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10342 str, label2vni(&attr->label));
d62a17ae 10343 }
f1aa5d8a 10344
92269aa2
DS
10345 /* Output some debug about internal state of the dest flags */
10346 if (json_paths) {
10347 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10348 json_object_boolean_true_add(json_path, "processScheduled");
10349 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10350 json_object_boolean_true_add(json_path, "userCleared");
10351 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10352 json_object_boolean_true_add(json_path, "labelChanged");
10353 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10354 json_object_boolean_true_add(json_path, "registeredForLabel");
10355 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10356 json_object_boolean_true_add(json_path, "selectDefered");
10357 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10358 json_object_boolean_true_add(json_path, "fibInstalled");
10359 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10360 json_object_boolean_true_add(json_path, "fibPending");
10361 }
10362
d62a17ae 10363 /* We've constructed the json object for this path, add it to the json
10364 * array of paths
10365 */
10366 if (json_paths) {
10367 if (json_nexthop_global || json_nexthop_ll) {
10368 json_nexthops = json_object_new_array();
f1aa5d8a 10369
d62a17ae 10370 if (json_nexthop_global)
10371 json_object_array_add(json_nexthops,
10372 json_nexthop_global);
f1aa5d8a 10373
d62a17ae 10374 if (json_nexthop_ll)
10375 json_object_array_add(json_nexthops,
10376 json_nexthop_ll);
f1aa5d8a 10377
d62a17ae 10378 json_object_object_add(json_path, "nexthops",
10379 json_nexthops);
10380 }
10381
10382 json_object_object_add(json_path, "peer", json_peer);
10383 json_object_array_add(json_paths, json_path);
05864da7 10384 }
b366b518
BB
10385}
10386
96ade3ed 10387#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10388#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10389#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10390
d62a17ae 10391static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10392 const char *prefix_list_str, afi_t afi,
10393 safi_t safi, enum bgp_show_type type);
10394static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10395 const char *filter, afi_t afi, safi_t safi,
10396 enum bgp_show_type type);
10397static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10398 const char *rmap_str, afi_t afi, safi_t safi,
10399 enum bgp_show_type type);
10400static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10401 const char *com, int exact, afi_t afi,
10402 safi_t safi);
10403static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10404 const char *prefix, afi_t afi, safi_t safi,
10405 enum bgp_show_type type);
a4d82a8a 10406static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10407 afi_t afi, safi_t safi, enum bgp_show_type type,
10408 bool use_json);
7f323236
DW
10409static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10410 const char *comstr, int exact, afi_t afi,
96f3485c 10411 safi_t safi, uint8_t show_flags);
d62a17ae 10412
1ae44dfc
LB
10413
10414static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10415 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10416 void *output_arg, char *rd, int is_last,
10417 unsigned long *output_cum, unsigned long *total_cum,
10418 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10419{
40381db7 10420 struct bgp_path_info *pi;
9bcb3eef 10421 struct bgp_dest *dest;
d62a17ae 10422 int header = 1;
10423 int display;
1ae44dfc
LB
10424 unsigned long output_count = 0;
10425 unsigned long total_count = 0;
d62a17ae 10426 struct prefix *p;
d62a17ae 10427 json_object *json_paths = NULL;
10428 int first = 1;
96f3485c
MK
10429 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10430 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10431 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10432
1ae44dfc
LB
10433 if (output_cum && *output_cum != 0)
10434 header = 0;
10435
9386b588 10436 if (use_json && !*json_header_depth) {
96f3485c
MK
10437 if (all)
10438 *json_header_depth = 1;
10439 else {
10440 vty_out(vty, "{\n");
10441 *json_header_depth = 2;
10442 }
10443
d62a17ae 10444 vty_out(vty,
23d0a753
DA
10445 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10446 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10447 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10448 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10449 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10450 ? VRF_DEFAULT_NAME
10451 : bgp->name,
10452 table->version, &bgp->router_id,
01eced22 10453 bgp->default_local_pref, bgp->as);
9386b588 10454 if (rd) {
445c2480 10455 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10456 ++*json_header_depth;
10457 }
d62a17ae 10458 }
718e3744 10459
445c2480
DS
10460 if (use_json && rd) {
10461 vty_out(vty, " \"%s\" : { ", rd);
10462 }
10463
d62a17ae 10464 /* Start processing of routes. */
9bcb3eef
DS
10465 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10466 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10467
9bcb3eef 10468 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10469 if (pi == NULL)
98ce9a06 10470 continue;
d62a17ae 10471
98ce9a06 10472 display = 0;
98ce9a06
DS
10473 if (use_json)
10474 json_paths = json_object_new_array();
10475 else
10476 json_paths = NULL;
d62a17ae 10477
6f94b685 10478 for (; pi; pi = pi->next) {
98ce9a06
DS
10479 total_count++;
10480 if (type == bgp_show_type_flap_statistics
10481 || type == bgp_show_type_flap_neighbor
10482 || type == bgp_show_type_dampend_paths
10483 || type == bgp_show_type_damp_neighbor) {
40381db7 10484 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10485 continue;
10486 }
10487 if (type == bgp_show_type_regexp) {
10488 regex_t *regex = output_arg;
d62a17ae 10489
40381db7 10490 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10491 == REG_NOMATCH)
10492 continue;
10493 }
10494 if (type == bgp_show_type_prefix_list) {
10495 struct prefix_list *plist = output_arg;
d62a17ae 10496
9bcb3eef 10497 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10498 != PREFIX_PERMIT)
10499 continue;
10500 }
10501 if (type == bgp_show_type_filter_list) {
10502 struct as_list *as_list = output_arg;
d62a17ae 10503
40381db7 10504 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10505 != AS_FILTER_PERMIT)
10506 continue;
10507 }
10508 if (type == bgp_show_type_route_map) {
10509 struct route_map *rmap = output_arg;
9b6d8fcf 10510 struct bgp_path_info path;
98ce9a06 10511 struct attr dummy_attr;
b68885f9 10512 route_map_result_t ret;
d62a17ae 10513
6f4f49b2 10514 dummy_attr = *pi->attr;
d62a17ae 10515
40381db7 10516 path.peer = pi->peer;
9b6d8fcf 10517 path.attr = &dummy_attr;
d62a17ae 10518
1782514f 10519 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10520 if (ret == RMAP_DENYMATCH)
10521 continue;
10522 }
10523 if (type == bgp_show_type_neighbor
10524 || type == bgp_show_type_flap_neighbor
10525 || type == bgp_show_type_damp_neighbor) {
10526 union sockunion *su = output_arg;
10527
40381db7
DS
10528 if (pi->peer == NULL
10529 || pi->peer->su_remote == NULL
10530 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10531 continue;
10532 }
10533 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10534 uint32_t destination;
d62a17ae 10535
9bcb3eef 10536 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10537 if (IN_CLASSC(destination)
9bcb3eef 10538 && dest_p->prefixlen == 24)
98ce9a06
DS
10539 continue;
10540 if (IN_CLASSB(destination)
9bcb3eef 10541 && dest_p->prefixlen == 16)
98ce9a06
DS
10542 continue;
10543 if (IN_CLASSA(destination)
9bcb3eef 10544 && dest_p->prefixlen == 8)
98ce9a06
DS
10545 continue;
10546 }
10547 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10548 p = output_arg;
9bcb3eef 10549 if (!prefix_match(p, dest_p))
98ce9a06
DS
10550 continue;
10551 }
10552 if (type == bgp_show_type_community_all) {
40381db7 10553 if (!pi->attr->community)
98ce9a06
DS
10554 continue;
10555 }
10556 if (type == bgp_show_type_community) {
10557 struct community *com = output_arg;
d62a17ae 10558
40381db7
DS
10559 if (!pi->attr->community
10560 || !community_match(pi->attr->community,
98ce9a06
DS
10561 com))
10562 continue;
10563 }
10564 if (type == bgp_show_type_community_exact) {
10565 struct community *com = output_arg;
d62a17ae 10566
40381db7
DS
10567 if (!pi->attr->community
10568 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10569 continue;
10570 }
10571 if (type == bgp_show_type_community_list) {
10572 struct community_list *list = output_arg;
d62a17ae 10573
40381db7 10574 if (!community_list_match(pi->attr->community,
a4d82a8a 10575 list))
98ce9a06
DS
10576 continue;
10577 }
a4d82a8a 10578 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10579 struct community_list *list = output_arg;
d62a17ae 10580
98ce9a06 10581 if (!community_list_exact_match(
40381db7 10582 pi->attr->community, list))
98ce9a06
DS
10583 continue;
10584 }
10585 if (type == bgp_show_type_lcommunity) {
10586 struct lcommunity *lcom = output_arg;
d62a17ae 10587
40381db7
DS
10588 if (!pi->attr->lcommunity
10589 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10590 lcom))
10591 continue;
10592 }
36a206db 10593
10594 if (type == bgp_show_type_lcommunity_exact) {
10595 struct lcommunity *lcom = output_arg;
10596
10597 if (!pi->attr->lcommunity
10598 || !lcommunity_cmp(pi->attr->lcommunity,
10599 lcom))
10600 continue;
10601 }
98ce9a06
DS
10602 if (type == bgp_show_type_lcommunity_list) {
10603 struct community_list *list = output_arg;
d62a17ae 10604
40381db7 10605 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10606 list))
98ce9a06
DS
10607 continue;
10608 }
36a206db 10609 if (type
10610 == bgp_show_type_lcommunity_list_exact) {
10611 struct community_list *list = output_arg;
10612
10613 if (!lcommunity_list_exact_match(
10614 pi->attr->lcommunity, list))
10615 continue;
10616 }
98ce9a06 10617 if (type == bgp_show_type_lcommunity_all) {
40381db7 10618 if (!pi->attr->lcommunity)
98ce9a06
DS
10619 continue;
10620 }
10621 if (type == bgp_show_type_dampend_paths
10622 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10623 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10624 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10625 continue;
10626 }
10627
10628 if (!use_json && header) {
23d0a753
DA
10629 vty_out(vty,
10630 "BGP table version is %" PRIu64
10631 ", local router ID is %pI4, vrf id ",
10632 table->version, &bgp->router_id);
9df8b37c
PZ
10633 if (bgp->vrf_id == VRF_UNKNOWN)
10634 vty_out(vty, "%s", VRFID_NONE_STR);
10635 else
10636 vty_out(vty, "%u", bgp->vrf_id);
10637 vty_out(vty, "\n");
01eced22
AD
10638 vty_out(vty, "Default local pref %u, ",
10639 bgp->default_local_pref);
10640 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10641 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10642 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10643 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10644 if (type == bgp_show_type_dampend_paths
10645 || type == bgp_show_type_damp_neighbor)
98ce9a06 10646 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10647 else if (type == bgp_show_type_flap_statistics
10648 || type == bgp_show_type_flap_neighbor)
98ce9a06 10649 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10650 else
ae248832
MK
10651 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10652 : BGP_SHOW_HEADER));
98ce9a06 10653 header = 0;
d62a17ae 10654 }
98ce9a06
DS
10655 if (rd != NULL && !display && !output_count) {
10656 if (!use_json)
10657 vty_out(vty,
10658 "Route Distinguisher: %s\n",
10659 rd);
d62a17ae 10660 }
98ce9a06
DS
10661 if (type == bgp_show_type_dampend_paths
10662 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10663 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10664 AFI_IP, safi, use_json,
10665 json_paths);
98ce9a06
DS
10666 else if (type == bgp_show_type_flap_statistics
10667 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10668 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10669 AFI_IP, safi, use_json,
10670 json_paths);
98ce9a06 10671 else
9bcb3eef 10672 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10673 json_paths, wide);
98ce9a06 10674 display++;
d62a17ae 10675 }
10676
98ce9a06
DS
10677 if (display) {
10678 output_count++;
10679 if (!use_json)
10680 continue;
10681
625d2931 10682 /* encode prefix */
9bcb3eef 10683 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10684 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10685
1840384b 10686
b54892e0
DS
10687 bgp_fs_nlri_get_string(
10688 (unsigned char *)
9bcb3eef
DS
10689 dest_p->u.prefix_flowspec.ptr,
10690 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10691 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10692 family2afi(dest_p->u
10693 .prefix_flowspec.family));
625d2931 10694 if (first)
b54892e0 10695 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10696 dest_p->u.prefix_flowspec
b54892e0 10697 .prefixlen);
625d2931 10698 else
b54892e0 10699 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10700 dest_p->u.prefix_flowspec
b54892e0 10701 .prefixlen);
625d2931 10702 } else {
625d2931 10703 if (first)
1b78780b 10704 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10705 else
1b78780b 10706 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10707 }
98ce9a06 10708 vty_out(vty, "%s",
f4ec52f7
DA
10709 json_object_to_json_string_ext(
10710 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10711 json_object_free(json_paths);
449feb8e 10712 json_paths = NULL;
98ce9a06 10713 first = 0;
1f83ed02
DS
10714 } else
10715 json_object_free(json_paths);
98ce9a06
DS
10716 }
10717
1ae44dfc
LB
10718 if (output_cum) {
10719 output_count += *output_cum;
10720 *output_cum = output_count;
10721 }
10722 if (total_cum) {
10723 total_count += *total_cum;
10724 *total_cum = total_count;
10725 }
d62a17ae 10726 if (use_json) {
9386b588 10727 if (rd) {
a4d82a8a 10728 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10729 }
10730 if (is_last) {
a4d82a8a
PZ
10731 unsigned long i;
10732 for (i = 0; i < *json_header_depth; ++i)
10733 vty_out(vty, " } ");
96f3485c
MK
10734 if (!all)
10735 vty_out(vty, "\n");
9386b588 10736 }
d62a17ae 10737 } else {
1ae44dfc
LB
10738 if (is_last) {
10739 /* No route is displayed */
10740 if (output_count == 0) {
10741 if (type == bgp_show_type_normal)
10742 vty_out(vty,
10743 "No BGP prefixes displayed, %ld exist\n",
10744 total_count);
10745 } else
d62a17ae 10746 vty_out(vty,
1ae44dfc
LB
10747 "\nDisplayed %ld routes and %ld total paths\n",
10748 output_count, total_count);
10749 }
d62a17ae 10750 }
718e3744 10751
d62a17ae 10752 return CMD_SUCCESS;
718e3744 10753}
10754
1ae44dfc
LB
10755int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10756 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10757 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10758{
9bcb3eef 10759 struct bgp_dest *dest, *next;
1ae44dfc
LB
10760 unsigned long output_cum = 0;
10761 unsigned long total_cum = 0;
9386b588 10762 unsigned long json_header_depth = 0;
67009e22 10763 struct bgp_table *itable;
0136788c 10764 bool show_msg;
96f3485c 10765 uint8_t show_flags = 0;
0136788c
LB
10766
10767 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10768
96f3485c
MK
10769 if (use_json)
10770 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10771
9bcb3eef
DS
10772 for (dest = bgp_table_top(table); dest; dest = next) {
10773 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10774
9bcb3eef
DS
10775 next = bgp_route_next(dest);
10776 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10777 continue;
67009e22 10778
9bcb3eef 10779 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10780 if (itable != NULL) {
1ae44dfc 10781 struct prefix_rd prd;
06b9f471 10782 char rd[RD_ADDRSTRLEN];
1ae44dfc 10783
9bcb3eef 10784 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10785 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10786 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10787 rd, next == NULL, &output_cum,
10788 &total_cum, &json_header_depth,
10789 show_flags);
0136788c
LB
10790 if (next == NULL)
10791 show_msg = false;
1ae44dfc
LB
10792 }
10793 }
0136788c
LB
10794 if (show_msg) {
10795 if (output_cum == 0)
10796 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10797 total_cum);
10798 else
10799 vty_out(vty,
10800 "\nDisplayed %ld routes and %ld total paths\n",
10801 output_cum, total_cum);
10802 }
1ae44dfc
LB
10803 return CMD_SUCCESS;
10804}
d62a17ae 10805static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10806 enum bgp_show_type type, void *output_arg,
10807 uint8_t show_flags)
fee0f4c6 10808{
d62a17ae 10809 struct bgp_table *table;
9386b588 10810 unsigned long json_header_depth = 0;
96f3485c 10811 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10812
d62a17ae 10813 if (bgp == NULL) {
10814 bgp = bgp_get_default();
10815 }
fee0f4c6 10816
d62a17ae 10817 if (bgp == NULL) {
10818 if (!use_json)
10819 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10820 else
10821 vty_out(vty, "{}\n");
d62a17ae 10822 return CMD_WARNING;
10823 }
4dd6177e 10824
1ae44dfc 10825 table = bgp->rib[afi][safi];
d62a17ae 10826 /* use MPLS and ENCAP specific shows until they are merged */
10827 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10828 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10829 output_arg, use_json);
d62a17ae 10830 }
dba3c1d3
PG
10831
10832 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10833 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10834 output_arg, use_json,
10835 1, NULL, NULL);
10836 }
d62a17ae 10837 /* labeled-unicast routes live in the unicast table */
10838 else if (safi == SAFI_LABELED_UNICAST)
10839 safi = SAFI_UNICAST;
fee0f4c6 10840
96f3485c
MK
10841 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10842 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10843}
10844
d62a17ae 10845static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10846 safi_t safi, uint8_t show_flags)
f186de26 10847{
d62a17ae 10848 struct listnode *node, *nnode;
10849 struct bgp *bgp;
10850 int is_first = 1;
9f049418 10851 bool route_output = false;
96f3485c 10852 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10853
d62a17ae 10854 if (use_json)
10855 vty_out(vty, "{\n");
9f689658 10856
d62a17ae 10857 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10858 route_output = true;
d62a17ae 10859 if (use_json) {
10860 if (!is_first)
10861 vty_out(vty, ",\n");
10862 else
10863 is_first = 0;
10864
10865 vty_out(vty, "\"%s\":",
10866 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10867 ? VRF_DEFAULT_NAME
d62a17ae 10868 : bgp->name);
10869 } else {
10870 vty_out(vty, "\nInstance %s:\n",
10871 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10872 ? VRF_DEFAULT_NAME
d62a17ae 10873 : bgp->name);
10874 }
10875 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10876 show_flags);
d62a17ae 10877 }
9f689658 10878
d62a17ae 10879 if (use_json)
10880 vty_out(vty, "}\n");
9f049418
DS
10881 else if (!route_output)
10882 vty_out(vty, "%% BGP instance not found\n");
f186de26 10883}
10884
718e3744 10885/* Header of detailed BGP route information */
d62a17ae 10886void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10887 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10888 afi_t afi, safi_t safi, json_object *json)
10889{
40381db7 10890 struct bgp_path_info *pi;
b54892e0 10891 const struct prefix *p;
d62a17ae 10892 struct peer *peer;
10893 struct listnode *node, *nnode;
06b9f471 10894 char buf1[RD_ADDRSTRLEN];
0291c246 10895 char prefix_str[BUFSIZ];
d62a17ae 10896 int count = 0;
10897 int best = 0;
10898 int suppress = 0;
c5f1e1b2
C
10899 int accept_own = 0;
10900 int route_filter_translated_v4 = 0;
10901 int route_filter_v4 = 0;
10902 int route_filter_translated_v6 = 0;
10903 int route_filter_v6 = 0;
10904 int llgr_stale = 0;
10905 int no_llgr = 0;
10906 int accept_own_nexthop = 0;
10907 int blackhole = 0;
d62a17ae 10908 int no_export = 0;
10909 int no_advertise = 0;
10910 int local_as = 0;
c5f1e1b2 10911 int no_peer = 0;
d62a17ae 10912 int first = 1;
10913 int has_valid_label = 0;
10914 mpls_label_t label = 0;
10915 json_object *json_adv_to = NULL;
9bedbb1e 10916
9bcb3eef
DS
10917 p = bgp_dest_get_prefix(dest);
10918 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10919
10920 if (has_valid_label)
9bcb3eef 10921 label = label_pton(&dest->local_label);
d62a17ae 10922
44c69747 10923 if (safi == SAFI_EVPN) {
d62a17ae 10924
44c69747 10925 if (!json) {
2dbe669b 10926 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 10927 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 10928 : "",
2dbe669b 10929 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
10930 } else {
10931 json_object_string_add(json, "rd",
10932 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10933 "");
10934 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10935 }
10936 } else {
10937 if (!json) {
8228a9a7 10938 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 10939 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
10940 ? prefix_rd2str(prd, buf1,
10941 sizeof(buf1))
10942 : ""),
10943 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 10944
44c69747
LK
10945 } else
10946 json_object_string_add(json, "prefix",
10947 prefix2str(p, prefix_str, sizeof(prefix_str)));
10948 }
10949
10950 if (has_valid_label) {
10951 if (json)
10952 json_object_int_add(json, "localLabel", label);
10953 else
d62a17ae 10954 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10955 }
10956
10957 if (!json)
d62a17ae 10958 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10959 vty_out(vty, "not allocated\n");
718e3744 10960
9bcb3eef 10961 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10962 count++;
40381db7 10963 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10964 best = count;
4056a5f6 10965 if (bgp_path_suppressed(pi))
d62a17ae 10966 suppress = 1;
cee9c031 10967
40381db7 10968 if (pi->attr->community == NULL)
cee9c031
QY
10969 continue;
10970
10971 no_advertise += community_include(
40381db7
DS
10972 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10973 no_export += community_include(pi->attr->community,
cee9c031 10974 COMMUNITY_NO_EXPORT);
40381db7 10975 local_as += community_include(pi->attr->community,
cee9c031 10976 COMMUNITY_LOCAL_AS);
40381db7 10977 accept_own += community_include(pi->attr->community,
cee9c031
QY
10978 COMMUNITY_ACCEPT_OWN);
10979 route_filter_translated_v4 += community_include(
40381db7 10980 pi->attr->community,
cee9c031
QY
10981 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10982 route_filter_translated_v6 += community_include(
40381db7 10983 pi->attr->community,
cee9c031
QY
10984 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10985 route_filter_v4 += community_include(
40381db7 10986 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10987 route_filter_v6 += community_include(
40381db7
DS
10988 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10989 llgr_stale += community_include(pi->attr->community,
cee9c031 10990 COMMUNITY_LLGR_STALE);
40381db7 10991 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10992 COMMUNITY_NO_LLGR);
10993 accept_own_nexthop +=
40381db7 10994 community_include(pi->attr->community,
cee9c031 10995 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10996 blackhole += community_include(pi->attr->community,
cee9c031 10997 COMMUNITY_BLACKHOLE);
40381db7 10998 no_peer += community_include(pi->attr->community,
cee9c031 10999 COMMUNITY_NO_PEER);
d62a17ae 11000 }
718e3744 11001 }
718e3744 11002
d62a17ae 11003 if (!json) {
11004 vty_out(vty, "Paths: (%d available", count);
11005 if (best) {
11006 vty_out(vty, ", best #%d", best);
b84060bb
PG
11007 if (safi == SAFI_UNICAST) {
11008 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11009 vty_out(vty, ", table %s",
11010 VRF_DEFAULT_NAME);
11011 else
11012 vty_out(vty, ", vrf %s",
11013 bgp->name);
11014 }
d62a17ae 11015 } else
11016 vty_out(vty, ", no best path");
11017
c5f1e1b2
C
11018 if (accept_own)
11019 vty_out(vty,
11020 ", accept own local route exported and imported in different VRF");
11021 else if (route_filter_translated_v4)
11022 vty_out(vty,
11023 ", mark translated RTs for VPNv4 route filtering");
11024 else if (route_filter_v4)
11025 vty_out(vty,
11026 ", attach RT as-is for VPNv4 route filtering");
11027 else if (route_filter_translated_v6)
11028 vty_out(vty,
11029 ", mark translated RTs for VPNv6 route filtering");
11030 else if (route_filter_v6)
11031 vty_out(vty,
11032 ", attach RT as-is for VPNv6 route filtering");
11033 else if (llgr_stale)
11034 vty_out(vty,
11035 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11036 else if (no_llgr)
11037 vty_out(vty,
11038 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11039 else if (accept_own_nexthop)
11040 vty_out(vty,
11041 ", accept local nexthop");
11042 else if (blackhole)
11043 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11044 else if (no_export)
11045 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11046 else if (no_advertise)
11047 vty_out(vty, ", not advertised to any peer");
d62a17ae 11048 else if (local_as)
11049 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11050 else if (no_peer)
11051 vty_out(vty,
11052 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11053
11054 if (suppress)
11055 vty_out(vty,
11056 ", Advertisements suppressed by an aggregate.");
11057 vty_out(vty, ")\n");
11058 }
718e3744 11059
d62a17ae 11060 /* If we are not using addpath then we can display Advertised to and
11061 * that will
11062 * show what peers we advertised the bestpath to. If we are using
11063 * addpath
11064 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11065 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11066 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11067 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11068 if (json && !json_adv_to)
11069 json_adv_to = json_object_new_object();
11070
11071 route_vty_out_advertised_to(
11072 vty, peer, &first,
11073 " Advertised to non peer-group peers:\n ",
11074 json_adv_to);
11075 }
11076 }
11077
11078 if (json) {
11079 if (json_adv_to) {
11080 json_object_object_add(json, "advertisedTo",
11081 json_adv_to);
11082 }
11083 } else {
11084 if (first)
11085 vty_out(vty, " Not advertised to any peer");
11086 vty_out(vty, "\n");
11087 }
11088 }
718e3744 11089}
11090
44c69747 11091static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11092 struct bgp_dest *bgp_node, struct vty *vty,
11093 struct bgp *bgp, afi_t afi, safi_t safi,
11094 json_object *json, enum bgp_path_type pathtype,
11095 int *display)
44c69747
LK
11096{
11097 struct bgp_path_info *pi;
11098 int header = 1;
11099 char rdbuf[RD_ADDRSTRLEN];
11100 json_object *json_header = NULL;
11101 json_object *json_paths = NULL;
11102
9bcb3eef 11103 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
11104
11105 if (json && !json_paths) {
11106 /* Instantiate json_paths only if path is valid */
11107 json_paths = json_object_new_array();
11108 if (pfx_rd) {
11109 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11110 json_header = json_object_new_object();
11111 } else
11112 json_header = json;
11113 }
11114
11115 if (header) {
11116 route_vty_out_detail_header(
11117 vty, bgp, bgp_node, pfx_rd,
11118 AFI_IP, safi, json_header);
11119 header = 0;
11120 }
11121 (*display)++;
11122
11123 if (pathtype == BGP_PATH_SHOW_ALL
11124 || (pathtype == BGP_PATH_SHOW_BESTPATH
11125 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11126 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11127 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11128 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11129 route_vty_out_detail(vty, bgp, bgp_node,
11130 pi, AFI_IP, safi,
11131 json_paths);
11132 }
11133
11134 if (json && json_paths) {
11135 json_object_object_add(json_header, "paths", json_paths);
11136
11137 if (pfx_rd)
11138 json_object_object_add(json, rdbuf, json_header);
11139 }
11140}
11141
718e3744 11142/* Display specified route of BGP table. */
d62a17ae 11143static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11144 struct bgp_table *rib, const char *ip_str,
11145 afi_t afi, safi_t safi,
11146 struct prefix_rd *prd, int prefix_check,
9f049418 11147 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11148{
11149 int ret;
d62a17ae 11150 int display = 0;
11151 struct prefix match;
9bcb3eef
DS
11152 struct bgp_dest *dest;
11153 struct bgp_dest *rm;
d62a17ae 11154 struct bgp_table *table;
11155 json_object *json = NULL;
11156 json_object *json_paths = NULL;
11157
11158 /* Check IP address argument. */
11159 ret = str2prefix(ip_str, &match);
11160 if (!ret) {
11161 vty_out(vty, "address is malformed\n");
11162 return CMD_WARNING;
11163 }
718e3744 11164
d62a17ae 11165 match.family = afi2family(afi);
b05a1c8b 11166
44c69747 11167 if (use_json)
d62a17ae 11168 json = json_object_new_object();
718e3744 11169
44c69747 11170 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11171 for (dest = bgp_table_top(rib); dest;
11172 dest = bgp_route_next(dest)) {
11173 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11174
9bcb3eef 11175 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11176 continue;
9bcb3eef 11177 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11178 if (!table)
ea47320b 11179 continue;
d62a17ae 11180
ea47320b
DL
11181 if ((rm = bgp_node_match(table, &match)) == NULL)
11182 continue;
d62a17ae 11183
9bcb3eef 11184 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11185 if (prefix_check
b54892e0 11186 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11187 bgp_dest_unlock_node(rm);
ea47320b
DL
11188 continue;
11189 }
d62a17ae 11190
9bcb3eef 11191 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11192 bgp, afi, safi, json, pathtype,
11193 &display);
44c69747 11194
9bcb3eef 11195 bgp_dest_unlock_node(rm);
44c69747
LK
11196 }
11197 } else if (safi == SAFI_EVPN) {
9bcb3eef 11198 struct bgp_dest *longest_pfx;
cded3b72 11199 bool is_exact_pfxlen_match = false;
44c69747 11200
9bcb3eef
DS
11201 for (dest = bgp_table_top(rib); dest;
11202 dest = bgp_route_next(dest)) {
11203 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11204
9bcb3eef 11205 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11206 continue;
9bcb3eef 11207 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11208 if (!table)
11209 continue;
11210
11211 longest_pfx = NULL;
cded3b72 11212 is_exact_pfxlen_match = false;
44c69747
LK
11213 /*
11214 * Search through all the prefixes for a match. The
11215 * pfx's are enumerated in ascending order of pfxlens.
11216 * So, the last pfx match is the longest match. Set
11217 * is_exact_pfxlen_match when we get exact pfxlen match
11218 */
11219 for (rm = bgp_table_top(table); rm;
11220 rm = bgp_route_next(rm)) {
b54892e0 11221 const struct prefix *rm_p =
9bcb3eef 11222 bgp_dest_get_prefix(rm);
44c69747
LK
11223 /*
11224 * Get prefixlen of the ip-prefix within type5
11225 * evpn route
11226 */
b54892e0
DS
11227 if (evpn_type5_prefix_match(rm_p, &match)
11228 && rm->info) {
44c69747
LK
11229 longest_pfx = rm;
11230 int type5_pfxlen =
b54892e0
DS
11231 bgp_evpn_get_type5_prefixlen(
11232 rm_p);
44c69747 11233 if (type5_pfxlen == match.prefixlen) {
cded3b72 11234 is_exact_pfxlen_match = true;
9bcb3eef 11235 bgp_dest_unlock_node(rm);
44c69747
LK
11236 break;
11237 }
d62a17ae 11238 }
11239 }
ea47320b 11240
44c69747
LK
11241 if (!longest_pfx)
11242 continue;
11243
11244 if (prefix_check && !is_exact_pfxlen_match)
11245 continue;
11246
11247 rm = longest_pfx;
9bcb3eef 11248 bgp_dest_lock_node(rm);
44c69747 11249
9bcb3eef 11250 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11251 bgp, afi, safi, json, pathtype,
11252 &display);
44c69747 11253
9bcb3eef 11254 bgp_dest_unlock_node(rm);
d62a17ae 11255 }
98a9dbc7 11256 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11257 if (use_json)
11258 json_paths = json_object_new_array();
11259
63a0b7a9
PG
11260 display = bgp_flowspec_display_match_per_ip(afi, rib,
11261 &match, prefix_check,
11262 vty,
11263 use_json,
11264 json_paths);
44c69747
LK
11265 if (use_json && display)
11266 json_object_object_add(json, "paths", json_paths);
d62a17ae 11267 } else {
9bcb3eef
DS
11268 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11269 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11270 if (!prefix_check
9bcb3eef
DS
11271 || dest_p->prefixlen == match.prefixlen) {
11272 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11273 safi, json, pathtype,
11274 &display);
d62a17ae 11275 }
11276
9bcb3eef 11277 bgp_dest_unlock_node(dest);
d62a17ae 11278 }
11279 }
e5eee9af 11280
d62a17ae 11281 if (use_json) {
996c9314 11282 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11283 json, JSON_C_TO_STRING_PRETTY |
11284 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11285 json_object_free(json);
11286 } else {
11287 if (!display) {
11288 vty_out(vty, "%% Network not in table\n");
11289 return CMD_WARNING;
11290 }
11291 }
b05a1c8b 11292
d62a17ae 11293 return CMD_SUCCESS;
718e3744 11294}
11295
fee0f4c6 11296/* Display specified route of Main RIB */
d62a17ae 11297static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11298 afi_t afi, safi_t safi, struct prefix_rd *prd,
11299 int prefix_check, enum bgp_path_type pathtype,
9f049418 11300 bool use_json)
d62a17ae 11301{
9b86009a 11302 if (!bgp) {
d62a17ae 11303 bgp = bgp_get_default();
9b86009a
RW
11304 if (!bgp) {
11305 if (!use_json)
11306 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11307 else
11308 vty_out(vty, "{}\n");
9b86009a
RW
11309 return CMD_WARNING;
11310 }
11311 }
d62a17ae 11312
11313 /* labeled-unicast routes live in the unicast table */
11314 if (safi == SAFI_LABELED_UNICAST)
11315 safi = SAFI_UNICAST;
11316
11317 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11318 afi, safi, prd, prefix_check, pathtype,
11319 use_json);
11320}
11321
11322static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11323 struct cmd_token **argv, bool exact, afi_t afi,
11324 safi_t safi, bool uj)
d62a17ae 11325{
11326 struct lcommunity *lcom;
11327 struct buffer *b;
11328 int i;
11329 char *str;
11330 int first = 0;
96f3485c 11331 uint8_t show_flags = 0;
4f28b2b5 11332 int ret;
96f3485c
MK
11333
11334 if (uj)
11335 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11336
11337 b = buffer_new(1024);
11338 for (i = 0; i < argc; i++) {
11339 if (first)
11340 buffer_putc(b, ' ');
11341 else {
11342 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11343 first = 1;
11344 buffer_putstr(b, argv[i]->arg);
11345 }
11346 }
11347 }
11348 buffer_putc(b, '\0');
57d187bc 11349
d62a17ae 11350 str = buffer_getstr(b);
11351 buffer_free(b);
57d187bc 11352
d62a17ae 11353 lcom = lcommunity_str2com(str);
11354 XFREE(MTYPE_TMP, str);
11355 if (!lcom) {
11356 vty_out(vty, "%% Large-community malformed\n");
11357 return CMD_WARNING;
11358 }
57d187bc 11359
4f28b2b5 11360 ret = bgp_show(vty, bgp, afi, safi,
36a206db 11361 (exact ? bgp_show_type_lcommunity_exact
ae248832 11362 : bgp_show_type_lcommunity),
96f3485c 11363 lcom, show_flags);
4f28b2b5
DS
11364
11365 lcommunity_free(&lcom);
11366 return ret;
57d187bc
JS
11367}
11368
d62a17ae 11369static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11370 const char *lcom, bool exact, afi_t afi,
11371 safi_t safi, bool uj)
57d187bc 11372{
d62a17ae 11373 struct community_list *list;
96f3485c
MK
11374 uint8_t show_flags = 0;
11375
11376 if (uj)
11377 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11378
57d187bc 11379
e237b0d2 11380 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11381 LARGE_COMMUNITY_LIST_MASTER);
11382 if (list == NULL) {
11383 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11384 lcom);
11385 return CMD_WARNING;
11386 }
57d187bc 11387
36a206db 11388 return bgp_show(vty, bgp, afi, safi,
11389 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11390 : bgp_show_type_lcommunity_list),
96f3485c 11391 list, show_flags);
fee0f4c6 11392}
11393
52951b63
DS
11394DEFUN (show_ip_bgp_large_community_list,
11395 show_ip_bgp_large_community_list_cmd,
36a206db 11396 "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
11397 SHOW_STR
11398 IP_STR
11399 BGP_STR
11400 BGP_INSTANCE_HELP_STR
9bedbb1e 11401 BGP_AFI_HELP_STR
4dd6177e 11402 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11403 "Display routes matching the large-community-list\n"
11404 "large-community-list number\n"
11405 "large-community-list name\n"
36a206db 11406 "Exact match of the large-communities\n"
52951b63
DS
11407 JSON_STR)
11408{
d62a17ae 11409 afi_t afi = AFI_IP6;
11410 safi_t safi = SAFI_UNICAST;
11411 int idx = 0;
36a206db 11412 bool exact_match = 0;
4d678463 11413 struct bgp *bgp = NULL;
9f049418 11414 bool uj = use_json(argc, argv);
d62a17ae 11415
4d678463
KA
11416 if (uj)
11417 argc--;
11418
11419 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11420 &bgp, uj);
11421 if (!idx)
11422 return CMD_WARNING;
d62a17ae 11423
11424 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11425
11426 const char *clist_number_or_name = argv[++idx]->arg;
11427
11428 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11429 exact_match = 1;
11430
11431 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11432 exact_match, afi, safi, uj);
52951b63
DS
11433}
11434DEFUN (show_ip_bgp_large_community,
11435 show_ip_bgp_large_community_cmd,
36a206db 11436 "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
11437 SHOW_STR
11438 IP_STR
11439 BGP_STR
11440 BGP_INSTANCE_HELP_STR
9bedbb1e 11441 BGP_AFI_HELP_STR
4dd6177e 11442 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11443 "Display routes matching the large-communities\n"
11444 "List of large-community numbers\n"
36a206db 11445 "Exact match of the large-communities\n"
52951b63
DS
11446 JSON_STR)
11447{
d62a17ae 11448 afi_t afi = AFI_IP6;
11449 safi_t safi = SAFI_UNICAST;
11450 int idx = 0;
36a206db 11451 bool exact_match = 0;
4d678463 11452 struct bgp *bgp = NULL;
9f049418 11453 bool uj = use_json(argc, argv);
96f3485c 11454 uint8_t show_flags = 0;
d62a17ae 11455
96f3485c
MK
11456 if (uj) {
11457 argc--;
11458 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11459 }
4d678463 11460
96f3485c
MK
11461 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11462 &bgp, uj);
11463 if (!idx)
11464 return CMD_WARNING;
d62a17ae 11465
36a206db 11466 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11467 if (argv_find(argv, argc, "exact-match", &idx))
11468 exact_match = 1;
11469 return bgp_show_lcommunity(vty, bgp, argc, argv,
11470 exact_match, afi, safi, uj);
11471 } else
d62a17ae 11472 return bgp_show(vty, bgp, afi, safi,
96f3485c 11473 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11474}
11475
71f1613a
DA
11476static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11477 safi_t safi, struct json_object *json_array);
d62a17ae 11478static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11479 safi_t safi, struct json_object *json);
e01ca200 11480
7b2ff250 11481
9ab0cf58
PG
11482DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11483 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11484 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11485 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11486{
11487 bool uj = use_json(argc, argv);
11488 struct bgp *bgp = NULL;
ec76a1d1
DA
11489 safi_t safi = SAFI_UNICAST;
11490 afi_t afi = AFI_IP6;
4265b261 11491 int idx = 0;
6c9d22e2
PG
11492 struct json_object *json_all = NULL;
11493 struct json_object *json_afi_safi = NULL;
4265b261
PG
11494
11495 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11496 &bgp, false);
71f1613a 11497 if (!idx)
4265b261 11498 return CMD_WARNING;
6c9d22e2 11499
4265b261 11500 if (uj)
6c9d22e2 11501 json_all = json_object_new_object();
4265b261 11502
9ab0cf58
PG
11503 FOREACH_AFI_SAFI (afi, safi) {
11504 /*
11505 * So limit output to those afi/safi pairs that
11506 * actually have something interesting in them
11507 */
11508 if (strmatch(get_afi_safi_str(afi, safi, true),
11509 "Unknown")) {
11510 continue;
11511 }
11512 if (uj) {
11513 json_afi_safi = json_object_new_array();
11514 json_object_object_add(
11515 json_all,
11516 get_afi_safi_str(afi, safi, true),
11517 json_afi_safi);
11518 } else {
11519 json_afi_safi = NULL;
6c9d22e2 11520 }
9ab0cf58
PG
11521
11522 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11523 }
6c9d22e2
PG
11524
11525 if (uj) {
9ab0cf58
PG
11526 vty_out(vty, "%s",
11527 json_object_to_json_string_ext(
11528 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11529 json_object_free(json_all);
4265b261 11530 }
6c9d22e2 11531
4265b261
PG
11532 return CMD_SUCCESS;
11533}
11534
7b2ff250 11535/* BGP route print out function without JSON */
14718643
PG
11536DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11537 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11538 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11539 SHOW_STR
11540 IP_STR
11541 BGP_STR
11542 BGP_INSTANCE_HELP_STR
11543 L2VPN_HELP_STR
11544 EVPN_HELP_STR
11545 "BGP RIB advertisement statistics\n"
11546 JSON_STR)
11547{
ec76a1d1
DA
11548 afi_t afi = AFI_IP6;
11549 safi_t safi = SAFI_UNICAST;
14718643
PG
11550 struct bgp *bgp = NULL;
11551 int idx = 0, ret;
11552 bool uj = use_json(argc, argv);
11553 struct json_object *json_afi_safi = NULL, *json = NULL;
11554
11555 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11556 &bgp, false);
11557 if (!idx)
11558 return CMD_WARNING;
11559
11560 if (uj)
11561 json_afi_safi = json_object_new_array();
11562 else
11563 json_afi_safi = NULL;
11564
11565 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11566
11567 if (uj) {
11568 json = json_object_new_object();
11569 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11570 json_afi_safi);
11571 vty_out(vty, "%s", json_object_to_json_string_ext(
11572 json, JSON_C_TO_STRING_PRETTY));
11573 json_object_free(json);
11574 }
11575 return ret;
11576}
11577
893cccd0 11578/* BGP route print out function without JSON */
9ab0cf58
PG
11579DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11580 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11581 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11582 "]]\
893cccd0 11583 statistics [json]",
9ab0cf58
PG
11584 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11585 BGP_SAFI_WITH_LABEL_HELP_STR
11586 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11587{
ec76a1d1
DA
11588 afi_t afi = AFI_IP6;
11589 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11590 struct bgp *bgp = NULL;
11591 int idx = 0, ret;
11592 bool uj = use_json(argc, argv);
6c9d22e2 11593 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11594
11595 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11596 &bgp, false);
11597 if (!idx)
11598 return CMD_WARNING;
6c9d22e2 11599
893cccd0 11600 if (uj)
6c9d22e2
PG
11601 json_afi_safi = json_object_new_array();
11602 else
11603 json_afi_safi = NULL;
11604
11605 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11606
11607 if (uj) {
11608 json = json_object_new_object();
11609 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11610 json_afi_safi);
9ab0cf58
PG
11611 vty_out(vty, "%s",
11612 json_object_to_json_string_ext(
11613 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11614 json_object_free(json);
11615 }
11616 return ret;
893cccd0 11617}
7b2ff250
DW
11618
11619/* BGP route print out function without JSON */
96f3485c 11620DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11621 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11622 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11623 "]]\
96f3485c 11624 <[all$all] dampening <parameters>\
7b2ff250
DW
11625 |route-map WORD\
11626 |prefix-list WORD\
11627 |filter-list WORD\
7b2ff250
DW
11628 |community-list <(1-500)|WORD> [exact-match]\
11629 |A.B.C.D/M longer-prefixes\
11630 |X:X::X:X/M longer-prefixes\
893cccd0 11631 >",
9ab0cf58
PG
11632 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11633 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11634 "Display the entries for all address families\n"
9ab0cf58
PG
11635 "Display detailed information about dampening\n"
11636 "Display detail of configured dampening parameters\n"
11637 "Display routes matching the route-map\n"
11638 "A route-map to match on\n"
11639 "Display routes conforming to the prefix-list\n"
11640 "Prefix-list name\n"
11641 "Display routes conforming to the filter-list\n"
11642 "Regular expression access list name\n"
11643 "Display routes matching the community-list\n"
11644 "community-list number\n"
11645 "community-list name\n"
11646 "Exact match of the communities\n"
11647 "IPv4 prefix\n"
11648 "Display route and more specific routes\n"
11649 "IPv6 prefix\n"
11650 "Display route and more specific routes\n")
718e3744 11651{
d62a17ae 11652 afi_t afi = AFI_IP6;
11653 safi_t safi = SAFI_UNICAST;
11654 int exact_match = 0;
d62a17ae 11655 struct bgp *bgp = NULL;
11656 int idx = 0;
96f3485c
MK
11657 uint8_t show_flags = 0;
11658
11659 /* [<ipv4|ipv6> [all]] */
11660 if (all) {
11661 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11662 if (argv_find(argv, argc, "ipv4", &idx))
11663 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11664
11665 if (argv_find(argv, argc, "ipv6", &idx))
11666 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11667 }
d62a17ae 11668
11669 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11670 &bgp, false);
d62a17ae 11671 if (!idx)
11672 return CMD_WARNING;
11673
d62a17ae 11674 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11675 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11676 return bgp_show_dampening_parameters(vty, afi, safi,
11677 show_flags);
d62a17ae 11678 }
c016b6c7 11679
d62a17ae 11680 if (argv_find(argv, argc, "prefix-list", &idx))
11681 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11682 safi, bgp_show_type_prefix_list);
11683
11684 if (argv_find(argv, argc, "filter-list", &idx))
11685 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11686 safi, bgp_show_type_filter_list);
11687
d62a17ae 11688 if (argv_find(argv, argc, "route-map", &idx))
11689 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11690 safi, bgp_show_type_route_map);
11691
d62a17ae 11692 if (argv_find(argv, argc, "community-list", &idx)) {
11693 const char *clist_number_or_name = argv[++idx]->arg;
11694 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11695 exact_match = 1;
11696 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11697 exact_match, afi, safi);
11698 }
11699 /* prefix-longer */
11700 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11701 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11702 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11703 safi,
11704 bgp_show_type_prefix_longer);
11705
7b2ff250
DW
11706 return CMD_WARNING;
11707}
11708
11709/* BGP route print out function with JSON */
ae248832 11710DEFPY (show_ip_bgp_json,
7b2ff250
DW
11711 show_ip_bgp_json_cmd,
11712 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11713 [all$all]\
cf4898bc
QY
11714 [cidr-only\
11715 |dampening <flap-statistics|dampened-paths>\
11716 |community [AA:NN|local-AS|no-advertise|no-export\
11717 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11718 |accept-own|accept-own-nexthop|route-filter-v6\
11719 |route-filter-v4|route-filter-translated-v6\
11720 |route-filter-translated-v4] [exact-match]\
ae248832 11721 ] [json$uj | wide$wide]",
7b2ff250
DW
11722 SHOW_STR
11723 IP_STR
11724 BGP_STR
11725 BGP_INSTANCE_HELP_STR
11726 BGP_AFI_HELP_STR
11727 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11728 "Display the entries for all address families\n"
7b2ff250
DW
11729 "Display only routes with non-natural netmasks\n"
11730 "Display detailed information about dampening\n"
11731 "Display flap statistics of routes\n"
11732 "Display paths suppressed due to dampening\n"
11733 "Display routes matching the communities\n"
d0086e8e
AD
11734 COMMUNITY_AANN_STR
11735 "Do not send outside local AS (well-known community)\n"
11736 "Do not advertise to any peer (well-known community)\n"
11737 "Do not export to next AS (well-known community)\n"
11738 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11739 "Do not export to any peer (well-known community)\n"
11740 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11741 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11742 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11743 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11744 "Should accept VPN route with local nexthop (well-known community)\n"
11745 "RT VPNv6 route filtering (well-known community)\n"
11746 "RT VPNv4 route filtering (well-known community)\n"
11747 "RT translated VPNv6 route filtering (well-known community)\n"
11748 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11749 "Exact match of the communities\n"
ae248832
MK
11750 JSON_STR
11751 "Increase table width for longer prefixes\n")
7b2ff250
DW
11752{
11753 afi_t afi = AFI_IP6;
11754 safi_t safi = SAFI_UNICAST;
11755 enum bgp_show_type sh_type = bgp_show_type_normal;
11756 struct bgp *bgp = NULL;
11757 int idx = 0;
d0086e8e 11758 int exact_match = 0;
96f3485c
MK
11759 char *community = NULL;
11760 bool first = true;
11761 uint8_t show_flags = 0;
9f049418 11762
96f3485c
MK
11763
11764 if (uj) {
9f049418 11765 argc--;
96f3485c
MK
11766 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11767 }
11768
11769 /* [<ipv4|ipv6> [all]] */
11770 if (all) {
11771 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11772
11773 if (argv_find(argv, argc, "ipv4", &idx))
11774 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11775
11776 if (argv_find(argv, argc, "ipv6", &idx))
11777 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11778 }
11779
11780 if (wide)
11781 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11782
11783 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11784 &bgp, uj);
7b2ff250
DW
11785 if (!idx)
11786 return CMD_WARNING;
11787
7b2ff250 11788 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11789 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11790
11791 if (argv_find(argv, argc, "dampening", &idx)) {
11792 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11793 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11794 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11795 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11796 }
11797
11798 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11799 char *maybecomm = NULL;
d0086e8e 11800
79bc257a
RW
11801 if (idx + 1 < argc) {
11802 if (argv[idx + 1]->type == VARIABLE_TKN)
11803 maybecomm = argv[idx + 1]->arg;
11804 else
11805 maybecomm = argv[idx + 1]->text;
11806 }
11807
cf4898bc
QY
11808 if (maybecomm && !strmatch(maybecomm, "json")
11809 && !strmatch(maybecomm, "exact-match"))
11810 community = maybecomm;
d0086e8e 11811
cf4898bc
QY
11812 if (argv_find(argv, argc, "exact-match", &idx))
11813 exact_match = 1;
d0086e8e 11814
96f3485c
MK
11815 if (!community)
11816 sh_type = bgp_show_type_community_all;
11817 }
11818
11819 if (!all) {
11820 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11821 if (community)
11822 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11823 exact_match, afi, safi,
11824 show_flags);
cf4898bc 11825 else
96f3485c
MK
11826 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11827 show_flags);
11828 } else {
11829 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11830 * AFI_IP6 */
11831
11832 if (uj)
11833 vty_out(vty, "{\n");
11834
11835 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11836 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11837 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11838 ? AFI_IP
11839 : AFI_IP6;
11840 FOREACH_SAFI (safi) {
96f3485c
MK
11841 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11842 continue;
11843
11844 if (uj) {
11845 if (first)
11846 first = false;
11847 else
11848 vty_out(vty, ",\n");
11849 vty_out(vty, "\"%s\":{\n",
11850 get_afi_safi_str(afi, safi,
11851 true));
11852 } else
11853 vty_out(vty,
11854 "\nFor address family: %s\n",
11855 get_afi_safi_str(afi, safi,
11856 false));
11857
11858 if (community)
11859 bgp_show_community(vty, bgp, community,
11860 exact_match, afi,
11861 safi, show_flags);
11862 else
11863 bgp_show(vty, bgp, afi, safi, sh_type,
11864 NULL, show_flags);
11865 if (uj)
11866 vty_out(vty, "}\n");
11867 }
11868 } else {
11869 /* show <ip> bgp all: for each AFI and SAFI*/
11870 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
11871 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11872 continue;
11873
11874 if (uj) {
11875 if (first)
11876 first = false;
11877 else
11878 vty_out(vty, ",\n");
d0086e8e 11879
96f3485c
MK
11880 vty_out(vty, "\"%s\":{\n",
11881 get_afi_safi_str(afi, safi,
11882 true));
11883 } else
11884 vty_out(vty,
11885 "\nFor address family: %s\n",
11886 get_afi_safi_str(afi, safi,
11887 false));
11888
11889 if (community)
11890 bgp_show_community(vty, bgp, community,
11891 exact_match, afi,
11892 safi, show_flags);
11893 else
11894 bgp_show(vty, bgp, afi, safi, sh_type,
11895 NULL, show_flags);
11896 if (uj)
11897 vty_out(vty, "}\n");
11898 }
11899 }
11900 if (uj)
11901 vty_out(vty, "}\n");
11902 }
11903 return CMD_SUCCESS;
a636c635 11904}
47fc97cc 11905
718e3744 11906DEFUN (show_ip_bgp_route,
11907 show_ip_bgp_route_cmd,
3efd0893 11908 "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 11909 SHOW_STR
11910 IP_STR
11911 BGP_STR
a636c635 11912 BGP_INSTANCE_HELP_STR
4f280b15 11913 BGP_AFI_HELP_STR
4dd6177e 11914 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11915 "Network in the BGP routing table to display\n"
0c7b1b01 11916 "IPv4 prefix\n"
8c3deaae 11917 "Network in the BGP routing table to display\n"
0c7b1b01 11918 "IPv6 prefix\n"
4092b06c 11919 "Display only the bestpath\n"
b05a1c8b 11920 "Display only multipaths\n"
9973d184 11921 JSON_STR)
4092b06c 11922{
d62a17ae 11923 int prefix_check = 0;
ae19d7dd 11924
d62a17ae 11925 afi_t afi = AFI_IP6;
11926 safi_t safi = SAFI_UNICAST;
11927 char *prefix = NULL;
11928 struct bgp *bgp = NULL;
11929 enum bgp_path_type path_type;
9f049418 11930 bool uj = use_json(argc, argv);
b05a1c8b 11931
d62a17ae 11932 int idx = 0;
ae19d7dd 11933
d62a17ae 11934 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11935 &bgp, uj);
d62a17ae 11936 if (!idx)
11937 return CMD_WARNING;
c41247f5 11938
d62a17ae 11939 if (!bgp) {
11940 vty_out(vty,
11941 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11942 return CMD_WARNING;
11943 }
a636c635 11944
d62a17ae 11945 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11946 if (argv_find(argv, argc, "A.B.C.D", &idx)
11947 || argv_find(argv, argc, "X:X::X:X", &idx))
11948 prefix_check = 0;
11949 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11950 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11951 prefix_check = 1;
11952
11953 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11954 && afi != AFI_IP6) {
11955 vty_out(vty,
11956 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11957 return CMD_WARNING;
11958 }
11959 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11960 && afi != AFI_IP) {
11961 vty_out(vty,
11962 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11963 return CMD_WARNING;
11964 }
11965
11966 prefix = argv[idx]->arg;
11967
11968 /* [<bestpath|multipath>] */
11969 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11970 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11971 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11972 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11973 else
360660c6 11974 path_type = BGP_PATH_SHOW_ALL;
a636c635 11975
d62a17ae 11976 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11977 path_type, uj);
4092b06c
DS
11978}
11979
8c3deaae
QY
11980DEFUN (show_ip_bgp_regexp,
11981 show_ip_bgp_regexp_cmd,
3e5b31b3 11982 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11983 SHOW_STR
11984 IP_STR
11985 BGP_STR
b00b230a 11986 BGP_INSTANCE_HELP_STR
4f280b15 11987 BGP_AFI_HELP_STR
4dd6177e 11988 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11989 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11990 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11991 JSON_STR)
8c3deaae 11992{
d62a17ae 11993 afi_t afi = AFI_IP6;
11994 safi_t safi = SAFI_UNICAST;
11995 struct bgp *bgp = NULL;
3e5b31b3
DA
11996 bool uj = use_json(argc, argv);
11997 char *regstr = NULL;
8c3deaae 11998
d62a17ae 11999 int idx = 0;
12000 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12001 &bgp, false);
d62a17ae 12002 if (!idx)
12003 return CMD_WARNING;
8c3deaae 12004
d62a17ae 12005 // get index of regex
3e5b31b3
DA
12006 if (argv_find(argv, argc, "REGEX", &idx))
12007 regstr = argv[idx]->arg;
8c3deaae 12008
5f71d11c 12009 assert(regstr);
3e5b31b3
DA
12010 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12011 bgp_show_type_regexp, uj);
8c3deaae
QY
12012}
12013
ae248832 12014DEFPY (show_ip_bgp_instance_all,
a636c635 12015 show_ip_bgp_instance_all_cmd,
ae248832 12016 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12017 SHOW_STR
a636c635 12018 IP_STR
4092b06c 12019 BGP_STR
a636c635 12020 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12021 BGP_AFI_HELP_STR
4dd6177e 12022 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12023 JSON_STR
12024 "Increase table width for longer prefixes\n")
4092b06c 12025{
d62a17ae 12026 afi_t afi = AFI_IP;
12027 safi_t safi = SAFI_UNICAST;
12028 struct bgp *bgp = NULL;
d62a17ae 12029 int idx = 0;
96f3485c 12030 uint8_t show_flags = 0;
ae19d7dd 12031
96f3485c 12032 if (uj) {
d62a17ae 12033 argc--;
96f3485c
MK
12034 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12035 }
12036
12037 if (wide)
12038 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12039
9f049418
DS
12040 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12041 &bgp, uj);
12042 if (!idx)
12043 return CMD_WARNING;
12044
96f3485c 12045 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12046 return CMD_SUCCESS;
e3e29b32
LB
12047}
12048
a4d82a8a 12049static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12050 afi_t afi, safi_t safi, enum bgp_show_type type,
12051 bool use_json)
718e3744 12052{
d62a17ae 12053 regex_t *regex;
12054 int rc;
96f3485c
MK
12055 uint8_t show_flags = 0;
12056
12057 if (use_json)
12058 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12059
c3900853 12060 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12061 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12062 regstr);
12063 return CMD_WARNING_CONFIG_FAILED;
12064 }
12065
d62a17ae 12066 regex = bgp_regcomp(regstr);
12067 if (!regex) {
12068 vty_out(vty, "Can't compile regexp %s\n", regstr);
12069 return CMD_WARNING;
12070 }
a636c635 12071
96f3485c 12072 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 12073 bgp_regex_free(regex);
12074 return rc;
e3e29b32
LB
12075}
12076
d62a17ae 12077static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12078 const char *prefix_list_str, afi_t afi,
12079 safi_t safi, enum bgp_show_type type)
e3e29b32 12080{
d62a17ae 12081 struct prefix_list *plist;
96f3485c 12082 uint8_t show_flags = 0;
718e3744 12083
d62a17ae 12084 plist = prefix_list_lookup(afi, prefix_list_str);
12085 if (plist == NULL) {
12086 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12087 prefix_list_str);
12088 return CMD_WARNING;
12089 }
718e3744 12090
96f3485c 12091 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
12092}
12093
d62a17ae 12094static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12095 const char *filter, afi_t afi, safi_t safi,
12096 enum bgp_show_type type)
4092b06c 12097{
d62a17ae 12098 struct as_list *as_list;
96f3485c 12099 uint8_t show_flags = 0;
718e3744 12100
d62a17ae 12101 as_list = as_list_lookup(filter);
12102 if (as_list == NULL) {
12103 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12104 filter);
12105 return CMD_WARNING;
12106 }
a636c635 12107
96f3485c 12108 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12109}
12110
d62a17ae 12111static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12112 const char *rmap_str, afi_t afi, safi_t safi,
12113 enum bgp_show_type type)
718e3744 12114{
d62a17ae 12115 struct route_map *rmap;
96f3485c 12116 uint8_t show_flags = 0;
bb46e94f 12117
d62a17ae 12118 rmap = route_map_lookup_by_name(rmap_str);
12119 if (!rmap) {
12120 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12121 return CMD_WARNING;
12122 }
12123
96f3485c 12124 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12125}
12126
7f323236
DW
12127static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12128 const char *comstr, int exact, afi_t afi,
96f3485c 12129 safi_t safi, uint8_t show_flags)
d62a17ae 12130{
12131 struct community *com;
d62a17ae 12132 int ret = 0;
12133
7f323236 12134 com = community_str2com(comstr);
d62a17ae 12135 if (!com) {
7f323236 12136 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12137 return CMD_WARNING;
12138 }
12139
12140 ret = bgp_show(vty, bgp, afi, safi,
12141 (exact ? bgp_show_type_community_exact
12142 : bgp_show_type_community),
96f3485c 12143 com, show_flags);
3c1f53de 12144 community_free(&com);
46c3ce83 12145
d62a17ae 12146 return ret;
718e3744 12147}
12148
d62a17ae 12149static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12150 const char *com, int exact, afi_t afi,
12151 safi_t safi)
50ef26d4 12152{
d62a17ae 12153 struct community_list *list;
96f3485c 12154 uint8_t show_flags = 0;
50ef26d4 12155
e237b0d2 12156 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12157 if (list == NULL) {
12158 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12159 return CMD_WARNING;
12160 }
718e3744 12161
d62a17ae 12162 return bgp_show(vty, bgp, afi, safi,
12163 (exact ? bgp_show_type_community_list_exact
12164 : bgp_show_type_community_list),
96f3485c 12165 list, show_flags);
50ef26d4 12166}
12167
d62a17ae 12168static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12169 const char *prefix, afi_t afi, safi_t safi,
12170 enum bgp_show_type type)
718e3744 12171{
d62a17ae 12172 int ret;
12173 struct prefix *p;
96f3485c 12174 uint8_t show_flags = 0;
47fc97cc 12175
d62a17ae 12176 p = prefix_new();
95cbbd2a 12177
d62a17ae 12178 ret = str2prefix(prefix, p);
12179 if (!ret) {
12180 vty_out(vty, "%% Malformed Prefix\n");
12181 return CMD_WARNING;
12182 }
47e9b292 12183
96f3485c 12184 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12185 prefix_free(&p);
d62a17ae 12186 return ret;
12187}
12188
d62a17ae 12189enum bgp_stats {
12190 BGP_STATS_MAXBITLEN = 0,
12191 BGP_STATS_RIB,
12192 BGP_STATS_PREFIXES,
12193 BGP_STATS_TOTPLEN,
12194 BGP_STATS_UNAGGREGATEABLE,
12195 BGP_STATS_MAX_AGGREGATEABLE,
12196 BGP_STATS_AGGREGATES,
12197 BGP_STATS_SPACE,
12198 BGP_STATS_ASPATH_COUNT,
12199 BGP_STATS_ASPATH_MAXHOPS,
12200 BGP_STATS_ASPATH_TOTHOPS,
12201 BGP_STATS_ASPATH_MAXSIZE,
12202 BGP_STATS_ASPATH_TOTSIZE,
12203 BGP_STATS_ASN_HIGHEST,
12204 BGP_STATS_MAX,
a636c635 12205};
2815e61f 12206
9ab0cf58 12207#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12208#define TABLE_STATS_IDX_JSON 1
12209
12210static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12211 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12212 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12213 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12214 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12215 "unaggregateablePrefixes"},
12216 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12217 "maximumAggregateablePrefixes"},
12218 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12219 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12220 [BGP_STATS_SPACE] = {"Address space advertised",
12221 "addressSpaceAdvertised"},
9ab0cf58
PG
12222 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12223 "advertisementsWithPaths"},
12224 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12225 "longestAsPath"},
12226 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12227 "largestAsPath"},
12228 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12229 "averageAsPathLengthHops"},
12230 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12231 "averageAsPathSizeBytes"},
12232 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12233 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12234};
2815e61f 12235
d62a17ae 12236struct bgp_table_stats {
12237 struct bgp_table *table;
12238 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12239 double total_space;
ff7924f6
PJ
12240};
12241
a636c635
DW
12242#if 0
12243#define TALLY_SIGFIG 100000
12244static unsigned long
12245ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 12246{
a636c635
DW
12247 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
12248 unsigned long res = (newtot * TALLY_SIGFIG) / count;
12249 unsigned long ret = newtot / count;
07d0c4ed 12250
a636c635
DW
12251 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
12252 return ret + 1;
12253 else
12254 return ret;
12255}
12256#endif
ff7924f6 12257
9bcb3eef 12258static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12259 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12260{
9bcb3eef 12261 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12262 struct bgp_path_info *pi;
b54892e0 12263 const struct prefix *rn_p;
d62a17ae 12264
9bcb3eef 12265 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12266 return;
d62a17ae 12267
9bcb3eef 12268 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12269 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12270 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12271
a636c635
DW
12272#if 0
12273 ts->counts[BGP_STATS_AVGPLEN]
12274 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
12275 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 12276 rn_p->prefixlen);
a636c635 12277#endif
d62a17ae 12278
9c14ec72 12279 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12280 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12281 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12282
9bcb3eef 12283 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12284 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12285 /* announced address space */
12286 if (space)
b54892e0 12287 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12288 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12289 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12290
9c14ec72 12291
9bcb3eef 12292 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12293 ts->counts[BGP_STATS_RIB]++;
12294
05864da7
DS
12295 if (CHECK_FLAG(pi->attr->flag,
12296 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12297 ts->counts[BGP_STATS_AGGREGATES]++;
12298
12299 /* as-path stats */
05864da7 12300 if (pi->attr->aspath) {
9c14ec72
RW
12301 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12302 unsigned int size = aspath_size(pi->attr->aspath);
12303 as_t highest = aspath_highest(pi->attr->aspath);
12304
12305 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12306
12307 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12308 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12309
12310 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12311 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12312
12313 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12314 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 12315#if 0
07d0c4ed 12316 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
12317 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12318 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
12319 hops);
12320 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
12321 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12322 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
12323 size);
12324#endif
9c14ec72
RW
12325 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12326 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12327 }
12328 }
12329}
12330
12331static int bgp_table_stats_walker(struct thread *t)
12332{
9bcb3eef
DS
12333 struct bgp_dest *dest, *ndest;
12334 struct bgp_dest *top;
9c14ec72
RW
12335 struct bgp_table_stats *ts = THREAD_ARG(t);
12336 unsigned int space = 0;
12337
12338 if (!(top = bgp_table_top(ts->table)))
12339 return 0;
12340
12341 switch (ts->table->afi) {
12342 case AFI_IP:
12343 space = IPV4_MAX_BITLEN;
12344 break;
12345 case AFI_IP6:
12346 space = IPV6_MAX_BITLEN;
12347 break;
12348 default:
12349 return 0;
12350 }
12351
12352 ts->counts[BGP_STATS_MAXBITLEN] = space;
12353
9bcb3eef 12354 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12355 if (ts->table->safi == SAFI_MPLS_VPN
12356 || ts->table->safi == SAFI_ENCAP
12357 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12358 struct bgp_table *table;
12359
9bcb3eef 12360 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12361 if (!table)
12362 continue;
12363
12364 top = bgp_table_top(table);
9bcb3eef
DS
12365 for (ndest = bgp_table_top(table); ndest;
12366 ndest = bgp_route_next(ndest))
12367 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12368 } else {
9bcb3eef 12369 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12370 }
12371 }
9c14ec72 12372
d62a17ae 12373 return 0;
2815e61f 12374}
ff7924f6 12375
71f1613a
DA
12376static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12377 struct json_object *json_array)
12378{
12379 struct listnode *node, *nnode;
12380 struct bgp *bgp;
12381
12382 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12383 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12384}
12385
12386static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12387 safi_t safi, struct json_object *json_array)
2815e61f 12388{
d62a17ae 12389 struct bgp_table_stats ts;
12390 unsigned int i;
893cccd0
PG
12391 int ret = CMD_SUCCESS;
12392 char temp_buf[20];
6c9d22e2
PG
12393 struct json_object *json = NULL;
12394
12395 if (json_array)
12396 json = json_object_new_object();
019386c2 12397
d62a17ae 12398 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12399 char warning_msg[50];
12400
12401 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12402 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12403 safi);
6c9d22e2
PG
12404
12405 if (!json)
893cccd0
PG
12406 vty_out(vty, "%s\n", warning_msg);
12407 else
9ab0cf58 12408 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12409
893cccd0
PG
12410 ret = CMD_WARNING;
12411 goto end_table_stats;
d62a17ae 12412 }
019386c2 12413
893cccd0 12414 if (!json)
5290ceab
DA
12415 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12416 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12417 else
12418 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12419
d62a17ae 12420 /* labeled-unicast routes live in the unicast table */
12421 if (safi == SAFI_LABELED_UNICAST)
12422 safi = SAFI_UNICAST;
019386c2 12423
d62a17ae 12424 memset(&ts, 0, sizeof(ts));
12425 ts.table = bgp->rib[afi][safi];
12426 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12427
d62a17ae 12428 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12429 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12430 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12431 continue;
12432
12433 switch (i) {
a636c635
DW
12434#if 0
12435 case BGP_STATS_ASPATH_AVGHOPS:
12436 case BGP_STATS_ASPATH_AVGSIZE:
12437 case BGP_STATS_AVGPLEN:
12438 vty_out (vty, "%-30s: ", table_stats_strs[i]);
12439 vty_out (vty, "%12.2f",
12440 (float)ts.counts[i] / (float)TALLY_SIGFIG);
12441 break;
12442#endif
d62a17ae 12443 case BGP_STATS_ASPATH_TOTHOPS:
12444 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12445 if (!json) {
9ab0cf58
PG
12446 snprintf(
12447 temp_buf, sizeof(temp_buf), "%12.2f",
12448 ts.counts[i]
12449 ? (float)ts.counts[i]
12450 / (float)ts.counts
12451 [BGP_STATS_ASPATH_COUNT]
12452 : 0);
893cccd0 12453 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12454 table_stats_strs[i]
12455 [TABLE_STATS_IDX_VTY],
893cccd0 12456 temp_buf);
9ab0cf58
PG
12457 } else {
12458 json_object_double_add(
12459 json,
12460 table_stats_strs[i]
12461 [TABLE_STATS_IDX_JSON],
12462 ts.counts[i]
12463 ? (double)ts.counts[i]
12464 / (double)ts.counts
d62a17ae 12465 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12466 : 0);
12467 }
d62a17ae 12468 break;
12469 case BGP_STATS_TOTPLEN:
6c9d22e2 12470 if (!json) {
9ab0cf58
PG
12471 snprintf(
12472 temp_buf, sizeof(temp_buf), "%12.2f",
12473 ts.counts[i]
12474 ? (float)ts.counts[i]
12475 / (float)ts.counts
12476 [BGP_STATS_PREFIXES]
12477 : 0);
893cccd0 12478 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12479 table_stats_strs[i]
12480 [TABLE_STATS_IDX_VTY],
893cccd0 12481 temp_buf);
9ab0cf58
PG
12482 } else {
12483 json_object_double_add(
12484 json,
12485 table_stats_strs[i]
12486 [TABLE_STATS_IDX_JSON],
12487 ts.counts[i]
12488 ? (double)ts.counts[i]
12489 / (double)ts.counts
d62a17ae 12490 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12491 : 0);
12492 }
d62a17ae 12493 break;
12494 case BGP_STATS_SPACE:
6c9d22e2
PG
12495 if (!json) {
12496 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12497 ts.total_space);
893cccd0 12498 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12499 table_stats_strs[i]
12500 [TABLE_STATS_IDX_VTY],
893cccd0 12501 temp_buf);
9ab0cf58
PG
12502 } else {
12503 json_object_double_add(
12504 json,
12505 table_stats_strs[i]
12506 [TABLE_STATS_IDX_JSON],
12507 (double)ts.total_space);
12508 }
8d0ab76d 12509 if (afi == AFI_IP6) {
6c9d22e2
PG
12510 if (!json) {
12511 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12512 "%12g",
12513 ts.total_space
12514 * pow(2.0, -128 + 32));
6c9d22e2
PG
12515 vty_out(vty, "%30s: %s\n",
12516 "/32 equivalent %s\n",
12517 temp_buf);
9ab0cf58
PG
12518 } else {
12519 json_object_double_add(
12520 json, "/32equivalent",
12521 (double)(ts.total_space
12522 * pow(2.0,
12523 -128 + 32)));
12524 }
6c9d22e2
PG
12525 if (!json) {
12526 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12527 "%12g",
12528 ts.total_space
12529 * pow(2.0, -128 + 48));
6c9d22e2
PG
12530 vty_out(vty, "%30s: %s\n",
12531 "/48 equivalent %s\n",
12532 temp_buf);
9ab0cf58
PG
12533 } else {
12534 json_object_double_add(
12535 json, "/48equivalent",
12536 (double)(ts.total_space
12537 * pow(2.0,
12538 -128 + 48)));
12539 }
8d0ab76d 12540 } else {
6c9d22e2
PG
12541 if (!json) {
12542 snprintf(temp_buf, sizeof(temp_buf),
12543 "%12.2f",
9ab0cf58
PG
12544 ts.total_space * 100.
12545 * pow(2.0, -32));
6c9d22e2 12546 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12547 "% announced ", temp_buf);
12548 } else {
12549 json_object_double_add(
12550 json, "%announced",
12551 (double)(ts.total_space * 100.
12552 * pow(2.0, -32)));
12553 }
6c9d22e2
PG
12554 if (!json) {
12555 snprintf(temp_buf, sizeof(temp_buf),
12556 "%12.2f",
9ab0cf58
PG
12557 ts.total_space
12558 * pow(2.0, -32 + 8));
6c9d22e2
PG
12559 vty_out(vty, "%30s: %s\n",
12560 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12561 } else {
12562 json_object_double_add(
12563 json, "/8equivalent",
12564 (double)(ts.total_space
12565 * pow(2.0, -32 + 8)));
12566 }
6c9d22e2
PG
12567 if (!json) {
12568 snprintf(temp_buf, sizeof(temp_buf),
12569 "%12.2f",
9ab0cf58
PG
12570 ts.total_space
12571 * pow(2.0, -32 + 24));
6c9d22e2 12572 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12573 "/24 equivalent ", temp_buf);
12574 } else {
12575 json_object_double_add(
12576 json, "/24equivalent",
12577 (double)(ts.total_space
12578 * pow(2.0, -32 + 24)));
12579 }
8d0ab76d 12580 }
d62a17ae 12581 break;
12582 default:
6c9d22e2
PG
12583 if (!json) {
12584 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12585 ts.counts[i]);
893cccd0 12586 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12587 table_stats_strs[i]
12588 [TABLE_STATS_IDX_VTY],
12589 temp_buf);
12590 } else {
12591 json_object_int_add(
12592 json,
12593 table_stats_strs[i]
12594 [TABLE_STATS_IDX_JSON],
12595 ts.counts[i]);
12596 }
d62a17ae 12597 }
893cccd0
PG
12598 if (!json)
12599 vty_out(vty, "\n");
d62a17ae 12600 }
9ab0cf58 12601end_table_stats:
6c9d22e2
PG
12602 if (json)
12603 json_object_array_add(json_array, json);
893cccd0 12604 return ret;
d62a17ae 12605}
12606
71f1613a
DA
12607static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12608 safi_t safi, struct json_object *json_array)
12609{
12610 if (!bgp) {
12611 bgp_table_stats_all(vty, afi, safi, json_array);
12612 return CMD_SUCCESS;
12613 }
12614
12615 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12616}
12617
d62a17ae 12618enum bgp_pcounts {
12619 PCOUNT_ADJ_IN = 0,
12620 PCOUNT_DAMPED,
12621 PCOUNT_REMOVED,
12622 PCOUNT_HISTORY,
12623 PCOUNT_STALE,
12624 PCOUNT_VALID,
12625 PCOUNT_ALL,
12626 PCOUNT_COUNTED,
7e3d9632 12627 PCOUNT_BPATH_SELECTED,
d62a17ae 12628 PCOUNT_PFCNT, /* the figure we display to users */
12629 PCOUNT_MAX,
a636c635 12630};
718e3744 12631
2b64873d 12632static const char *const pcount_strs[] = {
9d303b37
DL
12633 [PCOUNT_ADJ_IN] = "Adj-in",
12634 [PCOUNT_DAMPED] = "Damped",
12635 [PCOUNT_REMOVED] = "Removed",
12636 [PCOUNT_HISTORY] = "History",
12637 [PCOUNT_STALE] = "Stale",
12638 [PCOUNT_VALID] = "Valid",
12639 [PCOUNT_ALL] = "All RIB",
12640 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12641 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12642 [PCOUNT_PFCNT] = "Useable",
12643 [PCOUNT_MAX] = NULL,
a636c635 12644};
718e3744 12645
d62a17ae 12646struct peer_pcounts {
12647 unsigned int count[PCOUNT_MAX];
12648 const struct peer *peer;
12649 const struct bgp_table *table;
54317cba 12650 safi_t safi;
a636c635 12651};
47fc97cc 12652
9bcb3eef 12653static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12654{
54317cba
JW
12655 const struct bgp_adj_in *ain;
12656 const struct bgp_path_info *pi;
d62a17ae 12657 const struct peer *peer = pc->peer;
12658
54317cba
JW
12659 for (ain = rn->adj_in; ain; ain = ain->next)
12660 if (ain->peer == peer)
12661 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12662
9bcb3eef 12663 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12664
54317cba
JW
12665 if (pi->peer != peer)
12666 continue;
d62a17ae 12667
54317cba 12668 pc->count[PCOUNT_ALL]++;
d62a17ae 12669
54317cba
JW
12670 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12671 pc->count[PCOUNT_DAMPED]++;
12672 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12673 pc->count[PCOUNT_HISTORY]++;
12674 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12675 pc->count[PCOUNT_REMOVED]++;
12676 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12677 pc->count[PCOUNT_STALE]++;
12678 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12679 pc->count[PCOUNT_VALID]++;
12680 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12681 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12682 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12683 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12684
12685 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12686 pc->count[PCOUNT_COUNTED]++;
12687 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12688 flog_err(
12689 EC_LIB_DEVELOPMENT,
12690 "Attempting to count but flags say it is unusable");
12691 } else {
40381db7 12692 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12693 flog_err(
12694 EC_LIB_DEVELOPMENT,
12695 "Not counted but flags say we should");
d62a17ae 12696 }
12697 }
54317cba
JW
12698}
12699
12700static int bgp_peer_count_walker(struct thread *t)
12701{
9bcb3eef 12702 struct bgp_dest *rn, *rm;
54317cba
JW
12703 const struct bgp_table *table;
12704 struct peer_pcounts *pc = THREAD_ARG(t);
12705
12706 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12707 || pc->safi == SAFI_EVPN) {
12708 /* Special handling for 2-level routing tables. */
12709 for (rn = bgp_table_top(pc->table); rn;
12710 rn = bgp_route_next(rn)) {
9bcb3eef 12711 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12712 if (table != NULL)
12713 for (rm = bgp_table_top(table); rm;
12714 rm = bgp_route_next(rm))
12715 bgp_peer_count_proc(rm, pc);
12716 }
12717 } else
12718 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12719 bgp_peer_count_proc(rn, pc);
12720
d62a17ae 12721 return 0;
718e3744 12722}
12723
d62a17ae 12724static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12725 safi_t safi, bool use_json)
856ca177 12726{
d62a17ae 12727 struct peer_pcounts pcounts = {.peer = peer};
12728 unsigned int i;
12729 json_object *json = NULL;
12730 json_object *json_loop = NULL;
856ca177 12731
d62a17ae 12732 if (use_json) {
12733 json = json_object_new_object();
12734 json_loop = json_object_new_object();
12735 }
718e3744 12736
d62a17ae 12737 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12738 || !peer->bgp->rib[afi][safi]) {
12739 if (use_json) {
12740 json_object_string_add(
12741 json, "warning",
12742 "No such neighbor or address family");
12743 vty_out(vty, "%s\n", json_object_to_json_string(json));
12744 json_object_free(json);
12745 } else
12746 vty_out(vty, "%% No such neighbor or address family\n");
12747
12748 return CMD_WARNING;
12749 }
2a71e9ce 12750
d62a17ae 12751 memset(&pcounts, 0, sizeof(pcounts));
12752 pcounts.peer = peer;
12753 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12754 pcounts.safi = safi;
d62a17ae 12755
12756 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12757 * stats for the thread-walk (i.e. ensure this can't be blamed on
12758 * on just vty_read()).
12759 */
d62a17ae 12760 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12761
12762 if (use_json) {
12763 json_object_string_add(json, "prefixCountsFor", peer->host);
12764 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12765 get_afi_safi_str(afi, safi, true));
d62a17ae 12766 json_object_int_add(json, "pfxCounter",
12767 peer->pcount[afi][safi]);
12768
12769 for (i = 0; i < PCOUNT_MAX; i++)
12770 json_object_int_add(json_loop, pcount_strs[i],
12771 pcounts.count[i]);
12772
12773 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12774
12775 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12776 json_object_string_add(json, "pfxctDriftFor",
12777 peer->host);
12778 json_object_string_add(
12779 json, "recommended",
12780 "Please report this bug, with the above command output");
12781 }
996c9314
LB
12782 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12783 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12784 json_object_free(json);
12785 } else {
12786
12787 if (peer->hostname
892fedb6 12788 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12789 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12790 peer->hostname, peer->host,
5cb5f4d0 12791 get_afi_safi_str(afi, safi, false));
d62a17ae 12792 } else {
12793 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12794 get_afi_safi_str(afi, safi, false));
d62a17ae 12795 }
12796
6cde4b45 12797 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12798 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12799
12800 for (i = 0; i < PCOUNT_MAX; i++)
12801 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12802 pcounts.count[i]);
12803
12804 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12805 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12806 vty_out(vty,
12807 "Please report this bug, with the above command output\n");
12808 }
12809 }
12810
12811 return CMD_SUCCESS;
718e3744 12812}
12813
a636c635
DW
12814DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12815 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12816 "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 12817 SHOW_STR
12818 IP_STR
12819 BGP_STR
8386ac43 12820 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12821 BGP_AFI_HELP_STR
12822 BGP_SAFI_HELP_STR
0b16f239
DS
12823 "Detailed information on TCP and BGP neighbor connections\n"
12824 "Neighbor to display information about\n"
12825 "Neighbor to display information about\n"
91d37724 12826 "Neighbor on BGP configured interface\n"
a636c635 12827 "Display detailed prefix count information\n"
9973d184 12828 JSON_STR)
0b16f239 12829{
d62a17ae 12830 afi_t afi = AFI_IP6;
12831 safi_t safi = SAFI_UNICAST;
12832 struct peer *peer;
12833 int idx = 0;
12834 struct bgp *bgp = NULL;
9f049418
DS
12835 bool uj = use_json(argc, argv);
12836
12837 if (uj)
12838 argc--;
856ca177 12839
d62a17ae 12840 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12841 &bgp, uj);
d62a17ae 12842 if (!idx)
12843 return CMD_WARNING;
0b16f239 12844
d62a17ae 12845 argv_find(argv, argc, "neighbors", &idx);
12846 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12847 if (!peer)
12848 return CMD_WARNING;
bb46e94f 12849
29c8d9da 12850 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12851}
0b16f239 12852
d6902373
PG
12853#ifdef KEEP_OLD_VPN_COMMANDS
12854DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12855 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12856 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12857 SHOW_STR
12858 IP_STR
12859 BGP_STR
d6902373 12860 BGP_VPNVX_HELP_STR
91d37724 12861 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12862 "Detailed information on TCP and BGP neighbor connections\n"
12863 "Neighbor to display information about\n"
12864 "Neighbor to display information about\n"
91d37724 12865 "Neighbor on BGP configured interface\n"
a636c635 12866 "Display detailed prefix count information\n"
9973d184 12867 JSON_STR)
a636c635 12868{
d62a17ae 12869 int idx_peer = 6;
12870 struct peer *peer;
9f049418 12871 bool uj = use_json(argc, argv);
a636c635 12872
d62a17ae 12873 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12874 if (!peer)
12875 return CMD_WARNING;
12876
12877 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12878}
12879
d6902373
PG
12880DEFUN (show_ip_bgp_vpn_all_route_prefix,
12881 show_ip_bgp_vpn_all_route_prefix_cmd,
12882 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12883 SHOW_STR
12884 IP_STR
12885 BGP_STR
d6902373 12886 BGP_VPNVX_HELP_STR
91d37724
QY
12887 "Display information about all VPNv4 NLRIs\n"
12888 "Network in the BGP routing table to display\n"
3a2d747c 12889 "Network in the BGP routing table to display\n"
9973d184 12890 JSON_STR)
91d37724 12891{
d62a17ae 12892 int idx = 0;
12893 char *network = NULL;
12894 struct bgp *bgp = bgp_get_default();
12895 if (!bgp) {
12896 vty_out(vty, "Can't find default instance\n");
12897 return CMD_WARNING;
12898 }
87e34b58 12899
d62a17ae 12900 if (argv_find(argv, argc, "A.B.C.D", &idx))
12901 network = argv[idx]->arg;
12902 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12903 network = argv[idx]->arg;
12904 else {
12905 vty_out(vty, "Unable to figure out Network\n");
12906 return CMD_WARNING;
12907 }
87e34b58 12908
d62a17ae 12909 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12910 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12911}
d6902373 12912#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12913
44c69747
LK
12914DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12915 show_bgp_l2vpn_evpn_route_prefix_cmd,
12916 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12917 SHOW_STR
4c63a661
PG
12918 BGP_STR
12919 L2VPN_HELP_STR
12920 EVPN_HELP_STR
44c69747
LK
12921 "Network in the BGP routing table to display\n"
12922 "Network in the BGP routing table to display\n"
4c63a661
PG
12923 "Network in the BGP routing table to display\n"
12924 "Network in the BGP routing table to display\n"
12925 JSON_STR)
12926{
d62a17ae 12927 int idx = 0;
12928 char *network = NULL;
44c69747 12929 int prefix_check = 0;
a636c635 12930
44c69747
LK
12931 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12932 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12933 network = argv[idx]->arg;
44c69747 12934 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12935 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12936 network = argv[idx]->arg;
44c69747
LK
12937 prefix_check = 1;
12938 } else {
d62a17ae 12939 vty_out(vty, "Unable to figure out Network\n");
12940 return CMD_WARNING;
12941 }
44c69747
LK
12942 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12943 prefix_check, BGP_PATH_SHOW_ALL,
12944 use_json(argc, argv));
d62a17ae 12945}
12946
2f9bc755
DS
12947static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12948 struct bgp_table *table, int *header1,
12949 int *header2, json_object *json,
12950 json_object *json_scode,
12951 json_object *json_ocode, bool wide)
12952{
12953 uint64_t version = table ? table->version : 0;
23d0a753 12954 char buf[BUFSIZ] = {0};
2f9bc755
DS
12955
12956 if (*header1) {
12957 if (json) {
12958 json_object_int_add(json, "bgpTableVersion", version);
12959 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12960 inet_ntop(AF_INET,
12961 &bgp->router_id, buf,
12962 sizeof(buf)));
2f9bc755
DS
12963 json_object_int_add(json, "defaultLocPrf",
12964 bgp->default_local_pref);
12965 json_object_int_add(json, "localAS", bgp->as);
12966 json_object_object_add(json, "bgpStatusCodes",
12967 json_scode);
12968 json_object_object_add(json, "bgpOriginCodes",
12969 json_ocode);
12970 } else {
12971 vty_out(vty,
23d0a753
DA
12972 "BGP table version is %" PRIu64
12973 ", local router ID is %pI4, vrf id ",
12974 version, &bgp->router_id);
2f9bc755
DS
12975 if (bgp->vrf_id == VRF_UNKNOWN)
12976 vty_out(vty, "%s", VRFID_NONE_STR);
12977 else
12978 vty_out(vty, "%u", bgp->vrf_id);
12979 vty_out(vty, "\n");
12980 vty_out(vty, "Default local pref %u, ",
12981 bgp->default_local_pref);
12982 vty_out(vty, "local AS %u\n", bgp->as);
12983 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12984 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12985 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12986 }
12987 *header1 = 0;
12988 }
12989 if (*header2) {
12990 if (!json)
12991 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12992 : BGP_SHOW_HEADER));
12993 *header2 = 0;
12994 }
12995}
12996
d62a17ae 12997static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12998 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12999 const char *rmap_name, json_object *json,
13000 uint8_t show_flags)
d62a17ae 13001{
13002 struct bgp_table *table;
13003 struct bgp_adj_in *ain;
13004 struct bgp_adj_out *adj;
74a630b6
NT
13005 unsigned long output_count = 0;
13006 unsigned long filtered_count = 0;
9bcb3eef 13007 struct bgp_dest *dest;
d62a17ae 13008 int header1 = 1;
13009 struct bgp *bgp;
13010 int header2 = 1;
13011 struct attr attr;
13012 int ret;
13013 struct update_subgroup *subgrp;
13014 json_object *json_scode = NULL;
13015 json_object *json_ocode = NULL;
13016 json_object *json_ar = NULL;
13017 struct peer_af *paf;
f99def61 13018 bool route_filtered;
96f3485c
MK
13019 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13020 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 13021
13022 if (use_json) {
13023 json_scode = json_object_new_object();
13024 json_ocode = json_object_new_object();
13025 json_ar = json_object_new_object();
13026
13027 json_object_string_add(json_scode, "suppressed", "s");
13028 json_object_string_add(json_scode, "damped", "d");
13029 json_object_string_add(json_scode, "history", "h");
13030 json_object_string_add(json_scode, "valid", "*");
13031 json_object_string_add(json_scode, "best", ">");
13032 json_object_string_add(json_scode, "multipath", "=");
13033 json_object_string_add(json_scode, "internal", "i");
13034 json_object_string_add(json_scode, "ribFailure", "r");
13035 json_object_string_add(json_scode, "stale", "S");
13036 json_object_string_add(json_scode, "removed", "R");
13037
13038 json_object_string_add(json_ocode, "igp", "i");
13039 json_object_string_add(json_ocode, "egp", "e");
13040 json_object_string_add(json_ocode, "incomplete", "?");
13041 }
a636c635 13042
d62a17ae 13043 bgp = peer->bgp;
a636c635 13044
d62a17ae 13045 if (!bgp) {
13046 if (use_json) {
13047 json_object_string_add(json, "alert", "no BGP");
13048 vty_out(vty, "%s\n", json_object_to_json_string(json));
13049 json_object_free(json);
13050 } else
13051 vty_out(vty, "%% No bgp\n");
13052 return;
13053 }
a636c635 13054
c512a642
EDP
13055 /* labeled-unicast routes live in the unicast table */
13056 if (safi == SAFI_LABELED_UNICAST)
13057 table = bgp->rib[afi][SAFI_UNICAST];
13058 else
13059 table = bgp->rib[afi][safi];
d62a17ae 13060
13061 output_count = filtered_count = 0;
13062 subgrp = peer_subgroup(peer, afi, safi);
13063
6392aaa6 13064 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13065 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13066 char buf[BUFSIZ] = {0};
13067
d62a17ae 13068 if (use_json) {
13069 json_object_int_add(json, "bgpTableVersion",
13070 table->version);
13071 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13072 inet_ntop(AF_INET,
13073 &bgp->router_id, buf,
13074 sizeof(buf)));
01eced22
AD
13075 json_object_int_add(json, "defaultLocPrf",
13076 bgp->default_local_pref);
13077 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13078 json_object_object_add(json, "bgpStatusCodes",
13079 json_scode);
13080 json_object_object_add(json, "bgpOriginCodes",
13081 json_ocode);
07d0c4ed
DA
13082 json_object_string_add(
13083 json, "bgpOriginatingDefaultNetwork",
13084 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13085 } else {
23d0a753
DA
13086 vty_out(vty,
13087 "BGP table version is %" PRIu64
13088 ", local router ID is %pI4, vrf id ",
13089 table->version, &bgp->router_id);
9df8b37c
PZ
13090 if (bgp->vrf_id == VRF_UNKNOWN)
13091 vty_out(vty, "%s", VRFID_NONE_STR);
13092 else
13093 vty_out(vty, "%u", bgp->vrf_id);
13094 vty_out(vty, "\n");
01eced22
AD
13095 vty_out(vty, "Default local pref %u, ",
13096 bgp->default_local_pref);
13097 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13098 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13099 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13100 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13101
07d0c4ed
DA
13102 vty_out(vty, "Originating default network %s\n\n",
13103 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13104 }
13105 header1 = 0;
13106 }
a636c635 13107
9bcb3eef 13108 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13109 if (type == bgp_show_adj_route_received
13110 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13111 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13112 if (ain->peer != peer)
ea47320b 13113 continue;
6392aaa6 13114
2f9bc755
DS
13115 show_adj_route_header(
13116 vty, bgp, table, &header1, &header2,
13117 json, json_scode, json_ocode, wide);
6392aaa6 13118
6f4f49b2 13119 attr = *ain->attr;
f99def61
AD
13120 route_filtered = false;
13121
13122 /* Filter prefix using distribute list,
13123 * filter list or prefix list
13124 */
b54892e0 13125 const struct prefix *rn_p =
9bcb3eef 13126 bgp_dest_get_prefix(dest);
b54892e0
DS
13127 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13128 safi))
13129 == FILTER_DENY)
f99def61
AD
13130 route_filtered = true;
13131
13132 /* Filter prefix using route-map */
b54892e0
DS
13133 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13134 safi, rmap_name, NULL,
13135 0, NULL);
6392aaa6 13136
13c8e163
AD
13137 if (type == bgp_show_adj_route_filtered &&
13138 !route_filtered && ret != RMAP_DENY) {
b755861b 13139 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13140 continue;
d62a17ae 13141 }
6392aaa6 13142
13c8e163
AD
13143 if (type == bgp_show_adj_route_received &&
13144 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
13145 filtered_count++;
13146
b54892e0 13147 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13148 use_json, json_ar, wide);
b755861b 13149 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13150 output_count++;
d62a17ae 13151 }
6392aaa6 13152 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13153 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13154 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13155 if (paf->peer != peer || !adj->attr)
924c3f6a 13156 continue;
d62a17ae 13157
2f9bc755
DS
13158 show_adj_route_header(
13159 vty, bgp, table, &header1,
13160 &header2, json, json_scode,
13161 json_ocode, wide);
d62a17ae 13162
b54892e0 13163 const struct prefix *rn_p =
9bcb3eef 13164 bgp_dest_get_prefix(dest);
b54892e0 13165
6f4f49b2 13166 attr = *adj->attr;
b755861b 13167 ret = bgp_output_modifier(
b54892e0 13168 peer, rn_p, &attr, afi, safi,
b755861b 13169 rmap_name);
f46d8e1e 13170
b755861b 13171 if (ret != RMAP_DENY) {
b54892e0
DS
13172 route_vty_out_tmp(
13173 vty, rn_p, &attr, safi,
ae248832
MK
13174 use_json, json_ar,
13175 wide);
b755861b
PM
13176 output_count++;
13177 } else {
13178 filtered_count++;
a2addae8 13179 }
b755861b
PM
13180
13181 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13182 }
f20ce998
DS
13183 } else if (type == bgp_show_adj_route_bestpath) {
13184 struct bgp_path_info *pi;
13185
13186 show_adj_route_header(vty, bgp, table, &header1,
13187 &header2, json, json_scode,
13188 json_ocode, wide);
13189
13190 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13191 pi = pi->next) {
13192 if (pi->peer != peer)
13193 continue;
13194
13195 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13196 continue;
13197
13198 route_vty_out_tmp(vty,
13199 bgp_dest_get_prefix(dest),
13200 pi->attr, safi, use_json,
13201 json_ar, wide);
13202 output_count++;
13203 }
d62a17ae 13204 }
13205 }
d62a17ae 13206
d62a17ae 13207 if (use_json) {
6392aaa6
PM
13208 json_object_object_add(json, "advertisedRoutes", json_ar);
13209 json_object_int_add(json, "totalPrefixCounter", output_count);
13210 json_object_int_add(json, "filteredPrefixCounter",
13211 filtered_count);
13212
996c9314
LB
13213 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13214 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13215
13216 if (!output_count && !filtered_count) {
13217 json_object_free(json_scode);
13218 json_object_free(json_ocode);
13219 }
13220
d62a17ae 13221 json_object_free(json);
6392aaa6
PM
13222 } else if (output_count > 0) {
13223 if (filtered_count > 0)
13224 vty_out(vty,
13225 "\nTotal number of prefixes %ld (%ld filtered)\n",
13226 output_count, filtered_count);
13227 else
13228 vty_out(vty, "\nTotal number of prefixes %ld\n",
13229 output_count);
d62a17ae 13230 }
a636c635 13231}
2a71e9ce 13232
d62a17ae 13233static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13234 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13235 const char *rmap_name, uint8_t show_flags)
0b16f239 13236{
d62a17ae 13237 json_object *json = NULL;
96f3485c 13238 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13239
d62a17ae 13240 if (use_json)
13241 json = json_object_new_object();
0b16f239 13242
d62a17ae 13243 if (!peer || !peer->afc[afi][safi]) {
13244 if (use_json) {
13245 json_object_string_add(
13246 json, "warning",
13247 "No such neighbor or address family");
13248 vty_out(vty, "%s\n", json_object_to_json_string(json));
13249 json_object_free(json);
13250 } else
13251 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13252
d62a17ae 13253 return CMD_WARNING;
13254 }
13255
6392aaa6
PM
13256 if ((type == bgp_show_adj_route_received
13257 || type == bgp_show_adj_route_filtered)
d62a17ae 13258 && !CHECK_FLAG(peer->af_flags[afi][safi],
13259 PEER_FLAG_SOFT_RECONFIG)) {
13260 if (use_json) {
13261 json_object_string_add(
13262 json, "warning",
13263 "Inbound soft reconfiguration not enabled");
13264 vty_out(vty, "%s\n", json_object_to_json_string(json));
13265 json_object_free(json);
13266 } else
13267 vty_out(vty,
13268 "%% Inbound soft reconfiguration not enabled\n");
13269
13270 return CMD_WARNING;
13271 }
0b16f239 13272
96f3485c 13273 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13274
d62a17ae 13275 return CMD_SUCCESS;
a636c635 13276}
50ef26d4 13277
f20ce998
DS
13278DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13279 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13280 "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]",
13281 SHOW_STR
13282 IP_STR
13283 BGP_STR
13284 BGP_INSTANCE_HELP_STR
13285 BGP_AFI_HELP_STR
13286 BGP_SAFI_WITH_LABEL_HELP_STR
13287 "Detailed information on TCP and BGP neighbor connections\n"
13288 "Neighbor to display information about\n"
13289 "Neighbor to display information about\n"
13290 "Neighbor on BGP configured interface\n"
13291 "Display the routes selected by best path\n"
13292 JSON_STR
13293 "Increase table width for longer prefixes\n")
13294{
13295 afi_t afi = AFI_IP6;
13296 safi_t safi = SAFI_UNICAST;
13297 char *rmap_name = NULL;
13298 char *peerstr = NULL;
13299 struct bgp *bgp = NULL;
13300 struct peer *peer;
13301 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13302 int idx = 0;
96f3485c
MK
13303 uint8_t show_flags = 0;
13304
13305 if (uj)
13306 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13307
13308 if (wide)
13309 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13310
13311 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13312 &bgp, uj);
13313
13314 if (!idx)
13315 return CMD_WARNING;
13316
13317 argv_find(argv, argc, "neighbors", &idx);
13318 peerstr = argv[++idx]->arg;
13319
13320 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13321 if (!peer)
13322 return CMD_WARNING;
13323
96f3485c
MK
13324 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13325 show_flags);
f20ce998
DS
13326}
13327
ae248832 13328DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13329 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13330 "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 13331 SHOW_STR
13332 IP_STR
13333 BGP_STR
a636c635 13334 BGP_INSTANCE_HELP_STR
7395a2c9 13335 BGP_AFI_HELP_STR
4dd6177e 13336 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13337 "Display the entries for all address families\n"
718e3744 13338 "Detailed information on TCP and BGP neighbor connections\n"
13339 "Neighbor to display information about\n"
13340 "Neighbor to display information about\n"
91d37724 13341 "Neighbor on BGP configured interface\n"
a636c635 13342 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13343 "Display the received routes from neighbor\n"
13344 "Display the filtered routes received from neighbor\n"
a636c635
DW
13345 "Route-map to modify the attributes\n"
13346 "Name of the route map\n"
ae248832
MK
13347 JSON_STR
13348 "Increase table width for longer prefixes\n")
718e3744 13349{
d62a17ae 13350 afi_t afi = AFI_IP6;
13351 safi_t safi = SAFI_UNICAST;
13352 char *rmap_name = NULL;
13353 char *peerstr = NULL;
d62a17ae 13354 struct bgp *bgp = NULL;
13355 struct peer *peer;
6392aaa6 13356 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13357 int idx = 0;
96f3485c
MK
13358 bool first = true;
13359 uint8_t show_flags = 0;
6392aaa6 13360
96f3485c 13361 if (uj) {
d62a17ae 13362 argc--;
96f3485c
MK
13363 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13364 }
13365
13366 if (all) {
13367 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13368 if (argv_find(argv, argc, "ipv4", &idx))
13369 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13370
13371 if (argv_find(argv, argc, "ipv6", &idx))
13372 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13373 }
13374
13375 if (wide)
13376 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13377
9f049418
DS
13378 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13379 &bgp, uj);
13380 if (!idx)
13381 return CMD_WARNING;
13382
d62a17ae 13383 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13384 argv_find(argv, argc, "neighbors", &idx);
13385 peerstr = argv[++idx]->arg;
8c3deaae 13386
d62a17ae 13387 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13388 if (!peer)
13389 return CMD_WARNING;
856ca177 13390
d62a17ae 13391 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13392 type = bgp_show_adj_route_advertised;
13393 else if (argv_find(argv, argc, "received-routes", &idx))
13394 type = bgp_show_adj_route_received;
13395 else if (argv_find(argv, argc, "filtered-routes", &idx))
13396 type = bgp_show_adj_route_filtered;
13397
d62a17ae 13398 if (argv_find(argv, argc, "route-map", &idx))
13399 rmap_name = argv[++idx]->arg;
95cbbd2a 13400
96f3485c
MK
13401 if (!all)
13402 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13403 show_flags);
13404 if (uj)
13405 vty_out(vty, "{\n");
13406
13407 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13408 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13409 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13410 : AFI_IP6;
13411 FOREACH_SAFI (safi) {
96f3485c
MK
13412 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13413 continue;
13414
13415 if (uj) {
13416 if (first)
13417 first = false;
13418 else
13419 vty_out(vty, ",\n");
13420 vty_out(vty, "\"%s\":",
13421 get_afi_safi_str(afi, safi, true));
13422 } else
13423 vty_out(vty, "\nFor address family: %s\n",
13424 get_afi_safi_str(afi, safi, false));
13425
13426 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13427 show_flags);
13428 }
13429 } else {
13430 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13431 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13432 continue;
13433
13434 if (uj) {
13435 if (first)
13436 first = false;
13437 else
13438 vty_out(vty, ",\n");
13439 vty_out(vty, "\"%s\":",
13440 get_afi_safi_str(afi, safi, true));
13441 } else
13442 vty_out(vty, "\nFor address family: %s\n",
13443 get_afi_safi_str(afi, safi, false));
13444
13445 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13446 show_flags);
13447 }
13448 }
13449 if (uj)
13450 vty_out(vty, "}\n");
13451
13452 return CMD_SUCCESS;
95cbbd2a
ML
13453}
13454
718e3744 13455DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13456 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13457 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13458 SHOW_STR
13459 IP_STR
13460 BGP_STR
8c3deaae
QY
13461 "Address Family\n"
13462 "Address Family\n"
718e3744 13463 "Address Family modifier\n"
13464 "Detailed information on TCP and BGP neighbor connections\n"
13465 "Neighbor to display information about\n"
13466 "Neighbor to display information about\n"
91d37724 13467 "Neighbor on BGP configured interface\n"
718e3744 13468 "Display information received from a BGP neighbor\n"
856ca177 13469 "Display the prefixlist filter\n"
9973d184 13470 JSON_STR)
718e3744 13471{
d62a17ae 13472 afi_t afi = AFI_IP6;
13473 safi_t safi = SAFI_UNICAST;
13474 char *peerstr = NULL;
13475
13476 char name[BUFSIZ];
13477 union sockunion su;
13478 struct peer *peer;
13479 int count, ret;
13480
13481 int idx = 0;
13482
13483 /* show [ip] bgp */
13484 if (argv_find(argv, argc, "ip", &idx))
13485 afi = AFI_IP;
13486 /* [<ipv4|ipv6> [unicast]] */
13487 if (argv_find(argv, argc, "ipv4", &idx))
13488 afi = AFI_IP;
13489 if (argv_find(argv, argc, "ipv6", &idx))
13490 afi = AFI_IP6;
13491 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13492 argv_find(argv, argc, "neighbors", &idx);
13493 peerstr = argv[++idx]->arg;
13494
9f049418 13495 bool uj = use_json(argc, argv);
d62a17ae 13496
13497 ret = str2sockunion(peerstr, &su);
13498 if (ret < 0) {
13499 peer = peer_lookup_by_conf_if(NULL, peerstr);
13500 if (!peer) {
13501 if (uj)
13502 vty_out(vty, "{}\n");
13503 else
13504 vty_out(vty,
13505 "%% Malformed address or name: %s\n",
13506 peerstr);
13507 return CMD_WARNING;
13508 }
13509 } else {
13510 peer = peer_lookup(NULL, &su);
13511 if (!peer) {
13512 if (uj)
13513 vty_out(vty, "{}\n");
13514 else
13515 vty_out(vty, "No peer\n");
13516 return CMD_WARNING;
13517 }
13518 }
718e3744 13519
4ced1a2c 13520 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13521 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13522 if (count) {
13523 if (!uj)
13524 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13525 get_afi_safi_str(afi, safi, false));
d62a17ae 13526 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13527 } else {
13528 if (uj)
13529 vty_out(vty, "{}\n");
13530 else
13531 vty_out(vty, "No functional output\n");
13532 }
718e3744 13533
d62a17ae 13534 return CMD_SUCCESS;
13535}
13536
13537static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13538 afi_t afi, safi_t safi,
9f049418 13539 enum bgp_show_type type, bool use_json)
d62a17ae 13540{
96f3485c
MK
13541 uint8_t show_flags = 0;
13542
13543 if (use_json)
13544 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13545
d62a17ae 13546 if (!peer || !peer->afc[afi][safi]) {
13547 if (use_json) {
13548 json_object *json_no = NULL;
13549 json_no = json_object_new_object();
13550 json_object_string_add(
13551 json_no, "warning",
13552 "No such neighbor or address family");
13553 vty_out(vty, "%s\n",
13554 json_object_to_json_string(json_no));
13555 json_object_free(json_no);
13556 } else
13557 vty_out(vty, "%% No such neighbor or address family\n");
13558 return CMD_WARNING;
13559 }
47fc97cc 13560
7daf25a3
TA
13561 /* labeled-unicast routes live in the unicast table */
13562 if (safi == SAFI_LABELED_UNICAST)
13563 safi = SAFI_UNICAST;
13564
96f3485c 13565 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13566}
13567
dba3c1d3
PG
13568DEFUN (show_ip_bgp_flowspec_routes_detailed,
13569 show_ip_bgp_flowspec_routes_detailed_cmd,
13570 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13571 SHOW_STR
13572 IP_STR
13573 BGP_STR
13574 BGP_INSTANCE_HELP_STR
13575 BGP_AFI_HELP_STR
13576 "SAFI Flowspec\n"
13577 "Detailed information on flowspec entries\n"
13578 JSON_STR)
13579{
13580 afi_t afi = AFI_IP;
13581 safi_t safi = SAFI_UNICAST;
13582 struct bgp *bgp = NULL;
13583 int idx = 0;
9f049418 13584 bool uj = use_json(argc, argv);
96f3485c 13585 uint8_t show_flags = 0;
9f049418 13586
96f3485c 13587 if (uj) {
9f049418 13588 argc--;
96f3485c
MK
13589 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13590 }
dba3c1d3
PG
13591
13592 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13593 &bgp, uj);
dba3c1d3
PG
13594 if (!idx)
13595 return CMD_WARNING;
13596
96f3485c
MK
13597 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13598 show_flags);
dba3c1d3
PG
13599}
13600
718e3744 13601DEFUN (show_ip_bgp_neighbor_routes,
13602 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13603 "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 13604 SHOW_STR
13605 IP_STR
13606 BGP_STR
8386ac43 13607 BGP_INSTANCE_HELP_STR
4f280b15 13608 BGP_AFI_HELP_STR
4dd6177e 13609 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13610 "Detailed information on TCP and BGP neighbor connections\n"
13611 "Neighbor to display information about\n"
13612 "Neighbor to display information about\n"
91d37724 13613 "Neighbor on BGP configured interface\n"
2525cf39 13614 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13615 "Display the dampened routes received from neighbor\n"
13616 "Display routes learned from neighbor\n"
9973d184 13617 JSON_STR)
718e3744 13618{
d62a17ae 13619 char *peerstr = NULL;
13620 struct bgp *bgp = NULL;
13621 afi_t afi = AFI_IP6;
13622 safi_t safi = SAFI_UNICAST;
13623 struct peer *peer;
13624 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13625 int idx = 0;
9f049418
DS
13626 bool uj = use_json(argc, argv);
13627
13628 if (uj)
13629 argc--;
bb46e94f 13630
d62a17ae 13631 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13632 &bgp, uj);
d62a17ae 13633 if (!idx)
13634 return CMD_WARNING;
c493f2d8 13635
d62a17ae 13636 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13637 argv_find(argv, argc, "neighbors", &idx);
13638 peerstr = argv[++idx]->arg;
8c3deaae 13639
d62a17ae 13640 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13641 if (!peer)
d62a17ae 13642 return CMD_WARNING;
bb46e94f 13643
d62a17ae 13644 if (argv_find(argv, argc, "flap-statistics", &idx))
13645 sh_type = bgp_show_type_flap_neighbor;
13646 else if (argv_find(argv, argc, "dampened-routes", &idx))
13647 sh_type = bgp_show_type_damp_neighbor;
13648 else if (argv_find(argv, argc, "routes", &idx))
13649 sh_type = bgp_show_type_neighbor;
2525cf39 13650
d62a17ae 13651 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13652}
6b0655a2 13653
734b349e 13654struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13655
d62a17ae 13656struct bgp_distance {
13657 /* Distance value for the IP source prefix. */
d7c0a89a 13658 uint8_t distance;
718e3744 13659
d62a17ae 13660 /* Name of the access-list to be matched. */
13661 char *access_list;
718e3744 13662};
13663
4f280b15
LB
13664DEFUN (show_bgp_afi_vpn_rd_route,
13665 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13666 "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
13667 SHOW_STR
13668 BGP_STR
13669 BGP_AFI_HELP_STR
13670 "Address Family modifier\n"
13671 "Display information for a route distinguisher\n"
13672 "Route Distinguisher\n"
7395a2c9
DS
13673 "Network in the BGP routing table to display\n"
13674 "Network in the BGP routing table to display\n"
13675 JSON_STR)
4f280b15 13676{
d62a17ae 13677 int ret;
13678 struct prefix_rd prd;
13679 afi_t afi = AFI_MAX;
13680 int idx = 0;
4f280b15 13681
ff6566f3
DS
13682 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13683 vty_out(vty, "%% Malformed Address Family\n");
13684 return CMD_WARNING;
13685 }
13686
d62a17ae 13687 ret = str2prefix_rd(argv[5]->arg, &prd);
13688 if (!ret) {
13689 vty_out(vty, "%% Malformed Route Distinguisher\n");
13690 return CMD_WARNING;
13691 }
ff6566f3 13692
d62a17ae 13693 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13694 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13695}
13696
d62a17ae 13697static struct bgp_distance *bgp_distance_new(void)
718e3744 13698{
d62a17ae 13699 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13700}
13701
d62a17ae 13702static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13703{
d62a17ae 13704 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13705}
13706
37a87b8f
CS
13707int bgp_distance_set(uint8_t distance, const char *ip_str,
13708 const char *access_list_str, afi_t afi, safi_t safi,
13709 char *errmsg, size_t errmsg_len)
718e3744 13710{
d62a17ae 13711 int ret;
d62a17ae 13712 struct prefix p;
9bcb3eef 13713 struct bgp_dest *dest;
d62a17ae 13714 struct bgp_distance *bdistance;
718e3744 13715
d62a17ae 13716 ret = str2prefix(ip_str, &p);
13717 if (ret == 0) {
37a87b8f 13718 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13719 return CMD_WARNING_CONFIG_FAILED;
13720 }
718e3744 13721
d62a17ae 13722 /* Get BGP distance node. */
9bcb3eef
DS
13723 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13724 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13725 if (bdistance)
9bcb3eef 13726 bgp_dest_unlock_node(dest);
ca2e160d 13727 else {
d62a17ae 13728 bdistance = bgp_distance_new();
9bcb3eef 13729 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13730 }
718e3744 13731
d62a17ae 13732 /* Set distance value. */
13733 bdistance->distance = distance;
718e3744 13734
d62a17ae 13735 /* Reset access-list configuration. */
e1b36e13 13736 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13737 if (access_list_str)
13738 bdistance->access_list =
13739 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13740
d62a17ae 13741 return CMD_SUCCESS;
718e3744 13742}
13743
37a87b8f
CS
13744int bgp_distance_unset(uint8_t distance, const char *ip_str,
13745 const char *access_list_str, afi_t afi, safi_t safi,
13746 char *errmsg, size_t errmsg_len)
718e3744 13747{
d62a17ae 13748 int ret;
d62a17ae 13749 struct prefix p;
9bcb3eef 13750 struct bgp_dest *dest;
d62a17ae 13751 struct bgp_distance *bdistance;
718e3744 13752
d62a17ae 13753 ret = str2prefix(ip_str, &p);
13754 if (ret == 0) {
37a87b8f 13755 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13756 return CMD_WARNING_CONFIG_FAILED;
13757 }
718e3744 13758
9bcb3eef
DS
13759 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13760 if (!dest) {
37a87b8f 13761 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13762 return CMD_WARNING_CONFIG_FAILED;
13763 }
718e3744 13764
9bcb3eef 13765 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13766
d62a17ae 13767 if (bdistance->distance != distance) {
37a87b8f
CS
13768 snprintf(errmsg, errmsg_len,
13769 "Distance does not match configured\n");
d62a17ae 13770 return CMD_WARNING_CONFIG_FAILED;
13771 }
718e3744 13772
0a22ddfb 13773 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13774 bgp_distance_free(bdistance);
718e3744 13775
9bcb3eef
DS
13776 bgp_dest_set_bgp_path_info(dest, NULL);
13777 bgp_dest_unlock_node(dest);
13778 bgp_dest_unlock_node(dest);
718e3744 13779
d62a17ae 13780 return CMD_SUCCESS;
718e3744 13781}
13782
718e3744 13783/* Apply BGP information to distance method. */
b8685f9b 13784uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13785 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13786{
9bcb3eef 13787 struct bgp_dest *dest;
801bb996 13788 struct prefix q = {0};
d62a17ae 13789 struct peer *peer;
13790 struct bgp_distance *bdistance;
13791 struct access_list *alist;
13792 struct bgp_static *bgp_static;
13793
13794 if (!bgp)
13795 return 0;
13796
40381db7 13797 peer = pinfo->peer;
d62a17ae 13798
7b7d48e5
DS
13799 if (pinfo->attr->distance)
13800 return pinfo->attr->distance;
13801
801bb996
CS
13802 /* Check source address.
13803 * Note: for aggregate route, peer can have unspec af type.
13804 */
13805 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13806 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
13807 return 0;
13808
9bcb3eef
DS
13809 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13810 if (dest) {
13811 bdistance = bgp_dest_get_bgp_distance_info(dest);
13812 bgp_dest_unlock_node(dest);
d62a17ae 13813
13814 if (bdistance->access_list) {
13815 alist = access_list_lookup(afi, bdistance->access_list);
13816 if (alist
13817 && access_list_apply(alist, p) == FILTER_PERMIT)
13818 return bdistance->distance;
13819 } else
13820 return bdistance->distance;
718e3744 13821 }
718e3744 13822
d62a17ae 13823 /* Backdoor check. */
9bcb3eef
DS
13824 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13825 if (dest) {
13826 bgp_static = bgp_dest_get_bgp_static_info(dest);
13827 bgp_dest_unlock_node(dest);
718e3744 13828
d62a17ae 13829 if (bgp_static->backdoor) {
13830 if (bgp->distance_local[afi][safi])
13831 return bgp->distance_local[afi][safi];
13832 else
13833 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13834 }
718e3744 13835 }
718e3744 13836
d62a17ae 13837 if (peer->sort == BGP_PEER_EBGP) {
13838 if (bgp->distance_ebgp[afi][safi])
13839 return bgp->distance_ebgp[afi][safi];
13840 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 13841 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 13842 if (bgp->distance_ibgp[afi][safi])
13843 return bgp->distance_ibgp[afi][safi];
13844 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
13845 } else {
13846 if (bgp->distance_local[afi][safi])
13847 return bgp->distance_local[afi][safi];
13848 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 13849 }
718e3744 13850}
13851
a612fb77
DA
13852/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13853 * we should tell ZEBRA update the routes for a specific
13854 * AFI/SAFI to reflect changes in RIB.
13855 */
37a87b8f
CS
13856void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13857 safi_t update_safi)
a612fb77
DA
13858{
13859 afi_t afi;
13860 safi_t safi;
13861
13862 FOREACH_AFI_SAFI (afi, safi) {
13863 if (!bgp_fibupd_safi(safi))
13864 continue;
13865
8b54bc30
DA
13866 if (afi != update_afi && safi != update_safi)
13867 continue;
13868
13869 if (BGP_DEBUG(zebra, ZEBRA))
13870 zlog_debug(
13871 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13872 __func__, afi, safi);
13873 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13874 }
13875}
13876
37a87b8f
CS
13877DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13878 "distance bgp (1-255) (1-255) (1-255)",
13879 "Define an administrative distance\n"
13880 "BGP distance\n"
13881 "Distance for routes external to the AS\n"
13882 "Distance for routes internal to the AS\n"
13883 "Distance for local routes\n")
718e3744 13884{
d62a17ae 13885 int idx_number = 2;
13886 int idx_number_2 = 3;
13887 int idx_number_3 = 4;
13888 afi_t afi;
13889 safi_t safi;
37a87b8f 13890 char xpath[XPATH_MAXLEN];
718e3744 13891
d62a17ae 13892 afi = bgp_node_afi(vty);
13893 safi = bgp_node_safi(vty);
718e3744 13894
37a87b8f
CS
13895 snprintf(
13896 xpath, sizeof(xpath),
13897 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13898 yang_afi_safi_value2identity(afi, safi),
13899 bgp_afi_safi_get_container_str(afi, safi));
13900 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13901 snprintf(
13902 xpath, sizeof(xpath),
13903 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13904 yang_afi_safi_value2identity(afi, safi),
13905 bgp_afi_safi_get_container_str(afi, safi));
13906 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13907 argv[idx_number_2]->arg);
13908 snprintf(
13909 xpath, sizeof(xpath),
13910 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13911 yang_afi_safi_value2identity(afi, safi),
13912 bgp_afi_safi_get_container_str(afi, safi));
13913
13914 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13915 argv[idx_number_3]->arg);
13916
13917 return nb_cli_apply_changes(vty, NULL);
13918}
13919
13920DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13921 "no distance bgp [(1-255) (1-255) (1-255)]",
13922 NO_STR
13923 "Define an administrative distance\n"
13924 "BGP distance\n"
13925 "Distance for routes external to the AS\n"
13926 "Distance for routes internal to the AS\n"
13927 "Distance for local routes\n")
13928{
13929 afi_t afi;
13930 safi_t safi;
13931 char xpath[XPATH_MAXLEN];
13932
13933 afi = bgp_node_afi(vty);
13934 safi = bgp_node_safi(vty);
13935
13936 snprintf(
13937 xpath, sizeof(xpath),
13938 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13939 yang_afi_safi_value2identity(afi, safi),
13940 bgp_afi_safi_get_container_str(afi, safi));
13941 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13942 snprintf(
13943 xpath, sizeof(xpath),
13944 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13945 yang_afi_safi_value2identity(afi, safi),
13946 bgp_afi_safi_get_container_str(afi, safi));
13947 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13948 snprintf(
13949 xpath, sizeof(xpath),
13950 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13951 yang_afi_safi_value2identity(afi, safi),
13952 bgp_afi_safi_get_container_str(afi, safi));
13953
13954 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13955
13956 return nb_cli_apply_changes(vty, NULL);
718e3744 13957}
13958
37a87b8f
CS
13959void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
13960 struct lyd_node *dnode,
13961 bool show_defaults)
718e3744 13962{
37a87b8f
CS
13963 uint8_t distance_ebgp, distance_ibgp, distance_local;
13964
13965 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
13966 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
13967 distance_local = yang_dnode_get_uint8(dnode, "./local");
13968
13969 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
13970 distance_local);
13971}
13972
8cc7152a
CS
13973DEFPY_YANG(bgp_distance_source,
13974 bgp_distance_source_cmd,
13975 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
13976 NO_STR
13977 "Define an administrative distance\n"
8cc7152a 13978 "Distance value\n"
e12affc1
SW
13979 "IPv4 source prefix\n"
13980 "IPv6 source prefix\n"
37a87b8f 13981 "Access list name\n")
718e3744 13982{
37a87b8f
CS
13983 afi_t afi;
13984 safi_t safi;
13985 char xpath[XPATH_MAXLEN];
13986
13987 afi = bgp_node_afi(vty);
13988 safi = bgp_node_safi(vty);
13989
8cc7152a
CS
13990 if (!no) {
13991 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
13992 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
13993 distance_str);
13994 if (acl)
13995 nb_cli_enqueue_change(vty,
13996 "./access-list-policy-export",
13997 NB_OP_CREATE, acl);
13998 else
13999 nb_cli_enqueue_change(vty,
14000 "./access-list-policy-export",
14001 NB_OP_DESTROY, NULL);
14002 } else {
14003 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14004 }
37a87b8f
CS
14005
14006 snprintf(
14007 xpath, sizeof(xpath),
14008 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14009 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14010 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14011
14012 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14013}
14014
37a87b8f
CS
14015void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14016 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14017{
14018 vty_out(vty, " distance %d %s %s\n",
14019 yang_dnode_get_uint8(dnode, "./distance"),
14020 yang_dnode_get_string(dnode, "./prefix"),
14021 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14022 ? yang_dnode_get_string(dnode,
14023 "./access-list-policy-export")
14024 : "");
14025}
14026
7c98d487
DA
14027DEFPY_YANG(
14028 bgp_dampening, bgp_dampening_cmd,
14029 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14030 NO_STR
14031 "BGP Specific commands\n"
14032 "Enable route-flap dampening\n"
14033 "Half-life time for the penalty\n"
14034 "Value to start reusing a route\n"
14035 "Value to start suppressing a route\n"
14036 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14037{
14038 afi_t afi;
14039 safi_t safi;
14040 char xpath[XPATH_MAXLEN];
718e3744 14041
37a87b8f
CS
14042 afi = bgp_node_afi(vty);
14043 safi = bgp_node_safi(vty);
14044
d9ce5113
CS
14045 if (!no) {
14046 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14047 if (argc == 6) {
14048 nb_cli_enqueue_change(vty, "./reach-decay",
14049 NB_OP_MODIFY, halflife_str);
14050 nb_cli_enqueue_change(vty, "./reuse-above",
14051 NB_OP_MODIFY, reuse_str);
14052 nb_cli_enqueue_change(vty, "./suppress-above",
14053 NB_OP_MODIFY, suppress_str);
14054 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14055 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14056 } if (argc == 3) {
14057 nb_cli_enqueue_change(vty, "./reach-decay",
14058 NB_OP_MODIFY, halflife_str);
14059 }
14060 } else {
14061 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14062 }
7ebe9748 14063
37a87b8f
CS
14064 snprintf(
14065 xpath, sizeof(xpath),
14066 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14067 yang_afi_safi_value2identity(afi, safi),
14068 bgp_afi_safi_get_container_str(afi, safi));
14069
14070 return nb_cli_apply_changes(vty, xpath);
718e3744 14071}
14072
37a87b8f
CS
14073void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14074 struct lyd_node *dnode,
14075 bool show_defaults)
718e3744 14076{
37a87b8f
CS
14077 if (!yang_dnode_get_bool(dnode, "./enable"))
14078 return;
14079
14080 int half = DEFAULT_HALF_LIFE * 60;
14081 int reuse = DEFAULT_REUSE;
14082 int suppress = DEFAULT_SUPPRESS;
14083 int max;
14084
14085 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14086 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14087 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14088 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14089
14090 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14091 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14092 vty_out(vty, " bgp dampening\n");
14093 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14094 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14095 vty_out(vty, " bgp dampening %u\n", half);
14096 else
14097 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14098 suppress, max);
718e3744 14099}
14100
718e3744 14101/* Display specified route of BGP table. */
d62a17ae 14102static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14103 const char *ip_str, afi_t afi, safi_t safi,
14104 struct prefix_rd *prd, int prefix_check)
14105{
14106 int ret;
14107 struct prefix match;
9bcb3eef
DS
14108 struct bgp_dest *dest;
14109 struct bgp_dest *rm;
40381db7
DS
14110 struct bgp_path_info *pi;
14111 struct bgp_path_info *pi_temp;
d62a17ae 14112 struct bgp *bgp;
14113 struct bgp_table *table;
14114
14115 /* BGP structure lookup. */
14116 if (view_name) {
14117 bgp = bgp_lookup_by_name(view_name);
14118 if (bgp == NULL) {
14119 vty_out(vty, "%% Can't find BGP instance %s\n",
14120 view_name);
14121 return CMD_WARNING;
14122 }
14123 } else {
14124 bgp = bgp_get_default();
14125 if (bgp == NULL) {
14126 vty_out(vty, "%% No BGP process is configured\n");
14127 return CMD_WARNING;
14128 }
718e3744 14129 }
718e3744 14130
d62a17ae 14131 /* Check IP address argument. */
14132 ret = str2prefix(ip_str, &match);
14133 if (!ret) {
14134 vty_out(vty, "%% address is malformed\n");
14135 return CMD_WARNING;
14136 }
718e3744 14137
d62a17ae 14138 match.family = afi2family(afi);
14139
14140 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14141 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14142 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14143 dest = bgp_route_next(dest)) {
14144 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14145
9bcb3eef 14146 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14147 continue;
9bcb3eef 14148 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14149 if (!table)
ea47320b
DL
14150 continue;
14151 if ((rm = bgp_node_match(table, &match)) == NULL)
14152 continue;
d62a17ae 14153
9bcb3eef 14154 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14155
ea47320b 14156 if (!prefix_check
b54892e0 14157 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14158 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14159 while (pi) {
14160 if (pi->extra && pi->extra->damp_info) {
14161 pi_temp = pi->next;
ea47320b 14162 bgp_damp_info_free(
40ec3340
DS
14163 &pi->extra->damp_info,
14164 &bgp->damp[afi][safi],
a935f597 14165 1, afi, safi);
40381db7 14166 pi = pi_temp;
ea47320b 14167 } else
40381db7 14168 pi = pi->next;
d62a17ae 14169 }
ea47320b
DL
14170 }
14171
9bcb3eef 14172 bgp_dest_unlock_node(rm);
d62a17ae 14173 }
14174 } else {
9bcb3eef 14175 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14176 != NULL) {
9bcb3eef 14177 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14178
d62a17ae 14179 if (!prefix_check
9bcb3eef
DS
14180 || dest_p->prefixlen == match.prefixlen) {
14181 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14182 while (pi) {
14183 if (pi->extra && pi->extra->damp_info) {
14184 pi_temp = pi->next;
d62a17ae 14185 bgp_damp_info_free(
40ec3340
DS
14186 &pi->extra->damp_info,
14187 &bgp->damp[afi][safi],
a935f597 14188 1, afi, safi);
40381db7 14189 pi = pi_temp;
d62a17ae 14190 } else
40381db7 14191 pi = pi->next;
d62a17ae 14192 }
14193 }
14194
9bcb3eef 14195 bgp_dest_unlock_node(dest);
d62a17ae 14196 }
14197 }
718e3744 14198
d62a17ae 14199 return CMD_SUCCESS;
718e3744 14200}
14201
14202DEFUN (clear_ip_bgp_dampening,
14203 clear_ip_bgp_dampening_cmd,
14204 "clear ip bgp dampening",
14205 CLEAR_STR
14206 IP_STR
14207 BGP_STR
14208 "Clear route flap dampening information\n")
14209{
40ec3340
DS
14210 VTY_DECLVAR_CONTEXT(bgp, bgp);
14211 bgp_damp_info_clean(&bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
14212 SAFI_UNICAST);
d62a17ae 14213 return CMD_SUCCESS;
718e3744 14214}
14215
14216DEFUN (clear_ip_bgp_dampening_prefix,
14217 clear_ip_bgp_dampening_prefix_cmd,
14218 "clear ip bgp dampening A.B.C.D/M",
14219 CLEAR_STR
14220 IP_STR
14221 BGP_STR
14222 "Clear route flap dampening information\n"
0c7b1b01 14223 "IPv4 prefix\n")
718e3744 14224{
d62a17ae 14225 int idx_ipv4_prefixlen = 4;
14226 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14227 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14228}
14229
14230DEFUN (clear_ip_bgp_dampening_address,
14231 clear_ip_bgp_dampening_address_cmd,
14232 "clear ip bgp dampening A.B.C.D",
14233 CLEAR_STR
14234 IP_STR
14235 BGP_STR
14236 "Clear route flap dampening information\n"
14237 "Network to clear damping information\n")
14238{
d62a17ae 14239 int idx_ipv4 = 4;
14240 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14241 SAFI_UNICAST, NULL, 0);
718e3744 14242}
14243
14244DEFUN (clear_ip_bgp_dampening_address_mask,
14245 clear_ip_bgp_dampening_address_mask_cmd,
14246 "clear ip bgp dampening A.B.C.D A.B.C.D",
14247 CLEAR_STR
14248 IP_STR
14249 BGP_STR
14250 "Clear route flap dampening information\n"
14251 "Network to clear damping information\n"
14252 "Network mask\n")
14253{
d62a17ae 14254 int idx_ipv4 = 4;
14255 int idx_ipv4_2 = 5;
14256 int ret;
14257 char prefix_str[BUFSIZ];
718e3744 14258
d62a17ae 14259 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14260 prefix_str);
14261 if (!ret) {
14262 vty_out(vty, "%% Inconsistent address and mask\n");
14263 return CMD_WARNING;
14264 }
718e3744 14265
d62a17ae 14266 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14267 NULL, 0);
718e3744 14268}
6b0655a2 14269
e3b78da8 14270static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14271{
14272 struct vty *vty = arg;
e3b78da8 14273 struct peer *peer = bucket->data;
825d9834
DS
14274 char buf[SU_ADDRSTRLEN];
14275
14276 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14277 sockunion2str(&peer->su, buf, sizeof(buf)));
14278}
14279
2a0e69ae
DS
14280DEFUN (show_bgp_listeners,
14281 show_bgp_listeners_cmd,
14282 "show bgp listeners",
14283 SHOW_STR
14284 BGP_STR
14285 "Display Listen Sockets and who created them\n")
14286{
14287 bgp_dump_listener_info(vty);
14288
14289 return CMD_SUCCESS;
14290}
14291
825d9834
DS
14292DEFUN (show_bgp_peerhash,
14293 show_bgp_peerhash_cmd,
14294 "show bgp peerhash",
14295 SHOW_STR
14296 BGP_STR
14297 "Display information about the BGP peerhash\n")
14298{
14299 struct list *instances = bm->bgp;
14300 struct listnode *node;
14301 struct bgp *bgp;
14302
14303 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14304 vty_out(vty, "BGP: %s\n", bgp->name);
14305 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14306 vty);
14307 }
14308
14309 return CMD_SUCCESS;
14310}
14311
587ff0fd 14312/* also used for encap safi */
2b791107
DL
14313static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14314 afi_t afi, safi_t safi)
d62a17ae 14315{
9bcb3eef
DS
14316 struct bgp_dest *pdest;
14317 struct bgp_dest *dest;
d62a17ae 14318 struct bgp_table *table;
b54892e0
DS
14319 const struct prefix *p;
14320 const struct prefix_rd *prd;
d62a17ae 14321 struct bgp_static *bgp_static;
14322 mpls_label_t label;
d62a17ae 14323 char rdbuf[RD_ADDRSTRLEN];
14324
14325 /* Network configuration. */
9bcb3eef
DS
14326 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14327 pdest = bgp_route_next(pdest)) {
14328 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14329 if (!table)
ea47320b 14330 continue;
d62a17ae 14331
9bcb3eef
DS
14332 for (dest = bgp_table_top(table); dest;
14333 dest = bgp_route_next(dest)) {
14334 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14335 if (bgp_static == NULL)
ea47320b 14336 continue;
d62a17ae 14337
9bcb3eef
DS
14338 p = bgp_dest_get_prefix(dest);
14339 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14340 pdest);
d62a17ae 14341
ea47320b 14342 /* "network" configuration display. */
06b9f471 14343 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14344 label = decode_label(&bgp_static->label);
14345
8228a9a7 14346 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14347 if (safi == SAFI_MPLS_VPN)
14348 vty_out(vty, " label %u", label);
14349
14350 if (bgp_static->rmap.name)
14351 vty_out(vty, " route-map %s",
14352 bgp_static->rmap.name);
e2a86ad9
DS
14353
14354 if (bgp_static->backdoor)
14355 vty_out(vty, " backdoor");
14356
ea47320b
DL
14357 vty_out(vty, "\n");
14358 }
14359 }
d62a17ae 14360}
14361
2b791107
DL
14362static void bgp_config_write_network_evpn(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;
ff44f570 14371 char buf[PREFIX_STRLEN * 2];
d62a17ae 14372 char buf2[SU_ADDRSTRLEN];
14373 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14374 char esi_buf[ESI_BYTES];
d62a17ae 14375
14376 /* Network configuration. */
9bcb3eef
DS
14377 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14378 pdest = bgp_route_next(pdest)) {
14379 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14380 if (!table)
ea47320b 14381 continue;
d62a17ae 14382
9bcb3eef
DS
14383 for (dest = bgp_table_top(table); dest;
14384 dest = bgp_route_next(dest)) {
14385 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14386 if (bgp_static == NULL)
ea47320b 14387 continue;
d62a17ae 14388
ea47320b 14389 char *macrouter = NULL;
d62a17ae 14390
ea47320b
DL
14391 if (bgp_static->router_mac)
14392 macrouter = prefix_mac2str(
14393 bgp_static->router_mac, NULL, 0);
14394 if (bgp_static->eth_s_id)
0a50c248
AK
14395 esi_to_str(bgp_static->eth_s_id,
14396 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14397 p = bgp_dest_get_prefix(dest);
14398 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14399
ea47320b 14400 /* "network" configuration display. */
06b9f471 14401 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14402 if (p->u.prefix_evpn.route_type == 5) {
14403 char local_buf[PREFIX_STRLEN];
3714a385 14404 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14405 struct prefix_evpn *)p)
14406 ? AF_INET
14407 : AF_INET6;
3714a385 14408 inet_ntop(family,
14409 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14410 local_buf, PREFIX_STRLEN);
772270f3
QY
14411 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14412 p->u.prefix_evpn.prefix_addr
14413 .ip_prefix_length);
197cb530
PG
14414 } else {
14415 prefix2str(p, buf, sizeof(buf));
14416 }
ea47320b 14417
a4d82a8a
PZ
14418 if (bgp_static->gatewayIp.family == AF_INET
14419 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14420 inet_ntop(bgp_static->gatewayIp.family,
14421 &bgp_static->gatewayIp.u.prefix, buf2,
14422 sizeof(buf2));
ea47320b 14423 vty_out(vty,
7bcc8dac 14424 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14425 buf, rdbuf,
14426 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14427 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14428 macrouter);
14429
0a22ddfb 14430 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14431 }
14432 }
3da6fcd5
PG
14433}
14434
718e3744 14435/* Configuration of static route announcement and aggregate
14436 information. */
2b791107
DL
14437void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14438 safi_t safi)
d62a17ae 14439{
9bcb3eef 14440 struct bgp_dest *dest;
b54892e0 14441 const struct prefix *p;
d62a17ae 14442 struct bgp_static *bgp_static;
14443 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14444
2b791107
DL
14445 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14446 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14447 return;
14448 }
d62a17ae 14449
2b791107
DL
14450 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14451 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14452 return;
14453 }
d62a17ae 14454
14455 /* Network configuration. */
9bcb3eef
DS
14456 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14457 dest = bgp_route_next(dest)) {
14458 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14459 if (bgp_static == NULL)
ea47320b 14460 continue;
d62a17ae 14461
9bcb3eef 14462 p = bgp_dest_get_prefix(dest);
d62a17ae 14463
8228a9a7 14464 vty_out(vty, " network %pFX", p);
d62a17ae 14465
ea47320b
DL
14466 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14467 vty_out(vty, " label-index %u",
14468 bgp_static->label_index);
d62a17ae 14469
ea47320b
DL
14470 if (bgp_static->rmap.name)
14471 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14472
14473 if (bgp_static->backdoor)
14474 vty_out(vty, " backdoor");
718e3744 14475
ea47320b
DL
14476 vty_out(vty, "\n");
14477 }
14478
d62a17ae 14479 /* Aggregate-address configuration. */
9bcb3eef
DS
14480 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14481 dest = bgp_route_next(dest)) {
14482 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14483 if (bgp_aggregate == NULL)
ea47320b 14484 continue;
d62a17ae 14485
9bcb3eef 14486 p = bgp_dest_get_prefix(dest);
d62a17ae 14487
8228a9a7 14488 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14489
ea47320b
DL
14490 if (bgp_aggregate->as_set)
14491 vty_out(vty, " as-set");
d62a17ae 14492
ea47320b
DL
14493 if (bgp_aggregate->summary_only)
14494 vty_out(vty, " summary-only");
718e3744 14495
20894f50
DA
14496 if (bgp_aggregate->rmap.name)
14497 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14498
229757f1
DA
14499 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14500 vty_out(vty, " origin %s",
14501 bgp_origin2str(bgp_aggregate->origin));
14502
6aabb15d
RZ
14503 if (bgp_aggregate->match_med)
14504 vty_out(vty, " matching-MED-only");
14505
365ab2e7
RZ
14506 if (bgp_aggregate->suppress_map_name)
14507 vty_out(vty, " suppress-map %s",
14508 bgp_aggregate->suppress_map_name);
14509
ea47320b
DL
14510 vty_out(vty, "\n");
14511 }
d62a17ae 14512}
734b349e 14513
2b791107 14514void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14515 safi_t safi)
d62a17ae 14516{
9bcb3eef 14517 struct bgp_dest *dest;
d62a17ae 14518 struct bgp_distance *bdistance;
14519
14520 /* Distance configuration. */
14521 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14522 && bgp->distance_local[afi][safi]
14523 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14524 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14525 || bgp->distance_local[afi][safi]
14526 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14527 vty_out(vty, " distance bgp %d %d %d\n",
14528 bgp->distance_ebgp[afi][safi],
14529 bgp->distance_ibgp[afi][safi],
14530 bgp->distance_local[afi][safi]);
14531 }
734b349e 14532
9bcb3eef
DS
14533 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14534 dest = bgp_route_next(dest)) {
14535 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14536 if (bdistance != NULL)
56ca3b5b 14537 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14538 bdistance->distance, dest,
d62a17ae 14539 bdistance->access_list ? bdistance->access_list
14540 : "");
ca2e160d 14541 }
718e3744 14542}
14543
14544/* Allocate routing table structure and install commands. */
d62a17ae 14545void bgp_route_init(void)
14546{
14547 afi_t afi;
14548 safi_t safi;
14549
14550 /* Init BGP distance table. */
05c7a1cc 14551 FOREACH_AFI_SAFI (afi, safi)
960035b2 14552 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14553
14554 /* IPv4 BGP commands. */
14555 install_element(BGP_NODE, &bgp_table_map_cmd);
14556 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14557 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14558
554b3b10 14559 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14560
14561 /* IPv4 unicast configuration. */
14562 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14563 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14564 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14565
554b3b10 14566 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14567
14568 /* IPv4 multicast configuration. */
14569 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14570 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14571 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14572 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14573
14574 /* IPv4 labeled-unicast configuration. */
fb985e0c 14575 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14576 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14577
d62a17ae 14578 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14579 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14580 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14581 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14582 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14583 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14584 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14585 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14586
14587 install_element(VIEW_NODE,
14588 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14589 install_element(VIEW_NODE,
14590 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14591 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14592 install_element(VIEW_NODE,
14593 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14594#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14595 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14596#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14597 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14598 install_element(VIEW_NODE,
44c69747 14599 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14600
d62a17ae 14601 /* BGP dampening clear commands */
14602 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14603 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14604
d62a17ae 14605 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14606 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14607
14608 /* prefix count */
14609 install_element(ENABLE_NODE,
14610 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14611#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14612 install_element(ENABLE_NODE,
14613 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14614#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14615
d62a17ae 14616 /* New config IPv6 BGP commands. */
14617 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14618 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14619 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14620
554b3b10 14621 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14622
14623 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14624
fb985e0c
DA
14625 /* IPv6 labeled unicast address family. */
14626 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14627 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14628
d62a17ae 14629 install_element(BGP_NODE, &bgp_distance_cmd);
14630 install_element(BGP_NODE, &no_bgp_distance_cmd);
14631 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14632 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14633 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14634 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14635 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14636 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14637 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14638 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14639 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14640 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14641 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14642 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14643 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14644
ef5f4b23 14645 /* BGP dampening */
d9ce5113
CS
14646 install_element(BGP_NODE, &bgp_dampening_cmd);
14647 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14648 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14649 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14650 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14651 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14652 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14653
14654 /* Large Communities */
14655 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14656 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14657
14658 /* show bgp ipv4 flowspec detailed */
14659 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14660
2a0e69ae 14661 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14662 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14663}
14664
14665void bgp_route_finish(void)
14666{
14667 afi_t afi;
14668 safi_t safi;
14669
05c7a1cc
QY
14670 FOREACH_AFI_SAFI (afi, safi) {
14671 bgp_table_unlock(bgp_distance_table[afi][safi]);
14672 bgp_distance_table[afi][safi] = NULL;
14673 }
228da428 14674}